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

Re: [PATCH 0/1] quote: quote space

From
Junio C Hamano <gitster@pobox.com>
Date
Mar 19, 2024, 22:56 UTC
Message-ID
<xmqqfrwlltjn.fsf@gitster.g>
In-Reply-To
<xmqqttl2qml9.fsf@gitster.g>
Junio C Hamano <gitster@pobox.com> writes:
> That is an interesting corner case.  You should make this into a set
> of new tests somewhere in t/; I suspect this only will "break" for
> creation and deletion but not modification in-place or renaming (and
> that should also be in the tests).

It turns out that this is even more unintereseting than I hoped; it happens ONLY when there is no contents shown at all in the patch, and the patch is about creation or deletion of a path. Mode change without touching any contents may also trigger the same breakage.

Here is a fix, which seems not to break any existing tests.
----- >8 --------- >8 --------- >8 --------- >8 -----
Subject: [PATCH] apply: parse names out of "diff --git" more carefully

"git apply" uses the pathname parsed out of the "diff --git" header to decide which path is being patched, but this is used only when there is no other names available in the patch. When there is any content change (like we can see in this patch, that modifies the contents of "apply.c") or rename (which comes with "rename from" and "rename to" extended diff headers), the names are available without having to parse this header.

When we do need to parse this header, a special care needs to be taken, as the name of a directory or a file can have a SP in it so it is not like "find a space, and take everything before the space and that is the preimage filename, everything after the space is the postimage filename". We have a loop that stops at every SP on the "diff --git a/dir/file b/dir/foo" line and see if that SP is the right place that separates such a pair of names.

Unfortunately, this loop can terminate prematurely when a crafted directory name ended with a SP. The next pathname component after that SP (i.e. the beginning of the possible postimage filename) will be a slash, and instead of rejecting that position as the valid separation point between pre- and post-image filenames and keep looping, we stopped processing right there.

The fix is simple. Instead of stopping and giving up, keep going on when we see such a condition.

Reported-by: Han Young <hanyang.tony@bytedance.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 apply.c                |  9 ++++++++-
 t/t4126-apply-empty.sh | 22 ++++++++++++++++++++++
 2 files changed, 30 insertions(+), 1 deletion(-)
diff --git c/apply.c w/apply.c
index 432837a674..e311013bc4 100644
--- c/apply.c
+++ w/apply.c
@@ -1292,8 +1292,15 @@ static char *git_header_name(int p_value,
 				return NULL; /* no postimage name */
 			second = skip_tree_prefix(p_value, name + len + 1,
 						  line_len - (len + 1));
+			/*
+			 * If we are at the SP at the end of a directory,
+			 * skip_tree_prefix() may return NULL as that makes
+			 * it appears as if we have an absolute path.
+			 * Keep going to find another SP.
+			 */
 			if (!second)
-				return NULL;
+				continue;
+
 			/*
 			 * Does len bytes starting at "name" and "second"
 			 * (that are separated by one HT or SP we just
diff --git c/t/t4126-apply-empty.sh w/t/t4126-apply-empty.sh
index ece9fae207..eaf0c5304a 100755
--- c/t/t4126-apply-empty.sh
+++ w/t/t4126-apply-empty.sh
@@ -66,4 +66,26 @@ test_expect_success 'apply --index create' '
 	git diff --exit-code
 '
 
+test_expect_success 'apply with no-contents and a funny pathname' '
+	mkdir "funny " &&
+	>"funny /empty" &&
+	git add "funny /empty" &&
+	git diff HEAD "funny /" >sample.patch &&
+	git diff -R HEAD "funny /" >elpmas.patch &&
+	git reset --hard &&
+	rm -fr "funny " &&
+
+	git apply --stat --check --apply sample.patch &&
+	test_must_be_empty "funny /empty" &&
+
+	git apply --stat --check --apply elpmas.patch &&
+	test_path_is_missing "funny /empty" &&
+
+	git apply -R --stat --check --apply elpmas.patch &&
+	test_must_be_empty "funny /empty" &&
+
+	git apply -R --stat --check --apply sample.patch &&
+	test_path_is_missing "funny /empty"
+'
+
 test_done
Previous: Junio C HamanoNext: Junio C Hamano
Message 5 of 26 in “quote: quote space”
  1. 0/1 quote: quote spaceHan Young, Mar 19, 2024
  2. 1/1 quote: quote spaceHan Young, Mar 19, 2024
  3. Kristoffer HaugsbakkMar 19, 2024
  4. Junio C HamanoMar 19, 2024
  5. Junio C HamanoMar 19, 2024
  6. Junio C HamanoMar 26, 2024
  7. Jeff KingMar 27, 2024
  8. Junio C HamanoMar 27, 2024
  9. Junio C HamanoMar 27, 2024
  10. Jeff KingMar 28, 2024
  11. Jeff KingMar 28, 2024
  12. Eric SunshineMar 28, 2024
  13. Junio C HamanoMar 28, 2024
  14. t4126: make sure a directory with SP at the end is usableJunio C Hamano, Mar 28, 2024
  15. Junio C HamanoMar 29, 2024
  16. t4126: fix "funny directory name" test on Windows (again)Junio C Hamano, Mar 29, 2024
  17. Jeff KingMar 29, 2024
  18. t4126: fix "funny directory name" test on Windows (again)Junio C Hamano, Mar 29, 2024
  19. Jeff KingMar 29, 2024
  20. Jeff KingMar 29, 2024
  21. Junio C HamanoMar 29, 2024
  22. Johannes SchindelinApr 27, 2024
  23. Junio C HamanoApr 27, 2024
  24. Junio C HamanoMar 28, 2024
  25. Jeff KingMar 28, 2024
  26. Junio C HamanoMar 28, 2024

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.