| 1 | #!/bin/sh |
| 2 | |
| 3 | test_description='fsck on buffers without NUL termination |
| 4 | |
| 5 | The goal here is to make sure that the various fsck parsers never look |
| 6 | past the end of the buffer they are given, even when encountering broken |
| 7 | or truncated objects. |
| 8 | |
| 9 | We have to use "hash-object" for this because most code paths that read objects |
| 10 | append an extra NUL for safety after the buffer. But hash-object, since it is |
| 11 | reading straight from a file (and possibly even mmap-ing it) cannot always do |
| 12 | so. |
| 13 | |
| 14 | These tests _might_ catch such overruns in normal use, but should be run with |
| 15 | ASan or valgrind for more confidence. |
| 16 | ' |
| 17 | |
| 18 | . ./test-lib.sh |
| 19 | |
| 20 | # the general idea for tags and commits is to build up the "base" file |
| 21 | # progressively, and then test new truncations on top of it. |
| 22 | reset () { |
| 23 | test_expect_success 'reset input to empty' ' |
| 24 | >base |
| 25 | ' |
| 26 | } |
| 27 | |
| 28 | add () { |
| 29 | content="$1" |
| 30 | type=${content%% *} |
| 31 | test_expect_success "add $type line" ' |
| 32 | echo "$content" >>base |
| 33 | ' |
| 34 | } |
| 35 | |
| 36 | check () { |
| 37 | type=$1 |
| 38 | fsck=$2 |
| 39 | content=$3 |
| 40 | test_expect_success "truncated $type ($fsck, \"$content\")" ' |
| 41 | # do not pipe into hash-object here; we want to increase |
| 42 | # the chance that it uses a fixed-size buffer or mmap, |
| 43 | # and a pipe would be read into a strbuf. |
| 44 | { |
| 45 | cat base && |
| 46 | echo "$content" |
| 47 | } >input && |
| 48 | test_must_fail git hash-object -t "$type" input 2>err && |
| 49 | test_grep "$fsck" err |
| 50 | ' |
| 51 | } |
| 52 | |
| 53 | test_expect_success 'create valid objects' ' |
| 54 | git commit --allow-empty -m foo && |
| 55 | commit=$(git rev-parse --verify HEAD) && |
| 56 | tree=$(git rev-parse --verify HEAD^{tree}) |
| 57 | ' |
| 58 | |
| 59 | reset |
| 60 | check commit missingTree "" |
| 61 | check commit missingTree "tr" |
| 62 | check commit missingTree "tree" |
| 63 | check commit badTreeSha1 "tree " |
| 64 | check commit badTreeSha1 "tree 1234" |
| 65 | add "tree $tree" |
| 66 | |
| 67 | # these expect missingAuthor because "parent" is optional |
| 68 | check commit missingAuthor "" |
| 69 | check commit missingAuthor "par" |
| 70 | check commit missingAuthor "parent" |
| 71 | check commit badParentSha1 "parent " |
| 72 | check commit badParentSha1 "parent 1234" |
| 73 | add "parent $commit" |
| 74 | |
| 75 | check commit missingAuthor "" |
| 76 | check commit missingAuthor "au" |
| 77 | check commit missingAuthor "author" |
| 78 | ident_checks () { |
| 79 | check $1 missingEmail "$2 " |
| 80 | check $1 missingEmail "$2 name" |
| 81 | check $1 badEmail "$2 name <" |
| 82 | check $1 badEmail "$2 name <email" |
| 83 | check $1 missingSpaceBeforeDate "$2 name <email>" |
| 84 | check $1 badDate "$2 name <email> " |
| 85 | check $1 badDate "$2 name <email> 1234" |
| 86 | check $1 badTimezone "$2 name <email> 1234 " |
| 87 | check $1 badTimezone "$2 name <email> 1234 +" |
| 88 | } |
| 89 | ident_checks commit author |
| 90 | add "author name <email> 1234 +0000" |
| 91 | |
| 92 | check commit missingCommitter "" |
| 93 | check commit missingCommitter "co" |
| 94 | check commit missingCommitter "committer" |
| 95 | ident_checks commit committer |
| 96 | add "committer name <email> 1234 +0000" |
| 97 | |
| 98 | reset |
| 99 | check tag missingObject "" |
| 100 | check tag missingObject "obj" |
| 101 | check tag missingObject "object" |
| 102 | check tag badObjectSha1 "object " |
| 103 | check tag badObjectSha1 "object 1234" |
| 104 | add "object $commit" |
| 105 | |
| 106 | check tag missingType "" |
| 107 | check tag missingType "ty" |
| 108 | check tag missingType "type" |
| 109 | check tag badType "type " |
| 110 | check tag badType "type com" |
| 111 | add "type commit" |
| 112 | |
| 113 | check tag missingTagEntry "" |
| 114 | check tag missingTagEntry "ta" |
| 115 | check tag missingTagEntry "tag" |
| 116 | check tag badTagName "tag " |
| 117 | add "tag foo" |
| 118 | |
| 119 | check tag missingTagger "" |
| 120 | check tag missingTagger "ta" |
| 121 | check tag missingTagger "tagger" |
| 122 | ident_checks tag tagger |
| 123 | |
| 124 | # trees are a binary format and can't use our earlier helpers |
| 125 | test_expect_success 'truncated tree (short hash)' ' |
| 126 | printf "100644 foo\0\1\1\1\1" >input && |
| 127 | test_must_fail git hash-object -t tree input 2>err && |
| 128 | test_grep badTree err |
| 129 | ' |
| 130 | |
| 131 | test_expect_success 'truncated tree (missing nul)' ' |
| 132 | # these two things are indistinguishable to the parser. The important |
| 133 | # thing about this is example is that there are enough bytes to |
| 134 | # make up a hash, and that there is no NUL (and we confirm that the |
| 135 | # parser does not walk past the end of the buffer). |
| 136 | printf "100644 a long filename, or a hash with missing nul?" >input && |
| 137 | test_must_fail git hash-object -t tree input 2>err && |
| 138 | test_grep badTree err |
| 139 | ' |
| 140 | |
| 141 | test_done |