diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2014-07-25 17:43:59 +0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2014-07-30 12:54:43 -0700 |
commit | 98b23ccb48be9f50146ca9df5aa9b88369a4cad6 (patch) | |
tree | 1ecb6fa29bafb43bc7a8715e4547cda947748034 | |
parent | 6fba9aa4719a8c4568cab321b17f7675e26e6e48 (diff) | |
download | git-nd/unify-ref-parse.tar.gz |
refs.c: rewrite resolve_gitlink_ref() to use parse_ref()nd/unify-ref-parse
resolve_gitlink_ref_recursive() is less strict than the old
resolve_ref_unsafe() (which is now parse_ref()). It also has another
random limit 128 bytes for symrefs.
This brings MAXREFLEN check to resolve_ref* family. It looks like an
arbitrary limit though (added in 0ebde32 (Add 'resolve_gitlink_ref()'
helper function - 2007-04-09)
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | refs.c | 68 |
1 files changed, 26 insertions, 42 deletions
@@ -1237,48 +1237,11 @@ static int resolve_gitlink_packed_ref(struct ref_cache *refs, return 0; } -static int resolve_gitlink_ref_recursive(struct ref_cache *refs, - const char *refname, unsigned char *sha1, - int recursion) -{ - int fd, len; - char buffer[128], *p; - char *path; - - if (recursion > MAXDEPTH || strlen(refname) > MAXREFLEN) - return -1; - path = *refs->name - ? git_path_submodule(refs->name, "%s", refname) - : git_path("%s", refname); - fd = open(path, O_RDONLY); - if (fd < 0) - return resolve_gitlink_packed_ref(refs, refname, sha1); - - len = read(fd, buffer, sizeof(buffer)-1); - close(fd); - if (len < 0) - return -1; - while (len && isspace(buffer[len-1])) - len--; - buffer[len] = 0; - - /* Was it a detached head or an old-fashioned symlink? */ - if (!get_sha1_hex(buffer, sha1)) - return 0; - - /* Symref? */ - if (strncmp(buffer, "ref:", 4)) - return -1; - p = buffer + 4; - while (isspace(*p)) - p++; - - return resolve_gitlink_ref_recursive(refs, p, sha1, recursion+1); -} - int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sha1) { - int len = strlen(path), retval; + struct strbuf result = STRBUF_INIT; + int len = strlen(path), retval = 0; + int depth = MAXDEPTH; char *submodule; struct ref_cache *refs; @@ -1290,8 +1253,24 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sh refs = get_ref_cache(submodule); free(submodule); - retval = resolve_gitlink_ref_recursive(refs, refname, sha1, 0); - return retval; + strbuf_addstr(&result, refname); + while (!retval) { + if (--depth < 0) { + errno = ELOOP; + retval = -1; + break; + } + path = *refs->name + ? git_path_submodule(refs->name, "%s", result.buf) + : git_path("%s", result.buf); + retval = parse_ref(path, &result, sha1, NULL); + if (retval == -2) { + retval = resolve_gitlink_packed_ref(refs, result.buf, sha1); + retval = retval ? -1 : 1; + } + } + strbuf_release(&result); + return retval > 0 ? 0 : -1; } /* @@ -1341,6 +1320,11 @@ int parse_ref(const char *path, struct strbuf *ref, struct stat st; const char *buf; + if (ref->len > MAXREFLEN) { + errno = ENAMETOOLONG; + return -1; + } + /* * We might have to loop back here to avoid a race condition: * first we lstat() the file, then we try to read it as a link |