Merge branch 'jk/hash-object-fsck'

"git hash-object" now checks that the resulting object is well
formed with the same code as "git fsck".

* jk/hash-object-fsck:
  fsck: do not assume NUL-termination of buffers
  hash-object: use fsck for object checks
  fsck: provide a function to fsck buffer without object struct
  t: use hash-object --literally when created malformed objects
  t7030: stop using invalid tag name
  t1006: stop using 0-padded timestamps
  t1007: modernize malformed object tests
This commit is contained in:
Junio C Hamano 2023-01-30 14:24:22 -08:00
commit abf2bb895b
21 changed files with 293 additions and 95 deletions

94
fsck.c
View File

@ -748,6 +748,23 @@ static int fsck_tree(const struct object_id *tree_oid,
return retval;
}
/*
* Confirm that the headers of a commit or tag object end in a reasonable way,
* either with the usual "\n\n" separator, or at least with a trailing newline
* on the final header line.
*
* This property is important for the memory safety of our callers. It allows
* them to scan the buffer linewise without constantly checking the remaining
* size as long as:
*
* - they check that there are bytes left in the buffer at the start of any
* line (i.e., that the last newline they saw was not the final one we
* found here)
*
* - any intra-line scanning they do will stop at a newline, which will worst
* case hit the newline we found here as the end-of-header. This makes it
* OK for them to use helpers like parse_oid_hex(), or even skip_prefix().
*/
static int verify_headers(const void *data, unsigned long size,
const struct object_id *oid, enum object_type type,
struct fsck_options *options)
@ -808,6 +825,20 @@ static int fsck_ident(const char **ident,
if (*p != ' ')
return report(options, oid, type, FSCK_MSG_MISSING_SPACE_BEFORE_DATE, "invalid author/committer line - missing space before date");
p++;
/*
* Our timestamp parser is based on the C strto*() functions, which
* will happily eat whitespace, including the newline that is supposed
* to prevent us walking past the end of the buffer. So do our own
* scan, skipping linear whitespace but not newlines, and then
* confirming we found a digit. We _could_ be even more strict here,
* as we really expect only a single space, but since we have
* traditionally allowed extra whitespace, we'll continue to do so.
*/
while (*p == ' ' || *p == '\t')
p++;
if (!isdigit(*p))
return report(options, oid, type, FSCK_MSG_BAD_DATE,
"invalid author/committer line - bad date");
if (*p == '0' && p[1] != ' ')
return report(options, oid, type, FSCK_MSG_ZERO_PADDED_DATE, "invalid author/committer line - zero-padded date");
if (date_overflows(parse_timestamp(p, &end, 10)))
@ -834,12 +865,18 @@ static int fsck_commit(const struct object_id *oid,
unsigned author_count;
int err;
const char *buffer_begin = buffer;
const char *buffer_end = buffer + size;
const char *p;
/*
* We _must_ stop parsing immediately if this reports failure, as the
* memory safety of the rest of the function depends on it. See the
* comment above the definition of verify_headers() for more details.
*/
if (verify_headers(buffer, size, oid, OBJ_COMMIT, options))
return -1;
if (!skip_prefix(buffer, "tree ", &buffer))
if (buffer >= buffer_end || !skip_prefix(buffer, "tree ", &buffer))
return report(options, oid, OBJ_COMMIT, FSCK_MSG_MISSING_TREE, "invalid format - expected 'tree' line");
if (parse_oid_hex(buffer, &tree_oid, &p) || *p != '\n') {
err = report(options, oid, OBJ_COMMIT, FSCK_MSG_BAD_TREE_SHA1, "invalid 'tree' line format - bad sha1");
@ -847,7 +884,7 @@ static int fsck_commit(const struct object_id *oid,
return err;
}
buffer = p + 1;
while (skip_prefix(buffer, "parent ", &buffer)) {
while (buffer < buffer_end && skip_prefix(buffer, "parent ", &buffer)) {
if (parse_oid_hex(buffer, &parent_oid, &p) || *p != '\n') {
err = report(options, oid, OBJ_COMMIT, FSCK_MSG_BAD_PARENT_SHA1, "invalid 'parent' line format - bad sha1");
if (err)
@ -856,7 +893,7 @@ static int fsck_commit(const struct object_id *oid,
buffer = p + 1;
}
author_count = 0;
while (skip_prefix(buffer, "author ", &buffer)) {
while (buffer < buffer_end && skip_prefix(buffer, "author ", &buffer)) {
author_count++;
err = fsck_ident(&buffer, oid, OBJ_COMMIT, options);
if (err)
@ -868,7 +905,7 @@ static int fsck_commit(const struct object_id *oid,
err = report(options, oid, OBJ_COMMIT, FSCK_MSG_MULTIPLE_AUTHORS, "invalid format - multiple 'author' lines");
if (err)
return err;
if (!skip_prefix(buffer, "committer ", &buffer))
if (buffer >= buffer_end || !skip_prefix(buffer, "committer ", &buffer))
return report(options, oid, OBJ_COMMIT, FSCK_MSG_MISSING_COMMITTER, "invalid format - expected 'committer' line");
err = fsck_ident(&buffer, oid, OBJ_COMMIT, options);
if (err)
@ -899,13 +936,19 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
int ret = 0;
char *eol;
struct strbuf sb = STRBUF_INIT;
const char *buffer_end = buffer + size;
const char *p;
/*
* We _must_ stop parsing immediately if this reports failure, as the
* memory safety of the rest of the function depends on it. See the
* comment above the definition of verify_headers() for more details.
*/
ret = verify_headers(buffer, size, oid, OBJ_TAG, options);
if (ret)
goto done;
if (!skip_prefix(buffer, "object ", &buffer)) {
if (buffer >= buffer_end || !skip_prefix(buffer, "object ", &buffer)) {
ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_OBJECT, "invalid format - expected 'object' line");
goto done;
}
@ -916,11 +959,11 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
}
buffer = p + 1;
if (!skip_prefix(buffer, "type ", &buffer)) {
if (buffer >= buffer_end || !skip_prefix(buffer, "type ", &buffer)) {
ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TYPE_ENTRY, "invalid format - expected 'type' line");
goto done;
}
eol = strchr(buffer, '\n');
eol = memchr(buffer, '\n', buffer_end - buffer);
if (!eol) {
ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TYPE, "invalid format - unexpected end after 'type' line");
goto done;
@ -932,11 +975,11 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
goto done;
buffer = eol + 1;
if (!skip_prefix(buffer, "tag ", &buffer)) {
if (buffer >= buffer_end || !skip_prefix(buffer, "tag ", &buffer)) {
ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TAG_ENTRY, "invalid format - expected 'tag' line");
goto done;
}
eol = strchr(buffer, '\n');
eol = memchr(buffer, '\n', buffer_end - buffer);
if (!eol) {
ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TAG, "invalid format - unexpected end after 'type' line");
goto done;
@ -952,7 +995,7 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
}
buffer = eol + 1;
if (!skip_prefix(buffer, "tagger ", &buffer)) {
if (buffer >= buffer_end || !skip_prefix(buffer, "tagger ", &buffer)) {
/* early tags do not contain 'tagger' lines; warn only */
ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TAGGER_ENTRY, "invalid format - expected 'tagger' line");
if (ret)
@ -960,10 +1003,8 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
}
else
ret = fsck_ident(&buffer, oid, OBJ_TAG, options);
if (!*buffer)
goto done;
if (!starts_with(buffer, "\n")) {
if (buffer < buffer_end && !starts_with(buffer, "\n")) {
/*
* The verify_headers() check will allow
* e.g. "[...]tagger <tagger>\nsome
@ -1237,19 +1278,26 @@ int fsck_object(struct object *obj, void *data, unsigned long size,
if (!obj)
return report(options, NULL, OBJ_NONE, FSCK_MSG_BAD_OBJECT_SHA1, "no valid object to fsck");
if (obj->type == OBJ_BLOB)
return fsck_blob(&obj->oid, data, size, options);
if (obj->type == OBJ_TREE)
return fsck_tree(&obj->oid, data, size, options);
if (obj->type == OBJ_COMMIT)
return fsck_commit(&obj->oid, data, size, options);
if (obj->type == OBJ_TAG)
return fsck_tag(&obj->oid, data, size, options);
return fsck_buffer(&obj->oid, obj->type, data, size, options);
}
return report(options, &obj->oid, obj->type,
int fsck_buffer(const struct object_id *oid, enum object_type type,
void *data, unsigned long size,
struct fsck_options *options)
{
if (type == OBJ_BLOB)
return fsck_blob(oid, data, size, options);
if (type == OBJ_TREE)
return fsck_tree(oid, data, size, options);
if (type == OBJ_COMMIT)
return fsck_commit(oid, data, size, options);
if (type == OBJ_TAG)
return fsck_tag(oid, data, size, options);
return report(options, oid, type,
FSCK_MSG_UNKNOWN_TYPE,
"unknown type '%d' (internal fsck error)",
obj->type);
type);
}
int fsck_error_function(struct fsck_options *o,

8
fsck.h
View File

@ -183,6 +183,14 @@ int fsck_walk(struct object *obj, void *data, struct fsck_options *options);
int fsck_object(struct object *obj, void *data, unsigned long size,
struct fsck_options *options);
/*
* Same as fsck_object(), but for when the caller doesn't have an object
* struct.
*/
int fsck_buffer(const struct object_id *oid, enum object_type,
void *data, unsigned long size,
struct fsck_options *options);
/*
* fsck a tag, and pass info about it back to the caller. This is
* exposed fsck_object() internals for git-mktag(1).

View File

@ -33,6 +33,7 @@
#include "object-store.h"
#include "promisor-remote.h"
#include "submodule.h"
#include "fsck.h"
/* The maximum size for an object header. */
#define MAX_HEADER_LEN 32
@ -2284,32 +2285,21 @@ int repo_has_object_file(struct repository *r,
return repo_has_object_file_with_flags(r, oid, 0);
}
static void check_tree(const void *buf, size_t size)
/*
* We can't use the normal fsck_error_function() for index_mem(),
* because we don't yet have a valid oid for it to report. Instead,
* report the minimal fsck error here, and rely on the caller to
* give more context.
*/
static int hash_format_check_report(struct fsck_options *opts,
const struct object_id *oid,
enum object_type object_type,
enum fsck_msg_type msg_type,
enum fsck_msg_id msg_id,
const char *message)
{
struct tree_desc desc;
struct name_entry entry;
init_tree_desc(&desc, buf, size);
while (tree_entry(&desc, &entry))
/* do nothing
* tree_entry() will die() on malformed entries */
;
}
static void check_commit(const void *buf, size_t size)
{
struct commit c;
memset(&c, 0, sizeof(c));
if (parse_commit_buffer(the_repository, &c, buf, size, 0))
die(_("corrupt commit"));
}
static void check_tag(const void *buf, size_t size)
{
struct tag t;
memset(&t, 0, sizeof(t));
if (parse_tag_buffer(the_repository, &t, buf, size))
die(_("corrupt tag"));
error(_("object fails fsck: %s"), message);
return 1;
}
static int index_mem(struct index_state *istate,
@ -2336,12 +2326,13 @@ static int index_mem(struct index_state *istate,
}
}
if (flags & HASH_FORMAT_CHECK) {
if (type == OBJ_TREE)
check_tree(buf, size);
if (type == OBJ_COMMIT)
check_commit(buf, size);
if (type == OBJ_TAG)
check_tag(buf, size);
struct fsck_options opts = FSCK_OPTIONS_DEFAULT;
opts.strict = 1;
opts.error_func = hash_format_check_report;
if (fsck_buffer(null_oid(), type, buf, size, &opts))
die(_("refusing to create malformed object"));
fsck_finish(&opts);
}
if (write_object)

View File

@ -292,8 +292,8 @@ commit_message="Initial commit"
commit_sha1=$(echo_without_newline "$commit_message" | git commit-tree $tree_sha1)
commit_size=$(($(test_oid hexsz) + 137))
commit_content="tree $tree_sha1
author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 0000000000 +0000
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 0000000000 +0000
author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 0 +0000
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 0 +0000
$commit_message"
@ -304,7 +304,7 @@ type blob
tag hellotag
tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
tag_description="This is a tag"
tag_content="$tag_header_without_timestamp 0000000000 +0000
tag_content="$tag_header_without_timestamp 0 +0000
$tag_description"

View File

@ -203,23 +203,34 @@ done
test_expect_success 'too-short tree' '
echo abc >malformed-tree &&
test_must_fail git hash-object -t tree malformed-tree 2>err &&
test_i18ngrep "too-short tree object" err
grep "too-short tree object" err
'
test_expect_success 'malformed mode in tree' '
hex_sha1=$(echo foo | git hash-object --stdin -w) &&
bin_sha1=$(echo $hex_sha1 | hex2oct) &&
printf "9100644 \0$bin_sha1" >tree-with-malformed-mode &&
hex_oid=$(echo foo | git hash-object --stdin -w) &&
bin_oid=$(echo $hex_oid | hex2oct) &&
printf "9100644 \0$bin_oid" >tree-with-malformed-mode &&
test_must_fail git hash-object -t tree tree-with-malformed-mode 2>err &&
test_i18ngrep "malformed mode in tree entry" err
grep "malformed mode in tree entry" err
'
test_expect_success 'empty filename in tree' '
hex_sha1=$(echo foo | git hash-object --stdin -w) &&
bin_sha1=$(echo $hex_sha1 | hex2oct) &&
printf "100644 \0$bin_sha1" >tree-with-empty-filename &&
hex_oid=$(echo foo | git hash-object --stdin -w) &&
bin_oid=$(echo $hex_oid | hex2oct) &&
printf "100644 \0$bin_oid" >tree-with-empty-filename &&
test_must_fail git hash-object -t tree tree-with-empty-filename 2>err &&
test_i18ngrep "empty filename in tree entry" err
grep "empty filename in tree entry" err
'
test_expect_success 'duplicate filename in tree' '
hex_oid=$(echo foo | git hash-object --stdin -w) &&
bin_oid=$(echo $hex_oid | hex2oct) &&
{
printf "100644 file\0$bin_oid" &&
printf "100644 file\0$bin_oid"
} >tree-with-duplicate-filename &&
test_must_fail git hash-object -t tree tree-with-duplicate-filename 2>err &&
grep "duplicateEntries" err
'
test_expect_success 'corrupt commit' '

View File

@ -212,7 +212,7 @@ test_expect_success 'email without @ is okay' '
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) &&
new=$(git hash-object --literally -t commit -w --stdin <bad-email) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@ -223,7 +223,7 @@ test_expect_success 'email with embedded > is not okay' '
test_expect_success 'missing < email delimiter is reported nicely' '
git cat-file commit HEAD >basis &&
sed "s/<//" basis >bad-email-2 &&
new=$(git hash-object -t commit -w --stdin <bad-email-2) &&
new=$(git hash-object --literally -t commit -w --stdin <bad-email-2) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@ -234,7 +234,7 @@ test_expect_success 'missing < email delimiter is reported nicely' '
test_expect_success 'missing email is reported nicely' '
git cat-file commit HEAD >basis &&
sed "s/[a-z]* <[^>]*>//" basis >bad-email-3 &&
new=$(git hash-object -t commit -w --stdin <bad-email-3) &&
new=$(git hash-object --literally -t commit -w --stdin <bad-email-3) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@ -245,7 +245,7 @@ test_expect_success 'missing email is reported nicely' '
test_expect_success '> in name is reported' '
git cat-file commit HEAD >basis &&
sed "s/ </> </" basis >bad-email-4 &&
new=$(git hash-object -t commit -w --stdin <bad-email-4) &&
new=$(git hash-object --literally -t commit -w --stdin <bad-email-4) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@ -258,7 +258,7 @@ test_expect_success 'integer overflow in timestamps is reported' '
git cat-file commit HEAD >basis &&
sed "s/^\\(author .*>\\) [0-9]*/\\1 18446744073709551617/" \
<basis >bad-timestamp &&
new=$(git hash-object -t commit -w --stdin <bad-timestamp) &&
new=$(git hash-object --literally -t commit -w --stdin <bad-timestamp) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@ -269,7 +269,7 @@ test_expect_success 'integer overflow in timestamps is reported' '
test_expect_success 'commit with NUL in header' '
git cat-file commit HEAD >basis &&
sed "s/author ./author Q/" <basis | q_to_nul >commit-NUL-header &&
new=$(git hash-object -t commit -w --stdin <commit-NUL-header) &&
new=$(git hash-object --literally -t commit -w --stdin <commit-NUL-header) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@ -292,7 +292,7 @@ test_expect_success 'tree object with duplicate entries' '
git cat-file tree $T &&
git cat-file tree $T
) |
git hash-object -w -t tree --stdin
git hash-object --literally -w -t tree --stdin
) &&
test_must_fail git fsck 2>out &&
test_i18ngrep "error in tree .*contains duplicate file entries" out
@ -426,7 +426,7 @@ test_expect_success 'tag with incorrect tag name & missing tagger' '
This is an invalid tag.
EOF
tag=$(git hash-object -t tag -w --stdin <wrong-tag) &&
tag=$(git hash-object --literally -t tag -w --stdin <wrong-tag) &&
test_when_finished "remove_object $tag" &&
echo $tag >.git/refs/tags/wrong &&
test_when_finished "git update-ref -d refs/tags/wrong" &&
@ -558,7 +558,7 @@ test_expect_success 'rev-list --verify-objects with commit graph (parent)' '
test_expect_success 'force fsck to ignore double author' '
git cat-file commit HEAD >basis &&
sed "s/^author .*/&,&/" <basis | tr , \\n >multiple-authors &&
new=$(git hash-object -t commit -w --stdin <multiple-authors) &&
new=$(git hash-object --literally -t commit -w --stdin <multiple-authors) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@ -573,7 +573,7 @@ test_expect_success 'fsck notices blob entry pointing to null sha1' '
(git init null-blob &&
cd null-blob &&
sha=$(printf "100644 file$_bz$_bzoid" |
git hash-object -w --stdin -t tree) &&
git hash-object --literally -w --stdin -t tree) &&
git fsck 2>out &&
test_i18ngrep "warning.*null sha1" out
)
@ -583,7 +583,7 @@ test_expect_success 'fsck notices submodule entry pointing to null sha1' '
(git init null-commit &&
cd null-commit &&
sha=$(printf "160000 submodule$_bz$_bzoid" |
git hash-object -w --stdin -t tree) &&
git hash-object --literally -w --stdin -t tree) &&
git fsck 2>out &&
test_i18ngrep "warning.*null sha1" out
)
@ -648,7 +648,7 @@ test_expect_success 'NUL in commit' '
git commit --allow-empty -m "initial commitQNUL after message" &&
git cat-file commit HEAD >original &&
q_to_nul <original >munged &&
git hash-object -w -t commit --stdin <munged >name &&
git hash-object --literally -w -t commit --stdin <munged >name &&
git branch bad $(cat name) &&
test_must_fail git -c fsck.nulInCommit=error fsck 2>warn.1 &&
@ -794,8 +794,8 @@ test_expect_success 'fsck errors in packed objects' '
git cat-file commit HEAD >basis &&
sed "s/</one/" basis >one &&
sed "s/</foo/" basis >two &&
one=$(git hash-object -t commit -w one) &&
two=$(git hash-object -t commit -w two) &&
one=$(git hash-object --literally -t commit -w one) &&
two=$(git hash-object --literally -t commit -w two) &&
pack=$(
{
echo $one &&

140
t/t1451-fsck-buffer.sh Executable file
View File

@ -0,0 +1,140 @@
#!/bin/sh
test_description='fsck on buffers without NUL termination
The goal here is to make sure that the various fsck parsers never look
past the end of the buffer they are given, even when encountering broken
or truncated objects.
We have to use "hash-object" for this because most code paths that read objects
append an extra NUL for safety after the buffer. But hash-object, since it is
reading straight from a file (and possibly even mmap-ing it) cannot always do
so.
These tests _might_ catch such overruns in normal use, but should be run with
ASan or valgrind for more confidence.
'
. ./test-lib.sh
# the general idea for tags and commits is to build up the "base" file
# progressively, and then test new truncations on top of it.
reset () {
test_expect_success 'reset input to empty' '
>base
'
}
add () {
content="$1"
type=${content%% *}
test_expect_success "add $type line" '
echo "$content" >>base
'
}
check () {
type=$1
fsck=$2
content=$3
test_expect_success "truncated $type ($fsck, \"$content\")" '
# do not pipe into hash-object here; we want to increase
# the chance that it uses a fixed-size buffer or mmap,
# and a pipe would be read into a strbuf.
{
cat base &&
echo "$content"
} >input &&
test_must_fail git hash-object -t "$type" input 2>err &&
grep "$fsck" err
'
}
test_expect_success 'create valid objects' '
git commit --allow-empty -m foo &&
commit=$(git rev-parse --verify HEAD) &&
tree=$(git rev-parse --verify HEAD^{tree})
'
reset
check commit missingTree ""
check commit missingTree "tr"
check commit missingTree "tree"
check commit badTreeSha1 "tree "
check commit badTreeSha1 "tree 1234"
add "tree $tree"
# these expect missingAuthor because "parent" is optional
check commit missingAuthor ""
check commit missingAuthor "par"
check commit missingAuthor "parent"
check commit badParentSha1 "parent "
check commit badParentSha1 "parent 1234"
add "parent $commit"
check commit missingAuthor ""
check commit missingAuthor "au"
check commit missingAuthor "author"
ident_checks () {
check $1 missingEmail "$2 "
check $1 missingEmail "$2 name"
check $1 badEmail "$2 name <"
check $1 badEmail "$2 name <email"
check $1 missingSpaceBeforeDate "$2 name <email>"
check $1 badDate "$2 name <email> "
check $1 badDate "$2 name <email> 1234"
check $1 badTimezone "$2 name <email> 1234 "
check $1 badTimezone "$2 name <email> 1234 +"
}
ident_checks commit author
add "author name <email> 1234 +0000"
check commit missingCommitter ""
check commit missingCommitter "co"
check commit missingCommitter "committer"
ident_checks commit committer
add "committer name <email> 1234 +0000"
reset
check tag missingObject ""
check tag missingObject "obj"
check tag missingObject "object"
check tag badObjectSha1 "object "
check tag badObjectSha1 "object 1234"
add "object $commit"
check tag missingType ""
check tag missingType "ty"
check tag missingType "type"
check tag badType "type "
check tag badType "type com"
add "type commit"
check tag missingTagEntry ""
check tag missingTagEntry "ta"
check tag missingTagEntry "tag"
check tag badTagName "tag "
add "tag foo"
check tag missingTagger ""
check tag missingTagger "ta"
check tag missingTagger "tagger"
ident_checks tag tagger
# trees are a binary format and can't use our earlier helpers
test_expect_success 'truncated tree (short hash)' '
printf "100644 foo\0\1\1\1\1" >input &&
test_must_fail git hash-object -t tree input 2>err &&
grep badTree err
'
test_expect_success 'truncated tree (missing nul)' '
# these two things are indistinguishable to the parser. The important
# thing about this is example is that there are enough bytes to
# make up a hash, and that there is no NUL (and we confirm that the
# parser does not walk past the end of the buffer).
printf "100644 a long filename, or a hash with missing nul?" >input &&
test_must_fail git hash-object -t tree input 2>err &&
grep badTree err
'
test_done

View File

@ -10,7 +10,7 @@ test_expect_success 'create bogus tree' '
bogus_tree=$(
printf "100644 fooQ$name" |
q_to_nul |
git hash-object -w --stdin -t tree
git hash-object --literally -w --stdin -t tree
)
'

View File

@ -29,7 +29,7 @@ make_tree () {
make_tree_entry "$1" "$2" "$3"
shift; shift; shift
done |
git hash-object -w -t tree --stdin
git hash-object --literally -w -t tree --stdin
}
# this is kind of a convoluted setup, but matches

View File

@ -10,7 +10,7 @@ test_expect_success 'setup' '
git cat-file commit HEAD |
sed "/^author /s/>/>-<>/" >broken_email.commit &&
git hash-object -w -t commit broken_email.commit >broken_email.hash &&
git hash-object --literally -w -t commit broken_email.commit >broken_email.hash &&
git update-ref refs/heads/broken_email $(cat broken_email.hash)
'
@ -46,7 +46,7 @@ test_expect_success 'git log --format with broken author email' '
munge_author_date () {
git cat-file commit "$1" >commit.orig &&
sed "s/^\(author .*>\) [0-9]*/\1 $2/" <commit.orig >commit.munge &&
git hash-object -w -t commit commit.munge
git hash-object --literally -w -t commit commit.munge
}
test_expect_success 'unparsable dates produce sentinel value' '

View File

@ -263,7 +263,7 @@ tag guten tag
This is an invalid tag.
EOF
tag=$(git hash-object -t tag -w --stdin <wrong-tag) &&
tag=$(git hash-object -t tag -w --stdin --literally <wrong-tag) &&
pack1=$(echo $tag $sha | git pack-objects tag-test) &&
echo remove tag object &&
thirtyeight=${tag#??} &&

View File

@ -138,7 +138,7 @@ This commit object intentionally broken
EOF
test_expect_success 'setup bogus commit' '
commit="$(git hash-object -t commit -w --stdin <bogus-commit)"
commit="$(git hash-object --literally -t commit -w --stdin <bogus-commit)"
'
test_expect_success 'fsck with no skipList input' '

View File

@ -1114,7 +1114,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object'
This commit object intentionally broken
EOF
BOGUS=$(git -C "$P" hash-object -t commit -w --stdin <bogus-commit) &&
BOGUS=$(git -C "$P" hash-object -t commit -w --stdin --literally <bogus-commit) &&
git -C "$P" branch bogus-branch "$BOGUS" &&
echo my-blob >"$P/my-blob" &&

View File

@ -606,7 +606,7 @@ test_expect_success 'create tag without tagger' '
git tag -a -m "Broken tag" taggerless &&
git tag -f taggerless $(git cat-file tag taggerless |
sed -e "/^tagger /d" |
git hash-object --stdin -w -t tag)
git hash-object --literally --stdin -w -t tag)
'
test_atom refs/tags/taggerless type 'commit'

View File

@ -115,7 +115,7 @@ test_expect_success GPGSM 'verify and show signatures x509 with high minTrustLev
test_expect_success GPG 'detect fudged signature' '
git cat-file tag seventh-signed >raw &&
sed -e "/^tag / s/seventh/7th forged/" raw >forged1 &&
sed -e "/^tag / s/seventh/7th-forged/" raw >forged1 &&
git hash-object -w -t tag forged1 >forged1.tag &&
test_must_fail git verify-tag $(cat forged1.tag) 2>actual1 &&
grep "BAD signature from" actual1 &&

View File

@ -125,7 +125,7 @@ test_expect_success GPGSSH,GPGSSH_VERIFYTIME 'verify-tag failes with tag date ou
test_expect_success GPGSSH 'detect fudged ssh signature' '
test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
git cat-file tag seventh-signed >raw &&
sed -e "/^tag / s/seventh/7th forged/" raw >forged1 &&
sed -e "/^tag / s/seventh/7th-forged/" raw >forged1 &&
git hash-object -w -t tag forged1 >forged1.tag &&
test_must_fail git verify-tag $(cat forged1.tag) 2>actual1 &&
grep "${GPGSSH_BAD_SIGNATURE}" actual1 &&

View File

@ -105,7 +105,7 @@ test_expect_success '--amend option with empty author' '
test_expect_success '--amend option with missing author' '
git cat-file commit Initial >tmp &&
sed "s/author [^<]* </author </" tmp >malformed &&
sha=$(git hash-object -t commit -w malformed) &&
sha=$(git hash-object --literally -t commit -w malformed) &&
test_when_finished "remove_object $sha" &&
git checkout $sha &&
test_when_finished "git checkout Initial" &&

View File

@ -202,7 +202,7 @@ test_expect_success GPG 'detect fudged signature with NUL' '
git cat-file commit seventh-signed >raw &&
cat raw >forged2 &&
echo Qwik | tr "Q" "\000" >>forged2 &&
git hash-object -w -t commit forged2 >forged2.commit &&
git hash-object --literally -w -t commit forged2 >forged2.commit &&
test_must_fail git verify-commit $(cat forged2.commit) &&
git show --pretty=short --show-signature $(cat forged2.commit) >actual2 &&
grep "BAD signature from" actual2 &&

View File

@ -270,7 +270,7 @@ test_expect_success GPGSSH 'detect fudged signature with NUL' '
git cat-file commit seventh-signed >raw &&
cat raw >forged2 &&
echo Qwik | tr "Q" "\000" >>forged2 &&
git hash-object -w -t commit forged2 >forged2.commit &&
git hash-object --literally -w -t commit forged2 >forged2.commit &&
test_must_fail git verify-commit $(cat forged2.commit) &&
git show --pretty=short --show-signature $(cat forged2.commit) >actual2 &&
grep "${GPGSSH_BAD_SIGNATURE}" actual2 &&

View File

@ -201,7 +201,7 @@ committer David Reiss <dreiss@facebook.com> 1234567890 +0000
some message
EOF
COMMIT=$(git hash-object -t commit -w badcommit) &&
COMMIT=$(git hash-object --literally -t commit -w badcommit) &&
git --no-pager blame $COMMIT -- uno >/dev/null
'

View File

@ -373,7 +373,7 @@ EOF
test_expect_success 'cope with tagger-less tags' '
TAG=$(git hash-object -t tag -w tag-content) &&
TAG=$(git hash-object --literally -t tag -w tag-content) &&
git update-ref refs/tags/sonnenschein $TAG &&
git fast-export -C -C --signed-tags=strip --all > output &&
test $(grep -c "^tag " output) = 4 &&