fix a use-after-free in get_changed_paths() in got and tog Once the parent commit is closed the tree_id1 pointer is no longer valid, but the pointer was still being used. Make a deep copy to fix this issue.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
diff --git a/got/got.c b/got/got.c
index eead62c..71cc16e 100644
--- a/got/got.c
+++ b/got/got.c
@@ -3438,7 +3438,12 @@ get_changed_paths(struct got_pathlist_head *paths,
if (err)
return err;
- tree_id1 = got_object_commit_get_tree_id(pcommit);
+ tree_id1 = got_object_id_dup(
+ got_object_commit_get_tree_id(pcommit));
+ if (tree_id1 == NULL) {
+ got_object_commit_close(pcommit);
+ return got_error_from_errno("got_object_id_dup");
+ }
got_object_commit_close(pcommit);
}
@@ -3461,6 +3466,7 @@ done:
got_object_tree_close(tree1);
if (tree2)
got_object_tree_close(tree2);
+ free(tree_id1);
return err;
}
diff --git a/tog/tog.c b/tog/tog.c
index bc64c6a..c175ea3 100644
--- a/tog/tog.c
+++ b/tog/tog.c
@@ -3053,7 +3053,12 @@ get_changed_paths(struct got_pathlist_head *paths,
if (err)
return err;
- tree_id1 = got_object_commit_get_tree_id(pcommit);
+ tree_id1 = got_object_id_dup(
+ got_object_commit_get_tree_id(pcommit));
+ if (tree_id1 == NULL) {
+ got_object_commit_close(pcommit);
+ return got_error_from_errno("got_object_id_dup");
+ }
got_object_commit_close(pcommit);
}
@@ -3076,6 +3081,7 @@ done:
got_object_tree_close(tree1);
if (tree2)
got_object_tree_close(tree2);
+ free(tree_id1);
return err;
}