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>maint
							parent
							
								
									d599e0484f
								
							
						
					
					
						commit
						daae19224a
					
				
							
								
								
									
										47
									
								
								fsck.c
								
								
								
								
							
							
						
						
									
										47
									
								
								fsck.c
								
								
								
								
							|  | @ -222,12 +222,47 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func) | |||
| 	return retval; | ||||
| } | ||||
|  | ||||
| static int fsck_ident(char **ident, struct object *obj, fsck_error error_func) | ||||
| { | ||||
| 	if (**ident == '<' || **ident == '\n') | ||||
| 		return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing space before email"); | ||||
| 	*ident += strcspn(*ident, "<\n"); | ||||
| 	if ((*ident)[-1] != ' ') | ||||
| 		return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing space before email"); | ||||
| 	if (**ident != '<') | ||||
| 		return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing email"); | ||||
| 	(*ident)++; | ||||
| 	*ident += strcspn(*ident, "<>\n"); | ||||
| 	if (**ident != '>') | ||||
| 		return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad email"); | ||||
| 	(*ident)++; | ||||
| 	if (**ident != ' ') | ||||
| 		return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing space before date"); | ||||
| 	(*ident)++; | ||||
| 	if (**ident == '0' && (*ident)[1] != ' ') | ||||
| 		return error_func(obj, FSCK_ERROR, "invalid author/committer line - zero-padded date"); | ||||
| 	*ident += strspn(*ident, "0123456789"); | ||||
| 	if (**ident != ' ') | ||||
| 		return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad date"); | ||||
| 	(*ident)++; | ||||
| 	if ((**ident != '+' && **ident != '-') || | ||||
| 	    !isdigit((*ident)[1]) || | ||||
| 	    !isdigit((*ident)[2]) || | ||||
| 	    !isdigit((*ident)[3]) || | ||||
| 	    !isdigit((*ident)[4]) || | ||||
| 	    ((*ident)[5] != '\n')) | ||||
| 		return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad time zone"); | ||||
| 	(*ident) += 6; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int fsck_commit(struct commit *commit, fsck_error error_func) | ||||
| { | ||||
| 	char *buffer = commit->buffer; | ||||
| 	unsigned char tree_sha1[20], sha1[20]; | ||||
| 	struct commit_graft *graft; | ||||
| 	int parents = 0; | ||||
| 	int err; | ||||
|  | ||||
| 	if (commit->date == ULONG_MAX) | ||||
| 		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) | |||
| 	} | ||||
| 	if (memcmp(buffer, "author ", 7)) | ||||
| 		return error_func(&commit->object, FSCK_ERROR, "invalid format - expected 'author' line"); | ||||
| 	buffer += 7; | ||||
| 	err = fsck_ident(&buffer, &commit->object, error_func); | ||||
| 	if (err) | ||||
| 		return err; | ||||
| 	if (memcmp(buffer, "committer ", strlen("committer "))) | ||||
| 		return error_func(&commit->object, FSCK_ERROR, "invalid format - expected 'committer' line"); | ||||
| 	buffer += strlen("committer "); | ||||
| 	err = fsck_ident(&buffer, &commit->object, error_func); | ||||
| 	if (err) | ||||
| 		return err; | ||||
| 	if (*buffer != '\n') | ||||
| 		return error_func(&commit->object, FSCK_ERROR, "invalid format - expected blank line"); | ||||
| 	if (!commit->tree) | ||||
| 		return error_func(&commit->object, FSCK_ERROR, "could not load commit's tree %s", sha1_to_hex(tree_sha1)); | ||||
|  | ||||
|  |  | |||
|  | @ -57,6 +57,34 @@ test_expect_success 'branch pointing to non-commit' ' | |||
| 	git update-ref -d refs/heads/invalid | ||||
| ' | ||||
|  | ||||
| new=nothing | ||||
| test_expect_success 'email without @ is okay' ' | ||||
| 	git cat-file commit HEAD >basis && | ||||
| 	sed "s/@/AT/" basis >okay && | ||||
| 	new=$(git hash-object -t commit -w --stdin <okay) && | ||||
| 	echo "$new" && | ||||
| 	git update-ref refs/heads/bogus "$new" && | ||||
| 	git fsck 2>out && | ||||
| 	cat out && | ||||
| 	! grep "error in commit $new" out | ||||
| ' | ||||
| git update-ref -d refs/heads/bogus | ||||
| rm -f ".git/objects/$new" | ||||
|  | ||||
| new=nothing | ||||
| test_expect_success 'email with embedded > is not okay' ' | ||||
| 	git cat-file commit HEAD >basis && | ||||
| 	sed "s/@[a-z]/&>/" basis >bad-email && | ||||
| 	new=$(git hash-object -t commit -w --stdin <bad-email) && | ||||
| 	echo "$new" && | ||||
| 	git update-ref refs/heads/bogus "$new" && | ||||
| 	git fsck 2>out && | ||||
| 	cat out && | ||||
| 	grep "error in commit $new" out | ||||
| ' | ||||
| git update-ref -d refs/heads/bogus | ||||
| rm -f ".git/objects/$new" | ||||
|  | ||||
| cat > invalid-tag <<EOF | ||||
| object ffffffffffffffffffffffffffffffffffffffff | ||||
| type commit | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Jonathan Nieder
						Jonathan Nieder