| #!/bin/sh | |
| test_description='fsck on buffers without NUL termination | |
| The goal here is to make sure that the various fsck parsers never look | |
| past the end of the buffer they are given, even when encountering broken | |
| or truncated objects. | |
| We have to use "hash-object" for this because most code paths that read objects | |
| append an extra NUL for safety after the buffer. But hash-object, since it is | |
| reading straight from a file (and possibly even mmap-ing it) cannot always do | |
| so. | |
| These tests _might_ catch such overruns in normal use, but should be run with | |
| ASan or valgrind for more confidence. | |
| ' | |
| . ./test-lib.sh | |
| # the general idea for tags and commits is to build up the "base" file | |
| # progressively, and then test new truncations on top of it. | |
| reset () { | |
| test_expect_success 'reset input to empty' ' | |
| >base | |
| ' | |
| } | |
| add () { | |
| content="$1" | |
| type=${content%% *} | |
| test_expect_success "add $type line" ' | |
| echo "$content" >>base | |
| ' | |
| } | |
| check () { | |
| type=$1 | |
| fsck=$2 | |
| content=$3 | |
| test_expect_success "truncated $type ($fsck, \"$content\")" ' | |
| # do not pipe into hash-object here; we want to increase | |
| # the chance that it uses a fixed-size buffer or mmap, | |
| # and a pipe would be read into a strbuf. | |
| { | |
| cat base && | |
| echo "$content" | |
| } >input && | |
| test_must_fail git hash-object -t "$type" input 2>err && | |
| test_grep "$fsck" err | |
| ' | |
| } | |
| test_expect_success 'create valid objects' ' | |
| git commit --allow-empty -m foo && | |
| commit=$(git rev-parse --verify HEAD) && | |
| tree=$(git rev-parse --verify HEAD^{tree}) | |
| ' | |
| reset | |
| check commit missingTree "" | |
| check commit missingTree "tr" | |
| check commit missingTree "tree" | |
| check commit badTreeSha1 "tree " | |
| check commit badTreeSha1 "tree 1234" | |
| add "tree $tree" | |
| # these expect missingAuthor because "parent" is optional | |
| check commit missingAuthor "" | |
| check commit missingAuthor "par" | |
| check commit missingAuthor "parent" | |
| check commit badParentSha1 "parent " | |
| check commit badParentSha1 "parent 1234" | |
| add "parent $commit" | |
| check commit missingAuthor "" | |
| check commit missingAuthor "au" | |
| check commit missingAuthor "author" | |
| ident_checks () { | |
| check $1 missingEmail "$2 " | |
| check $1 missingEmail "$2 name" | |
| check $1 badEmail "$2 name <" | |
| check $1 badEmail "$2 name <email" | |
| check $1 missingSpaceBeforeDate "$2 name <email>" | |
| check $1 badDate "$2 name <email> " | |
| check $1 badDate "$2 name <email> 1234" | |
| check $1 badTimezone "$2 name <email> 1234 " | |
| check $1 badTimezone "$2 name <email> 1234 +" | |
| } | |
| ident_checks commit author | |
| add "author name <email> 1234 +0000" | |
| check commit missingCommitter "" | |
| check commit missingCommitter "co" | |
| check commit missingCommitter "committer" | |
| ident_checks commit committer | |
| add "committer name <email> 1234 +0000" | |
| reset | |
| check tag missingObject "" | |
| check tag missingObject "obj" | |
| check tag missingObject "object" | |
| check tag badObjectSha1 "object " | |
| check tag badObjectSha1 "object 1234" | |
| add "object $commit" | |
| check tag missingType "" | |
| check tag missingType "ty" | |
| check tag missingType "type" | |
| check tag badType "type " | |
| check tag badType "type com" | |
| add "type commit" | |
| check tag missingTagEntry "" | |
| check tag missingTagEntry "ta" | |
| check tag missingTagEntry "tag" | |
| check tag badTagName "tag " | |
| add "tag foo" | |
| check tag missingTagger "" | |
| check tag missingTagger "ta" | |
| check tag missingTagger "tagger" | |
| ident_checks tag tagger | |
| # trees are a binary format and can't use our earlier helpers | |
| test_expect_success 'truncated tree (short hash)' ' | |
| printf "100644 foo\0\1\1\1\1" >input && | |
| test_must_fail git hash-object -t tree input 2>err && | |
| test_grep badTree err | |
| ' | |
| test_expect_success 'truncated tree (missing nul)' ' | |
| # these two things are indistinguishable to the parser. The important | |
| # thing about this is example is that there are enough bytes to | |
| # make up a hash, and that there is no NUL (and we confirm that the | |
| # parser does not walk past the end of the buffer). | |
| printf "100644 a long filename, or a hash with missing nul?" >input && | |
| test_must_fail git hash-object -t tree input 2>err && | |
| test_grep badTree err | |
| ' | |
| test_done |