Skip to contentSkip to conversation

symbolic-ref: check format of given reference

PATCH In review Michael Schubert 3 participants 8 messages Jun 15, 2016

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 symbolic-ref: check format of given reference

Currently, it's possible to update HEAD with a nonsense reference since no strict validation is performed. Example:

	$ git symbolic-ref HEAD 'refs/heads/master
Quoted 3 lines

'

Fix this by checking the given reference with check_refname_format().

---

This was discussed earlier this year:

http://thread.gmane.org/gmane.comp.version-control.git/189715

What about pointing at non-existing references? Should this still be allowed?

Additionally, I had to reindent two lines to make git-am happy (indent with spaces).

 builtin/symbolic-ref.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
builtin/symbolic-ref.c +5 -3
index 801d62e..22362e0 100644
@@ -43,16 +43,18 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
 
 	git_config(git_default_config, NULL);
 	argc = parse_options(argc, argv, prefix, options,
-			     git_symbolic_ref_usage, 0);
-	if (msg &&!*msg)
+				git_symbolic_ref_usage, 0);
+	if (msg && !*msg)
 		die("Refusing to perform update with empty message");
 	switch (argc) {
 	case 1:
 		check_symref(argv[0], quiet);
 		break;
 	case 2:
+		if (check_refname_format(argv[1], 0))
+			die("No valid reference format: '%s'", argv[1]);
 		if (!strcmp(argv[0], "HEAD") &&
-		    prefixcmp(argv[1], "refs/"))
+			prefixcmp(argv[1], "refs/"))
 			die("Refusing to point HEAD outside of refs/");
 		create_symref(argv[0], argv[1], msg);
 		break;
Signature · 1 line
1.7.11.rc3.11.g7dba3f7.dirty
#1 lore raw
Quoted 6 lines · Michael Schubert

This was discussed earlier this year:

http://thread.gmane.org/gmane.comp.version-control.git/189715

What about pointing at non-existing references? Should this still be allowed?

How else would you reimplement "checkout --orphan" in your own Porcelain using symbolic-ref?

Quoted 3 lines

Additionally, I had to reindent two lines to make git-am happy (indent with spaces).

I doubt that it is needed; the '-' lines show runs of HT followed by fewer than 8 SP, which should not trigger "indent with spaces".

Quoted 29 lines
 builtin/symbolic-ref.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
builtin/symbolic-ref.c +5 -3
index 801d62e..22362e0 100644
@@ -43,16 +43,18 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
 
 	git_config(git_default_config, NULL);
 	argc = parse_options(argc, argv, prefix, options,
-			     git_symbolic_ref_usage, 0);
-	if (msg &&!*msg)
+				git_symbolic_ref_usage, 0);
+	if (msg && !*msg)
 		die("Refusing to perform update with empty message");
 	switch (argc) {
 	case 1:
 		check_symref(argv[0], quiet);
 		break;
 	case 2:
+		if (check_refname_format(argv[1], 0))
+			die("No valid reference format: '%s'", argv[1]);
 		if (!strcmp(argv[0], "HEAD") &&
-		    prefixcmp(argv[1], "refs/"))
+			prefixcmp(argv[1], "refs/"))
 			die("Refusing to point HEAD outside of refs/");
 		create_symref(argv[0], argv[1], msg);
 		break;
#2 lore raw
Quoted 11 lines · Junio C Hamano
Quoted 6 lines · Michael Schubert

This was discussed earlier this year:

http://thread.gmane.org/gmane.comp.version-control.git/189715

What about pointing at non-existing references? Should this still be allowed?

How else would you reimplement "checkout --orphan" in your own Porcelain using symbolic-ref?

Forgot about that.

Quoted 6 lines
Quoted 3 lines

Additionally, I had to reindent two lines to make git-am happy (indent with spaces).

I doubt that it is needed; the '-' lines show runs of HT followed by fewer than 8 SP, which should not trigger "indent with spaces".

I've only noticed because git-am was telling me when I tried to apply the patch.? Am I missing something?

#3 lore raw
Quoted 8 lines · Michael Schubert
Quoted 5 lines
Quoted 2 lines

