Raw
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