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

Re: [PATCH] apply: refuse touching a file beyond symlink

From
Jeff King <peff@peff.net>
Date
Jan 30, 2015, 18:11 UTC
Message-ID
<20150130181153.GA25513@peff.net>
In-Reply-To
<xmqqa911e2ot.fsf_-_@gitster.dls.corp.google.com>
On Thu, Jan 29, 2015 at 12:45:22PM -0800, Junio C Hamano wrote:
Show 12 quoted lines
> +static int path_is_beyond_symlink(const char *name_)
> +{
> +	struct strbuf name = STRBUF_INIT;
> +
> +	strbuf_addstr(&name, name_);
> +	do {
> +		struct patch *previous;
> +
> +		while (--name.len && name.buf[name.len] != '/')
> +			; /* scan backwards */
> +		if (!name.len)
> +			break;

I imagine it is impossible here for "name_" to be initially empty, but it would make the backwards-scan loop go quite badly. Worth a comment or an assert()?

Show 25 quoted lines
> +		name.buf[name.len] = '\0';
> +		previous = in_fn_table(name.buf);
> +		if (previous) {
> +			if (!was_deleted(previous) &&
> +			    !to_be_deleted(previous) &&
> +			    previous->new_mode &&
> +			    S_ISLNK(previous->new_mode))
> +				goto symlink_found;
> +		} else if (check_index) {
> +			int pos = cache_name_pos(name.buf, name.len);
> +			if (0 <= pos &&
> +			    S_ISLNK(active_cache[pos]->ce_mode))
> +				goto symlink_found;
> +		} else {
> +			struct stat st;
> +			if (!lstat(name.buf, &st) && S_ISLNK(st.st_mode))
> +				goto symlink_found;
> +		}
> +	} while (1);
> +
> +	strbuf_release(&name);
> +	return 0;
> +symlink_found:
> +	strbuf_release(&name);
> +	return 1;

Style nit, but might this be easier to follow the logic without the gotos, by putting the setup and cleanup in a wrapper function and returning directly from the main logic?

  static int path_is_beyond_symlink(const char *name)
  {
	struct strbuf buf = STRBUF_INIT;
	int ret;
	strbuf_addstr(&buf, name);
	ret = path_is_beyond_symlink_1(name);
	strbuf_release(&buf);
	return ret;
  }
I can live with it either way, though.
> +	if (!patch->is_delete && path_is_beyond_symlink(patch->new_name))
> +		return error(_("affected file '%s' is beyond a symbolic link"),
> +			     patch->new_name);

Why does this not kick in when deleting a file? If it is not OK to add across a symlink, why is it OK to delete? IOW, why should this test fail:

diff --git a/t/t4122-apply-symlink-inside.sh b/t/t4122-apply-symlink-inside.sh
index 0a8de4a..f03b604 100755
--- a/t/t4122-apply-symlink-inside.sh
+++ b/t/t4122-apply-symlink-inside.sh
@@ -64,6 +64,7 @@ test_expect_success SYMLINKS 'do not follow symbolic link (setup)' '
 	>arch/x86_64/dir/file &&
 	git add arch/x86_64/dir/file &&
 	git diff HEAD >add_file.patch &&
+	git diff -R HEAD >del_file.patch &&
 	git reset --hard &&
 	rm -fr arch/x86_64/dir &&
 
@@ -111,7 +112,11 @@ test_expect_success SYMLINKS 'do not follow symbolic link (existing)' '
 
 	test_must_fail git apply --cached add_file.patch 2>error-ct-file &&
 	test_i18ngrep "beyond a symbolic link" error-ct-file &&
-	test_must_fail git ls-files --error-unmatch arch/i386/dir
+	test_must_fail git ls-files --error-unmatch arch/i386/dir &&
+
+	>arch/i386/dir/file &&
+	test_must_fail git apply del_file.patch &&
+	test_path_is_file arch/i386/dir/file
 '
 
 test_done

> +	test ! -e arch/x86_64/dir &&
> +	test ! -e arch/i386/dir/file &&

Minor nit: use test_path_is_missing here (and elsewhere in the added
tests).

-Peff
Previous: Christian CouderNext: Junio C Hamano
Message 23 of 35 in “patch-2.7.3 no longer applies relative symbolic link patches”
  1. Josh BoyerJan 26, 2015
  2. Josh BoyerJan 26, 2015
  3. Linus TorvaldsJan 26, 2015
  4. David KastrupJan 26, 2015
  5. Josh BoyerJan 26, 2015
  6. Linus TorvaldsJan 26, 2015
  7. Junio C HamanoJan 26, 2015
  8. Linus TorvaldsJan 26, 2015
  9. Andreas GruenbacherJan 27, 2015
  10. Andreas GruenbacherJan 31, 2015
  11. Josh BoyerJan 26, 2015
  12. Junio C HamanoJan 27, 2015
  13. Junio C HamanoJan 27, 2015
  14. Junio C HamanoJan 29, 2015
  15. Junio C HamanoJan 29, 2015
  16. apply: refuse touching a file beyond symlinkJunio C Hamano, Jan 29, 2015
  17. Stefan BellerJan 29, 2015
  18. 2/1 apply: reject input that touches outside $cwdJunio C Hamano, Jan 29, 2015
  19. Jeff KingJan 30, 2015
  20. Junio C HamanoJan 30, 2015
  21. Jeff KingJan 30, 2015
  22. Christian CouderJan 30, 2015
  23. Jeff KingJan 30, 2015
  24. Junio C HamanoJan 30, 2015
  25. Jeff KingJan 30, 2015
  26. Junio C HamanoJan 30, 2015
  27. Jeff KingJan 30, 2015
  28. Junio C HamanoJan 30, 2015
  29. Junio C HamanoJan 30, 2015
  30. Jeff KingJan 30, 2015
  31. Junio C HamanoJan 30, 2015
  32. Jeff KingJan 30, 2015
  33. Junio C HamanoJan 30, 2015
  34. Junio C HamanoJan 30, 2015
  35. Andreas GruenbacherJan 27, 2015

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.