summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 8431c4e)
raw | patch | inline | side by side (parent: 8431c4e)
author | Junio C Hamano <junkio@cox.net> | |
Thu, 15 Dec 2005 20:54:00 +0000 (12:54 -0800) | ||
committer | Junio C Hamano <junkio@cox.net> | |
Thu, 15 Dec 2005 20:54:00 +0000 (12:54 -0800) |
When .git/refs/heads/frotz and .git/refs/tags/frotz existed, and
the object name stored in .git/refs/heads/frotz were corrupt, we
ended up picking tags/frotz without complaining. Worse yet, if
the corrupt .git/refs/heads/frotz was more than 40 bytes and
began with hexadecimal characters, it silently overwritten the
initial part of the returned result.
This commit adds a couple of tests to demonstrate these cases,
with a fix.
Signed-off-by: Junio C Hamano <junkio@cox.net>
the object name stored in .git/refs/heads/frotz were corrupt, we
ended up picking tags/frotz without complaining. Worse yet, if
the corrupt .git/refs/heads/frotz was more than 40 bytes and
began with hexadecimal characters, it silently overwritten the
initial part of the returned result.
This commit adds a couple of tests to demonstrate these cases,
with a fix.
Signed-off-by: Junio C Hamano <junkio@cox.net>
sha1_name.c | patch | blob | history | |
t/t0000-basic.sh | patch | blob | history | |
t/test-lib.sh | patch | blob | history |
diff --git a/sha1_name.c b/sha1_name.c
index faac158b16ca978914696ed5d2801770a122cce2..bf8f0f0e1feef55ba6be764f60815d15036efa4e 100644 (file)
--- a/sha1_name.c
+++ b/sha1_name.c
return NULL;
}
-static int ambiguous_path(const char *path)
+static int ambiguous_path(const char *path, int len)
{
int slash = 1;
+ int cnt;
- for (;;) {
+ for (cnt = 0; cnt < len; cnt++) {
switch (*path++) {
case '\0':
break;
}
return slash;
}
+ return slash;
}
static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
return 0;
/* Accept only unambiguous ref paths. */
- if (ambiguous_path(str))
+ if (ambiguous_path(str, len))
return -1;
for (p = prefix; *p; p++) {
char *pathname = git_path("%s/%.*s", *p, len, str);
+
if (!read_ref(pathname, sha1)) {
/* Must be unique; i.e. when heads/foo and
* tags/foo are both present, reject "foo".
- * Note that read_ref() eventually calls
- * get_sha1_hex() which can smudge initial
- * part of the buffer even if what is read
- * is found to be invalid halfway.
*/
if (1 < found++)
return -1;
}
+
+ /* We want to allow .git/description file and
+ * "description" branch to exist at the same time.
+ * "git-rev-parse description" should silently skip
+ * .git/description file as a candidate for
+ * get_sha1(). However, having garbage file anywhere
+ * under refs/ is not OK, and we would not have caught
+ * ambiguous heads and tags with the above test.
+ */
+ else if (**p && !access(pathname, F_OK)) {
+ /* Garbage exists under .git/refs */
+ return error("garbage ref found '%s'", pathname);
+ }
}
- if (found == 1)
+ switch (found) {
+ case 0:
+ return -1;
+ case 1:
return 0;
- return -1;
+ default:
+ return error("ambiguous refname '%.*s'", len, str);
+ }
}
static int get_sha1_1(const char *name, int len, unsigned char *sha1);
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index bc3e711a525f164f21132438d4d4e12e3dc10698..ffa723ea8bab577fa8443bf9c3b96a01df10434c 100755 (executable)
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
'no diff after checkout and git-update-index --refresh.' \
'git-diff-files >current && cmp -s current /dev/null'
+
+# extended sha1 parsing and ambiguity resolution
+
+GIT_AUTHOR_DATE='1995-01-29T16:00:00 -0800'
+GIT_AUTHOR_EMAIL=a.u.thor@example.com
+GIT_AUTHOR_NAME='A U Thor'
+GIT_COMMITTER_DATE='1995-01-29T16:00:00 -0800'
+GIT_COMMITTER_EMAIL=c.o.mmitter@example.com
+GIT_COMMITTER_NAME='C O Mmitter'
+export GIT_AUTHOR_DATE
+export GIT_AUTHOR_EMAIL
+export GIT_AUTHOR_NAME
+export GIT_COMMITTER_DATE
+export GIT_COMMITTER_EMAIL
+export GIT_COMMITTER_NAME
+
+test_expect_success \
+ 'initial commit.' \
+ 'commit=$(echo Initial commit | git-commit-tree $tree) &&
+ echo "$commit" >.git/refs/heads/master &&
+ git-ls-tree HEAD &&
+ test "$commit" = 51a092e9ef6cbbe66d258acd17599d3f80be6162'
+
+test_expect_success \
+ 'Ambiguous' \
+ 'echo "$commit" >.git/refs/heads/nasty &&
+ echo "$commit" >.git/refs/tags/nasty &&
+ if git-rev-parse --verify nasty
+ then
+ echo "should have barfed"
+ false
+ else
+ :
+ fi &&
+ # names directly underneath .git/ should not interfere
+ echo "$commit" >.git/refs/heads/description &&
+ git-rev-parse --verify description &&
+ # broken object name
+ echo fffffffffffffffffffffffffffffffffffffffg \
+ >.git/refs/heads/nasty &&
+ if git-rev-parse --verify nasty
+ then
+ echo "should have barfed"
+ false
+ else
+ :
+ fi'
+
test_done
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 2819bef1c4a80954be121bde3c44fce9221fcdfa..a97d259e26bc269c8f370f1d3bfa82e7d6cb9831 100755 (executable)
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
unset GIT_AUTHOR_DATE
unset GIT_AUTHOR_EMAIL
unset GIT_AUTHOR_NAME
+unset GIT_COMMITTER_DATE
unset GIT_COMMITTER_EMAIL
unset GIT_COMMITTER_NAME
unset GIT_DIFF_OPTS