Junio C Hamano [off-list ref] writes:
quoted
I think we've discussed tightening it a few years ago already.
HEAD, MERGE_HEAD, FETCH_HEAD, etc. all are "^[_A-Z]*$" and it may even be
a good idea to insist "^[_A-Z]*HEAD$" or even "^([A-Z][A-Z]*_)?HEAD$".
Perhaps like this? Only compile tested...
Not quite. There are at least three bugs in the patch.
- Some subsystems use random refnames like NOTES_MERGE_PARTIAL that would
not match "^([A-Z][A-Z]*_)?HEAD$". The rule needs to be relaxed;
- dwim_ref() can be fed "refs/heads/master" and is expected to dwim it to
the master branch.
- These codepaths get pointer+length so that it can be told to parse only
the first 4 bytes in "HEAD:$path".
-- >8 --
Subject: [PATCH] Restrict ref-like names immediately below $GIT_DIR
We have always dwimmed the user input $string into a ref by first looking
directly inside $GIT_DIR, and then in $GIT_DIR/refs, $GIT_DIR/refs/tags,
etc., and that is what made
git log HEAD..MERGE_HEAD
work correctly. This however means that
git rev-parse config
git log index
would look at $GIT_DIR/config and $GIT_DIR/index and see if they are valid
refs.
To reduce confusion, let's not dwim a path immediately below $GIT_DIR that
is not all-caps.
Signed-off-by: Junio C Hamano <redacted>
---
sha1_name.c | 23 +++++++++++++++++++++++
1 files changed, 23 insertions(+), 0 deletions(-)
diff --git a/sha1_name.c b/sha1_name.c
index 143fd97..5eb19c2 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -261,6 +261,25 @@ static char *substitute_branch_name(const char **string, int *len)
return NULL;
}
+static int ok_at_root_level(const char *str, int len)
+{
+ int seen_non_root_char = 0;
+
+ while (len--) {
+ char ch = *str++;
+
+ if (ch == '/')
+ return 1;
+ /*
+ * Only accept likes of .git/HEAD, .git/MERGE_HEAD at
+ * the root level as a ref.
+ */
+ if (ch != '_' && (ch < 'A' || 'Z' < ch))
+ seen_non_root_char = 1;
+ }
+ return !seen_non_root_char;
+}
+
int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
{
char *last_branch = substitute_branch_name(&str, &len);@@ -274,6 +293,8 @@ int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
unsigned char *this_result;
int flag;
+ if (p == ref_rev_parse_rules && !ok_at_root_level(str, len))
+ continue;
this_result = refs_found ? sha1_from_ref : sha1;
mksnpath(fullref, sizeof(fullref), *p, len, str);
r = resolve_ref(fullref, this_result, 1, &flag);
@@ -302,6 +323,8 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
char path[PATH_MAX];
const char *ref, *it;
+ if (p == ref_rev_parse_rules && !ok_at_root_level(str, len))
+ continue;
mksnpath(path, sizeof(path), *p, len, str);
ref = resolve_ref(path, hash, 1, NULL);
if (!ref)