From: Junio C Hamano Date: Fri, 9 Dec 2022 08:03:49 +0000 (+0900) Subject: Merge branch 'ps/attr-limits' into maint-2.32 X-Git-Tag: v2.32.5~1^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e0bfc0b3b91052a5807b66aea866648087b30b80;p=thirdparty%2Fgit.git Merge branch 'ps/attr-limits' into maint-2.32 --- e0bfc0b3b91052a5807b66aea866648087b30b80 diff --cc attr.c index 9e897e43f5,f9316d14ba..d7b8f60e7b --- a/attr.c +++ b/attr.c @@@ -335,10 -331,9 +335,9 @@@ static const char *parse_attr(const cha } static struct match_attr *parse_attr_line(const char *line, const char *src, - int lineno, int macro_ok) + int lineno, unsigned flags) { - int namelen; - int num_attr, i; + size_t namelen, num_attr, i; const char *cp, *name, *states; struct match_attr *res = NULL; int is_macro; @@@ -661,11 -661,11 +665,11 @@@ static void handle_attr_line(struct att { struct match_attr *a; - a = parse_attr_line(line, src, lineno, macro_ok); + a = parse_attr_line(line, src, lineno, flags); if (!a) return; - ALLOC_GROW(res->attrs, res->num_matches + 1, res->alloc); - res->attrs[res->num_matches++] = a; + ALLOC_GROW_BY(res->attrs, res->num_matches, 1, res->alloc); + res->attrs[res->num_matches - 1] = a; } static struct attr_stack *read_attr_from_array(const char **list) @@@ -703,33 -702,39 +707,45 @@@ void git_attr_set_direction(enum git_at direction = new_direction; } -static struct attr_stack *read_attr_from_file(const char *path, int macro_ok) +static struct attr_stack *read_attr_from_file(const char *path, unsigned flags) { + struct strbuf buf = STRBUF_INIT; - FILE *fp = fopen_or_warn(path, "r"); + int fd; + FILE *fp; struct attr_stack *res; - char buf[2048]; int lineno = 0; - int fd; + struct stat st; - if (!fp) - return NULL; + if (flags & READ_ATTR_NOFOLLOW) + fd = open_nofollow(path, O_RDONLY); + else + fd = open(path, O_RDONLY); - fd = fileno(fp); + if (fd < 0) { + warn_on_fopen_errors(path); + return NULL; + } + fp = xfdopen(fd, "r"); + if (fstat(fd, &st)) { + warning_errno(_("cannot fstat gitattributes file '%s'"), path); + fclose(fp); + return NULL; + } + if (st.st_size >= ATTR_MAX_FILE_SIZE) { + warning(_("ignoring overly large gitattributes file '%s'"), path); + fclose(fp); + return NULL; + } CALLOC_ARRAY(res, 1); - while (fgets(buf, sizeof(buf), fp)) { - char *bufp = buf; - if (!lineno) - skip_utf8_bom(&bufp, strlen(bufp)); - handle_attr_line(res, bufp, path, ++lineno, flags); + while (strbuf_getline(&buf, fp) != EOF) { + if (!lineno && starts_with(buf.buf, utf8_bom)) + strbuf_remove(&buf, 0, strlen(utf8_bom)); - handle_attr_line(res, buf.buf, path, ++lineno, macro_ok); ++ handle_attr_line(res, buf.buf, path, ++lineno, flags); } + fclose(fp); + strbuf_release(&buf); return res; } @@@ -744,11 -750,15 +761,15 @@@ static struct attr_stack *read_attr_fro if (!istate) return NULL; - buf = read_blob_data_from_index(istate, path, NULL); + buf = read_blob_data_from_index(istate, path, &size); if (!buf) return NULL; + if (size >= ATTR_MAX_FILE_SIZE) { + warning(_("ignoring overly large gitattributes blob '%s'"), path); + return NULL; + } - res = xcalloc(1, sizeof(*res)); + CALLOC_ARRAY(res, 1); for (sp = buf; *sp; ) { char *ep; int more; diff --cc t/t0003-attributes.sh index 1e4c672b84,9d9aa2855d..89d5a0f67f --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@@ -342,31 -339,63 +342,90 @@@ test_expect_success 'query binary macr test_cmp expect actual ' +test_expect_success SYMLINKS 'set up symlink tests' ' + echo "* test" >attr && + rm -f .gitattributes +' + +test_expect_success SYMLINKS 'symlinks respected in core.attributesFile' ' + test_when_finished "rm symlink" && + ln -s attr symlink && + test_config core.attributesFile "$(pwd)/symlink" && + attr_check file set +' + +test_expect_success SYMLINKS 'symlinks respected in info/attributes' ' + test_when_finished "rm .git/info/attributes" && + ln -s ../../attr .git/info/attributes && + attr_check file set +' + +test_expect_success SYMLINKS 'symlinks not respected in-tree' ' + test_when_finished "rm -rf .gitattributes subdir" && + ln -s attr .gitattributes && + mkdir subdir && + ln -s ../attr subdir/.gitattributes && + attr_check_basic subdir/file unspecified && + test_i18ngrep "unable to access.*gitattributes" err +' + + test_expect_success 'large attributes line ignored in tree' ' + test_when_finished "rm .gitattributes" && + printf "path %02043d" 1 >.gitattributes && + git check-attr --all path >actual 2>err && + echo "warning: ignoring overly long attributes line 1" >expect && + test_cmp expect err && + test_must_be_empty actual + ' + + test_expect_success 'large attributes line ignores trailing content in tree' ' + test_when_finished "rm .gitattributes" && + # older versions of Git broke lines at 2048 bytes; the 2045 bytes + # of 0-padding here is accounting for the three bytes of "a 1", which + # would knock "trailing" to the "next" line, where it would be + # erroneously parsed. + printf "a %02045dtrailing attribute\n" 1 >.gitattributes && + git check-attr --all trailing >actual 2>err && + echo "warning: ignoring overly long attributes line 1" >expect && + test_cmp expect err && + test_must_be_empty actual + ' + + test_expect_success EXPENSIVE 'large attributes file ignored in tree' ' + test_when_finished "rm .gitattributes" && + dd if=/dev/zero of=.gitattributes bs=101M count=1 2>/dev/null && + git check-attr --all path >/dev/null 2>err && + echo "warning: ignoring overly large gitattributes file ${SQ}.gitattributes${SQ}" >expect && + test_cmp expect err + ' + + test_expect_success 'large attributes line ignored in index' ' + test_when_finished "git update-index --remove .gitattributes" && + blob=$(printf "path %02043d" 1 | git hash-object -w --stdin) && + git update-index --add --cacheinfo 100644,$blob,.gitattributes && + git check-attr --cached --all path >actual 2>err && + echo "warning: ignoring overly long attributes line 1" >expect && + test_cmp expect err && + test_must_be_empty actual + ' + + test_expect_success 'large attributes line ignores trailing content in index' ' + test_when_finished "git update-index --remove .gitattributes" && + blob=$(printf "a %02045dtrailing attribute\n" 1 | git hash-object -w --stdin) && + git update-index --add --cacheinfo 100644,$blob,.gitattributes && + git check-attr --cached --all trailing >actual 2>err && + echo "warning: ignoring overly long attributes line 1" >expect && + test_cmp expect err && + test_must_be_empty actual + ' + + test_expect_success EXPENSIVE 'large attributes file ignored in index' ' + test_when_finished "git update-index --remove .gitattributes" && + blob=$(dd if=/dev/zero bs=101M count=1 2>/dev/null | git hash-object -w --stdin) && + git update-index --add --cacheinfo 100644,$blob,.gitattributes && + git check-attr --cached --all path >/dev/null 2>err && + echo "warning: ignoring overly large gitattributes blob ${SQ}.gitattributes${SQ}" >expect && + test_cmp expect err + ' + test_done