fsck: check ident lines in commit objects
Check that email addresses do not contain <, >, or newline so they can be quickly scanned without trouble. The copy() function in ident.c already ensures that ordinary git commands will not write email addresses without this property. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jonathan Nieder committed
Apr 24, 2010 at 11:06 UTC
daae19224a05be9efb9a39c2a2c1c9a60fe906f1
2 files changed
+75
fsck.c
+47
@@ -222,12 +222,47 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
222
return retval;
223
}
224
225
+static int fsck_ident(char **ident, struct object *obj, fsck_error error_func)
226
+{
227
+ if (**ident == '<' || **ident == '\n')
228
+ return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing space before email");
229
+ *ident += strcspn(*ident, "<\n");
230
+ if ((*ident)[-1] != ' ')
231
+ return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing space before email");
232
+ if (**ident != '<')
233
+ return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing email");
234
+ (*ident)++;
235
+ *ident += strcspn(*ident, "<>\n");
236
+ if (**ident != '>')
237
+ return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad email");
238
+ (*ident)++;
239
+ if (**ident != ' ')
240
+ return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing space before date");
241
+ (*ident)++;
242
+ if (**ident == '0' && (*ident)[1] != ' ')
243
+ return error_func(obj, FSCK_ERROR, "invalid author/committer line - zero-padded date");
244
+ *ident += strspn(*ident, "0123456789");
245
+ if (**ident != ' ')
246
+ return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad date");
247
+ (*ident)++;
248
+ if ((**ident != '+' && **ident != '-') ||
249
+ !isdigit((*ident)[1]) ||
250
+ !isdigit((*ident)[2]) ||
251
+ !isdigit((*ident)[3]) ||
252
+ !isdigit((*ident)[4]) ||
253
+ ((*ident)[5] != '\n'))
254
+ return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad time zone");
255
+ (*ident) += 6;
256
+ return 0;
257
+}
258
+
259
static int fsck_commit(struct commit *commit, fsck_error error_func)
260
{
261
char *buffer = commit->buffer;
262
unsigned char tree_sha1[20], sha1[20];
263
struct commit_graft *graft;
264
int parents = 0;
265
+ int err;
266
267
if (commit->date == ULONG_MAX)
268
return error_func(&commit->object, FSCK_ERROR, "invalid author/committer line");
@@ -266,6 +301,18 @@ static int fsck_commit(struct commit *commit, fsck_error error_func)
301
}
302
if (memcmp(buffer, "author ", 7))
303
return error_func(&commit->object, FSCK_ERROR, "invalid format - expected 'author' line");
304
+ buffer += 7;
305
+ err = fsck_ident(&buffer, &commit->object, error_func);
306
+ if (err)
307
+ return err;
308
+ if (memcmp(buffer, "committer ", strlen("committer ")))
309
+ return error_func(&commit->object, FSCK_ERROR, "invalid format - expected 'committer' line");
310
+ buffer += strlen("committer ");
311
+ err = fsck_ident(&buffer, &commit->object, error_func);
312
+ if (err)
313
+ return err;
314
+ if (*buffer != '\n')
315
+ return error_func(&commit->object, FSCK_ERROR, "invalid format - expected blank line");
316
if (!commit->tree)
317
return error_func(&commit->object, FSCK_ERROR, "could not load commit's tree %s", sha1_to_hex(tree_sha1));
318
t/t1450-fsck.sh
+28
@@ -57,6 +57,34 @@ test_expect_success 'branch pointing to non-commit' '
57
git update-ref -d refs/heads/invalid
58
'
59
60
+new=nothing
61
+test_expect_success 'email without @ is okay' '
62
+ git cat-file commit HEAD >basis &&
63
+ sed "s/@/AT/" basis >okay &&
64
+ new=$(git hash-object -t commit -w --stdin <okay) &&
65
+ echo "$new" &&
66
+ git update-ref refs/heads/bogus "$new" &&
67
+ git fsck 2>out &&
68
+ cat out &&
69
+ ! grep "error in commit $new" out
70
+'
71
+git update-ref -d refs/heads/bogus
72
+rm -f ".git/objects/$new"
73
+
74
+new=nothing
75
+test_expect_success 'email with embedded > is not okay' '
76
+ git cat-file commit HEAD >basis &&
77
+ sed "s/@[a-z]/&>/" basis >bad-email &&
78
+ new=$(git hash-object -t commit -w --stdin <bad-email) &&
79
+ echo "$new" &&
80
+ git update-ref refs/heads/bogus "$new" &&
81
+ git fsck 2>out &&
82
+ cat out &&
83
+ grep "error in commit $new" out
84
+'
85
+git update-ref -d refs/heads/bogus
86
+rm -f ".git/objects/$new"
87
+
88
cat > invalid-tag <<EOF
89
object ffffffffffffffffffffffffffffffffffffffff
90
type commit