Additionally, I had to reindent two lines to make git-am happy (indent with spaces).

I doubt that it is needed; the '-' lines show runs of HT followed by fewer than 8 SP, which should not trigger "indent with spaces".

I've only noticed because git-am was telling me when I tried to apply the patch.? Am I missing something?

Perhaps, but I cannot tell exactly what you are doing wrong.

If you didn't touch lines you did not have to in a way to break indentation and cause "indent with spaces", "am" would not have complained (it only looks at "+" lines).

Attached is a patch based on your patch but removes the unnecessary re-indentation part, and "git am" happily applies it to my tree without complaining. Does it apply for you (obviously to a revision without your patch) cleanly without complaint? Otherwise it could be that whitespace categories that are specified for the file in your local attributes file may be different from mine (i.e. an empty set).

-- >8 --
From: Michael Schubert <[email protected]>
Date: Sun, 17 Jun 2012 22:26:37 +0200
Subject: [PATCH] symbolic-ref: check format of given reference

Currently, it's possible to update HEAD with a nonsense reference since no strict validation is performed. Example:

	$ git symbolic-ref HEAD 'refs/heads/master
Quoted 3 lines

'

Fix this by checking the given reference with check_refname_format().

---
 builtin/symbolic-ref.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
builtin/symbolic-ref.c +3 -1
index 801d62e..a529541 100644
@@ -44,13 +44,15 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
 	git_config(git_default_config, NULL);
 	argc = parse_options(argc, argv, prefix, options,
 			     git_symbolic_ref_usage, 0);
