X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=refs.c;h=97506a4ebdfbd164abad6be76d7160db171d9148;hb=0f8fdc3958ad0cb7c740b76189f98307eebcd64b;hp=2aac90ca54f3fe207d7b05dda56f0f04badf460e;hpb=8098a178b26dc7a158d129a092a5b78da6d12b72;p=git.git diff --git a/refs.c b/refs.c index 2aac90ca..97506a4e 100644 --- a/refs.c +++ b/refs.c @@ -2,7 +2,6 @@ #include "cache.h" #include -#include /* We allow "recursive" symbolic refs. Only within reason, though */ #define MAXDEPTH 5 @@ -46,7 +45,7 @@ int validate_symref(const char *path) len -= 4; while (len && isspace(*buf)) buf++, len--; - if (len >= 5 && !memcmp("refs/", buffer, 5)) + if (len >= 5 && !memcmp("refs/", buf, 5)) return 0; return -1; } @@ -335,17 +334,54 @@ int write_ref_sha1(const char *ref, int fd, const unsigned char *sha1) return retval; } +/* + * Make sure "ref" is something reasonable to have under ".git/refs/"; + * We do not like it if: + * + * - any path component of it begins with ".", or + * - it has double dots "..", or + * - it has ASCII control character, "~", "^", ":" or SP, anywhere, or + * - it ends with a "/". + */ + +static inline int bad_ref_char(int ch) +{ + return (((unsigned) ch) <= ' ' || + ch == '~' || ch == '^' || ch == ':'); +} + int check_ref_format(const char *ref) { - char *middle; - if (ref[0] == '.' || ref[0] == '/') - return -1; - middle = strchr(ref, '/'); - if (!middle || !middle[1]) - return -1; - if (strchr(middle + 1, '/')) - return -1; - return 0; + int ch, level; + const char *cp = ref; + + level = 0; + while (1) { + while ((ch = *cp++) == '/') + ; /* tolerate duplicated slashes */ + if (!ch) + return -1; /* should not end with slashes */ + + /* we are at the beginning of the path component */ + if (ch == '.' || bad_ref_char(ch)) + return -1; + + /* scan the rest of the path component */ + while ((ch = *cp++) != 0) { + if (bad_ref_char(ch)) + return -1; + if (ch == '/') + break; + if (ch == '.' && *cp == '.') + return -1; + } + level++; + if (!ch) { + if (level < 2) + return -1; /* at least of form "heads/blah" */ + return 0; + } + } } int write_ref_sha1_unlocked(const char *ref, const unsigned char *sha1)