]>
Commit | Line | Data |
---|---|---|
8e430903 JK |
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 | ' | |
b2e5d75d ÆAB |
17 | |
18 | TEST_PASSES_SANITIZE_LEAK=true | |
8e430903 JK |
19 | . ./test-lib.sh |
20 | ||
21 | # the general idea for tags and commits is to build up the "base" file | |
22 | # progressively, and then test new truncations on top of it. | |
23 | reset () { | |
24 | test_expect_success 'reset input to empty' ' | |
25 | >base | |
26 | ' | |
27 | } | |
28 | ||
29 | add () { | |
30 | content="$1" | |
31 | type=${content%% *} | |
32 | test_expect_success "add $type line" ' | |
33 | echo "$content" >>base | |
34 | ' | |
35 | } | |
36 | ||
37 | check () { | |
38 | type=$1 | |
39 | fsck=$2 | |
40 | content=$3 | |
41 | test_expect_success "truncated $type ($fsck, \"$content\")" ' | |
42 | # do not pipe into hash-object here; we want to increase | |
43 | # the chance that it uses a fixed-size buffer or mmap, | |
44 | # and a pipe would be read into a strbuf. | |
45 | { | |
46 | cat base && | |
47 | echo "$content" | |
48 | } >input && | |
49 | test_must_fail git hash-object -t "$type" input 2>err && | |
50 | grep "$fsck" err | |
51 | ' | |
52 | } | |
53 | ||
54 | test_expect_success 'create valid objects' ' | |
55 | git commit --allow-empty -m foo && | |
56 | commit=$(git rev-parse --verify HEAD) && | |
57 | tree=$(git rev-parse --verify HEAD^{tree}) | |
58 | ' | |
59 | ||
60 | reset | |
61 | check commit missingTree "" | |
62 | check commit missingTree "tr" | |
63 | check commit missingTree "tree" | |
64 | check commit badTreeSha1 "tree " | |
65 | check commit badTreeSha1 "tree 1234" | |
66 | add "tree $tree" | |
67 | ||
68 | # these expect missingAuthor because "parent" is optional | |
69 | check commit missingAuthor "" | |
70 | check commit missingAuthor "par" | |
71 | check commit missingAuthor "parent" | |
72 | check commit badParentSha1 "parent " | |
73 | check commit badParentSha1 "parent 1234" | |
74 | add "parent $commit" | |
75 | ||
76 | check commit missingAuthor "" | |
77 | check commit missingAuthor "au" | |
78 | check commit missingAuthor "author" | |
79 | ident_checks () { | |
80 | check $1 missingEmail "$2 " | |
81 | check $1 missingEmail "$2 name" | |
82 | check $1 badEmail "$2 name <" | |
83 | check $1 badEmail "$2 name <email" | |
84 | check $1 missingSpaceBeforeDate "$2 name <email>" | |
85 | check $1 badDate "$2 name <email> " | |
86 | check $1 badDate "$2 name <email> 1234" | |
87 | check $1 badTimezone "$2 name <email> 1234 " | |
88 | check $1 badTimezone "$2 name <email> 1234 +" | |
89 | } | |
90 | ident_checks commit author | |
91 | add "author name <email> 1234 +0000" | |
92 | ||
93 | check commit missingCommitter "" | |
94 | check commit missingCommitter "co" | |
95 | check commit missingCommitter "committer" | |
96 | ident_checks commit committer | |
97 | add "committer name <email> 1234 +0000" | |
98 | ||
99 | reset | |
100 | check tag missingObject "" | |
101 | check tag missingObject "obj" | |
102 | check tag missingObject "object" | |
103 | check tag badObjectSha1 "object " | |
104 | check tag badObjectSha1 "object 1234" | |
105 | add "object $commit" | |
106 | ||
107 | check tag missingType "" | |
108 | check tag missingType "ty" | |
109 | check tag missingType "type" | |
110 | check tag badType "type " | |
111 | check tag badType "type com" | |
112 | add "type commit" | |
113 | ||
114 | check tag missingTagEntry "" | |
115 | check tag missingTagEntry "ta" | |
116 | check tag missingTagEntry "tag" | |
117 | check tag badTagName "tag " | |
118 | add "tag foo" | |
119 | ||
120 | check tag missingTagger "" | |
121 | check tag missingTagger "ta" | |
122 | check tag missingTagger "tagger" | |
123 | ident_checks tag tagger | |
124 | ||
125 | # trees are a binary format and can't use our earlier helpers | |
126 | test_expect_success 'truncated tree (short hash)' ' | |
127 | printf "100644 foo\0\1\1\1\1" >input && | |
128 | test_must_fail git hash-object -t tree input 2>err && | |
129 | grep badTree err | |
130 | ' | |
131 | ||
132 | test_expect_success 'truncated tree (missing nul)' ' | |
133 | # these two things are indistinguishable to the parser. The important | |
134 | # thing about this is example is that there are enough bytes to | |
135 | # make up a hash, and that there is no NUL (and we confirm that the | |
136 | # parser does not walk past the end of the buffer). | |
137 | printf "100644 a long filename, or a hash with missing nul?" >input && | |
138 | test_must_fail git hash-object -t tree input 2>err && | |
139 | grep badTree err | |
140 | ' | |
141 | ||
142 | test_done |