-	if (msg &&!*msg)
+	if (msg && !*msg)
 		die("Refusing to perform update with empty message");
 	switch (argc) {
 	case 1:
 		check_symref(argv[0], quiet);
 		break;
 	case 2:
+		if (check_refname_format(argv[1], 0))
+			die("No valid reference format: '%s'", argv[1]);
 		if (!strcmp(argv[0], "HEAD") &&
 		    prefixcmp(argv[1], "refs/"))
 			die("Refusing to point HEAD outside of refs/");
Signature · 1 line
1.7.11
#4 lore raw
Quoted 11 lines · Junio C Hamano

From: Michael Schubert <[email protected]>
Date: Sun, 17 Jun 2012 22:26:37 +0200
Subject: [PATCH] symbolic-ref: check format of given reference

Currently, it's possible to update HEAD with a nonsense reference since no strict validation is performed. Example:

	$ git symbolic-ref HEAD 'refs/heads/master
Quoted 3 lines

'

It would be nice to add a new test or two to t1401. 1401.3 was already trying to catch a malformed reference with this test:

test_must_fail git symbolic-ref HEAD foo

and it did trigger thanks to the prefixcmp(argv[1], "refs/") test we already have. Probably something like

git symbolic-ref HEAD "refs/heads/.foo"
git symbolic-ref HEAD "refs/heads/-foo"

would be a good start.

To make the latter _correctly_ work requires a bit of work, though. We should make sure all the check_refname_format() callers pass the full path to a ref, get rid of ALLOW_ONELEVEL, and redo commits like 6348624 (disallow branch names that start with a hyphen, 2010-09-14) and 4f0accd (tag: disallow '-' as tag name, 2011-05-10).

For that matter, shouldn't symbolic-ref be forbidden to point outside refs/heads/, not just restricted in refs/ like the current code does?

#5 lore raw
Quoted 3 lines · Junio C Hamano

For that matter, shouldn't symbolic-ref be forbidden to point outside refs/heads/, not just restricted in refs/ like the current code does?

We tried that already but reverted it due to topgit. See:

commit e9cc02f0e41fd5d2f51e3c3f2b4f8cfa9e434432
Author: Jeff King <[email protected]>
Date: Fri Feb 13 13:26:09 2009 -0500

symbolic-ref: allow refs/<whatever> in HEAD

Commit afe5d3d5 introduced a safety valve to symbolic-ref to disallow installing an invalid HEAD. It was accompanied by b229d18a, which changed validate_headref to require that HEAD contain a pointer to refs/heads/ instead of just refs/. Therefore, the safety valve also checked for refs/heads/.

As it turns out, topgit is using refs/top-bases/ in HEAD, leading us to re-loosen (at least temporarily) the validate_headref check made in b229d18a. This patch does the corresponding loosening for the symbolic-ref safety valve, so that the two are in agreement once more.

-Peff

#6 lore raw
Quoted 20 lines · Jeff King
Quoted 3 lines · Junio C Hamano

For that matter, shouldn't symbolic-ref be forbidden to point outside refs/heads/, not just restricted in refs/ like the current code does?

We tried that already but reverted it due to topgit. See:

commit e9cc02f0e41fd5d2f51e3c3f2b4f8cfa9e434432
Author: Jeff King <[email protected]>
Date: Fri Feb 13 13:26:09 2009 -0500

symbolic-ref: allow refs/<whatever> in HEAD

Commit afe5d3d5 introduced a safety valve to symbolic-ref to disallow installing an invalid HEAD. It was accompanied by b229d18a, which changed validate_headref to require that HEAD contain a pointer to refs/heads/ instead of just refs/. Therefore, the safety valve also checked for refs/heads/.

Quoted 5 lines

As it turns out, topgit is using refs/top-bases/ in HEAD, leading us to re-loosen (at least temporarily) the validate_headref check made in b229d18a. This patch does the corresponding loosening for the symbolic-ref safety valve, so that the two are in agreement once more.

The "at least temporarily" in that commit message merited a little investigation. There was some discussion of changing topgit to record its information using a different scheme, but there was no clear outcome:

http://thread.gmane.org/gmane.comp.version-control.git/109581

So if somebody wanted to re-tighten this check, they would want to at least check topgit's current behavior, and see which versions of it we would be breaking. I tend to think it is not worth the effort.

-Peff

#7 lore raw
In reply to Junio C Hamano
Quoted 5 lines · Junio C Hamano
Quoted 3 lines · Michael Schubert
Quoted 3 lines
Quoted 2 lines

Additionally, I had to reindent two lines to make git-am happy (indent with spaces).

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

I doubt that it is needed; the '-' lines show runs of HT followed by fewer than 8 SP, which should not trigger "indent with spaces".

I've only noticed because git-am was telling me when I tried to apply the patch.? Am I missing something?

Perhaps, but I cannot tell exactly what you are doing wrong.

Thunderbird replaced the tabs (but did not do that before). Sorry for the noise.

Quoted 8 lines

If you didn't touch lines you did not have to in a way to break indentation and cause "indent with spaces", "am" would not have complained (it only looks at "+" lines).

Attached is a patch based on your patch but removes the unnecessary re-indentation part, and "git am" happily applies it to my tree without complaining. Does it apply for you (obviously to a revision without your patch) cleanly without complaint?

Works, Thanks.

Quoted 43 lines

-- >8 --
From: Michael Schubert <[email protected]>
Date: Sun, 17 Jun 2012 22:26:37 +0200
Subject: [PATCH] symbolic-ref: check format of given reference

Currently, it's possible to update HEAD with a nonsense reference since no strict validation is performed. Example:

	$ git symbolic-ref HEAD 'refs/heads/master
Quoted 3 lines

'

Fix this by checking the given reference with check_refname_format().

---
 builtin/symbolic-ref.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
builtin/symbolic-ref.c +3 -1
index 801d62e..a529541 100644
@@ -44,13 +44,15 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
 	git_config(git_default_config, NULL);
 	argc = parse_options(argc, argv, prefix, options,
 			     git_symbolic_ref_usage, 0);
-	if (msg &&!*msg)
+	if (msg && !*msg)
 		die("Refusing to perform update with empty message");
 	switch (argc) {
 	case 1:
 		check_symref(argv[0], quiet);
 		break;
 	case 2:
+		if (check_refname_format(argv[1], 0))
+			die("No valid reference format: '%s'", argv[1]);
 		if (!strcmp(argv[0], "HEAD") &&
 		    prefixcmp(argv[1], "refs/"))
 			die("Refusing to point HEAD outside of refs/");