Commit aa8b5dd032c8cba930e5be67a90069a95e0001b8

Stefan Sperling 2021-08-01T12:59:32

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.

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;
 }