diff options
-rw-r--r-- | fsck.c | 38 | ||||
-rw-r--r-- | fsck.h | 12 | ||||
-rwxr-xr-x | t/t1450-fsck.sh | 24 |
3 files changed, 73 insertions, 1 deletions
@@ -2,6 +2,7 @@ #include "object-store.h" #include "repository.h" #include "object.h" +#include "attr.h" #include "blob.h" #include "tree.h" #include "tree-walk.h" @@ -615,7 +616,10 @@ static int fsck_tree(const struct object_id *tree_oid, } if (is_hfs_dotgitattributes(name) || is_ntfs_dotgitattributes(name)) { - if (S_ISLNK(mode)) + if (!S_ISLNK(mode)) + oidset_insert(&options->gitattributes_found, + entry_oid); + else retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_GITATTRIBUTES_SYMLINK, ".gitattributes is a symlink"); @@ -1206,6 +1210,35 @@ static int fsck_blob(const struct object_id *oid, const char *buf, ret |= data.ret; } + if (oidset_contains(&options->gitattributes_found, oid)) { + const char *ptr; + + oidset_insert(&options->gitattributes_done, oid); + + if (!buf || size > ATTR_MAX_FILE_SIZE) { + /* + * A missing buffer here is a sign that the caller found the + * blob too gigantic to load into memory. Let's just consider + * that an error. + */ + return report(options, oid, OBJ_BLOB, + FSCK_MSG_GITATTRIBUTES_LARGE, + ".gitattributes too large to parse"); + } + + for (ptr = buf; *ptr; ) { + const char *eol = strchrnul(ptr, '\n'); + if (eol - ptr >= ATTR_MAX_LINE_LENGTH) { + ret |= report(options, oid, OBJ_BLOB, + FSCK_MSG_GITATTRIBUTES_LINE_LENGTH, + ".gitattributes has too long lines to parse"); + break; + } + + ptr = *eol ? eol + 1 : eol; + } + } + return ret; } @@ -1293,6 +1326,9 @@ int fsck_finish(struct fsck_options *options) ret |= fsck_blobs(&options->gitmodules_found, &options->gitmodules_done, FSCK_MSG_GITMODULES_MISSING, FSCK_MSG_GITMODULES_BLOB, options, ".gitmodules"); + ret |= fsck_blobs(&options->gitattributes_found, &options->gitattributes_done, + FSCK_MSG_GITATTRIBUTES_MISSING, FSCK_MSG_GITATTRIBUTES_BLOB, + options, ".gitattributes"); return ret; } @@ -55,6 +55,10 @@ enum fsck_msg_type { FUNC(GITMODULES_URL, ERROR) \ FUNC(GITMODULES_PATH, ERROR) \ FUNC(GITMODULES_UPDATE, ERROR) \ + FUNC(GITATTRIBUTES_MISSING, ERROR) \ + FUNC(GITATTRIBUTES_LARGE, ERROR) \ + FUNC(GITATTRIBUTES_LINE_LENGTH, ERROR) \ + FUNC(GITATTRIBUTES_BLOB, ERROR) \ /* warnings */ \ FUNC(BAD_FILEMODE, WARN) \ FUNC(EMPTY_NAME, WARN) \ @@ -129,6 +133,8 @@ struct fsck_options { struct oidset skiplist; struct oidset gitmodules_found; struct oidset gitmodules_done; + struct oidset gitattributes_found; + struct oidset gitattributes_done; kh_oid_map_t *object_names; }; @@ -136,18 +142,24 @@ struct fsck_options { .skiplist = OIDSET_INIT, \ .gitmodules_found = OIDSET_INIT, \ .gitmodules_done = OIDSET_INIT, \ + .gitattributes_found = OIDSET_INIT, \ + .gitattributes_done = OIDSET_INIT, \ .error_func = fsck_error_function \ } #define FSCK_OPTIONS_STRICT { \ .strict = 1, \ .gitmodules_found = OIDSET_INIT, \ .gitmodules_done = OIDSET_INIT, \ + .gitattributes_found = OIDSET_INIT, \ + .gitattributes_done = OIDSET_INIT, \ .error_func = fsck_error_function, \ } #define FSCK_OPTIONS_MISSING_GITMODULES { \ .strict = 1, \ .gitmodules_found = OIDSET_INIT, \ .gitmodules_done = OIDSET_INIT, \ + .gitattributes_found = OIDSET_INIT, \ + .gitattributes_done = OIDSET_INIT, \ .error_func = fsck_error_cb_print_missing_gitmodules, \ } diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index 5071ac63a5..9e0afe1fbf 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -865,4 +865,28 @@ test_expect_success 'detect corrupt index file in fsck' ' test_i18ngrep "bad index file" errors ' +test_expect_success 'fsck error on gitattributes with excessive line lengths' ' + blob=$(printf "pattern %02048d" 1 | git hash-object -w --stdin) && + test_when_finished "remove_object $blob" && + tree=$(printf "100644 blob %s\t%s\n" $blob .gitattributes | git mktree) && + test_when_finished "remove_object $tree" && + cat >expected <<-EOF && + error in blob $blob: gitattributesLineLength: .gitattributes has too long lines to parse + EOF + test_must_fail git fsck --no-dangling >actual 2>&1 && + test_cmp expected actual +' + +test_expect_success 'fsck error on gitattributes with excessive size' ' + blob=$(test-tool genzeros $((100 * 1024 * 1024 + 1)) | git hash-object -w --stdin) && + test_when_finished "remove_object $blob" && + tree=$(printf "100644 blob %s\t%s\n" $blob .gitattributes | git mktree) && + test_when_finished "remove_object $tree" && + cat >expected <<-EOF && + error in blob $blob: gitattributesLarge: .gitattributes too large to parse + EOF + test_must_fail git fsck --no-dangling >actual 2>&1 && + test_cmp expected actual +' + test_done |