git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 2/3] fast-import: add a check for tree delta base sha1

From
Dmitry Ivankov <divanorama@gmail.com>
Date
Aug 12, 2011, 10:32 UTC
Message-ID
<1313145170-24471-3-git-send-email-divanorama@gmail.com>
In-Reply-To
<1313145170-24471-1-git-send-email-divanorama@gmail.com>

fast-import is able to write imported tree objects in delta format. It holds a tree structure in memory where each tree entry may have a delta base sha1 assigned. When delta base data is needed it is reconstructed from this in-memory structure. Though sometimes the delta base data doesn't match the delta base sha1 so wrong or even corrupt pack is produced.

To create a small easily reproducible test, add an excessive check for delta base sha1. It's not likely that computing sha1 for each tree delta base costs us much.

Signed-off-by: Dmitry Ivankov <divanorama@gmail.com>
---
 fast-import.c          |   20 +++++++++++++++-----
 t/t9300-fast-import.sh |   38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 5 deletions(-)
diff --git a/fast-import.c b/fast-import.c
index d0f8580..8196d1b 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1455,12 +1455,22 @@ static void store_tree(struct tree_entry *root)
 			store_tree(t->entries[i]);
 	}
 
-	le = find_object(root->versions[0].sha1);
-	if (S_ISDIR(root->versions[0].mode) && le && le->pack_id == pack_id) {
+	if (!is_null_sha1(root->versions[0].sha1)
+					&& S_ISDIR(root->versions[0].mode)) {
+		unsigned char old_tree_sha1[20];
 		mktree(t, 0, &old_tree);
-		lo.data = old_tree;
-		lo.offset = le->idx.offset;
-		lo.depth = t->delta_depth;
+		prepare_object_hash(OBJ_TREE, &old_tree,
+						NULL, NULL, old_tree_sha1);
+
+		if (hashcmp(old_tree_sha1, root->versions[0].sha1))
+			die("internal tree delta base sha1 mismatch");
+
+		le = find_object(root->versions[0].sha1);
+		if (le && le->pack_id == pack_id) {
+			lo.data = old_tree;
+			lo.offset = le->idx.offset;
+			lo.depth = t->delta_depth;
+		}
 	}
 
 	mktree(t, 1, &new_tree);
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index f256475..c70e489 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -734,6 +734,44 @@ test_expect_success \
 	 git diff-tree --abbrev --raw L^ L >output &&
 	 test_cmp expect output'
 
+cat >input <<INPUT_END
+blob
+mark :1
+data <<EOF
+the data
+EOF
+
+commit refs/heads/L2
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+init L2
+COMMIT
+
+M 644 :1 a/b/c
+M 644 :1 a/b/d
+M 644 :1 a/e/f
+INPUT_END
+
+cat >input2 <<INPUT_END
+commit refs/heads/L2
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+update L2
+COMMIT
+from refs/heads/L2^0
+M 040000 @A g
+M 040000 @E g/b
+M 040000 @E g/b/h
+INPUT_END
+
+test_expect_failure \
+    'L: verify internal tree delta base' \
+	'git fast-import <input &&
+	A=$(git ls-tree L2 a | tr " " "\t" | cut -f 3) &&
+	E=$(git ls-tree L2 a/e | tr " " "\t" | cut -f 3) &&
+	cat input2 | sed -e "s/@A/$A/" -e "s/@E/$E/" >input &&
+	git fast-import <input'
+
 ###
 ### series M
 ###
-- 
1.7.3.4
Previous: Dmitry IvankovNext: Jonathan Nieder
Message 3 of 14 in “fix data corruption in fast-import”
  1. 0/3 fix data corruption in fast-importDmitry Ivankov, Aug 12, 2011
  2. 1/3 fast-import: extract object preparation functionDmitry Ivankov, Aug 12, 2011
  3. 2/3 fast-import: add a check for tree delta base sha1Dmitry Ivankov, Aug 12, 2011
  4. Jonathan NiederAug 13, 2011
  5. 3/3 fast-import: prevent producing bad deltaDmitry Ivankov, Aug 12, 2011
  6. 0/2 fix data corruption in fast-importDmitry Ivankov, Aug 14, 2011
  7. 1/2 fast-import: add a test for tree delta base corruptionDmitry Ivankov, Aug 14, 2011
  8. 2/2 fast-import: prevent producing bad deltaDmitry Ivankov, Aug 14, 2011
  9. fast-import: do not write bad delta for replaced subtreesJonathan Nieder, Aug 20, 2011
  10. Andreas SchwabAug 20, 2011
  11. Jonathan NiederAug 20, 2011
  12. fast-import: do not write bad delta for replaced subtreesDmitry Ivankov, Aug 20, 2011
  13. Jonathan NiederAug 20, 2011
  14. Dmitry IvankovAug 20, 2011

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.