1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-05-04 12:26:12 +02:00

object-file API: split up and simplify check_object_signature()

Split up the check_object_signature() function into that non-streaming
version (it accepts an already filled "buf"), and a new
stream_object_signature() which will retrieve the object from storage,
and hash it on-the-fly.

All of the callers of check_object_signature() were effectively
calling two different functions, if we go by cyclomatic
complexity. I.e. they'd either take the early "if (map)" branch and
return early, or not. This has been the case since the "if (map)"
condition was added in 090ea12671 (parse_object: avoid putting whole
blob in core, 2012-03-07).

We can then further simplify the resulting check_object_signature()
function since only one caller wanted to pass a non-NULL "buf" and a
non-NULL "real_oidp". That "read_loose_object()" codepath used by "git
fsck" can instead use hash_object_file() followed by oideq().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Ævar Arnfjörð Bjarmason 2022-02-05 00:48:30 +01:00 committed by Junio C Hamano
parent ee213de22d
commit 0f156dbb04
7 changed files with 38 additions and 28 deletions

View File

@ -300,7 +300,7 @@ static void export_blob(const struct object_id *oid)
if (!buf)
die("could not read blob %s", oid_to_hex(oid));
if (check_object_signature(the_repository, oid, buf, size,
type_name(type), NULL) < 0)
type_name(type)) < 0)
die("oid mismatch in blob %s", oid_to_hex(oid));
object = parse_object_buffer(the_repository, oid, type,
size, buf, &eaten);

View File

@ -1413,7 +1413,7 @@ static void fix_unresolved_deltas(struct hashfile *f)
continue;
if (check_object_signature(the_repository, &d->oid, data, size,
type_name(type), NULL) < 0)
type_name(type)) < 0)
die(_("local object %s is corrupt"), oid_to_hex(&d->oid));
/*

View File

@ -61,9 +61,8 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
type_name(*tagged_type), type_name(type));
repl = lookup_replace_object(the_repository, tagged_oid);
ret = check_object_signature(the_repository, repl,
buffer, size, type_name(*tagged_type),
NULL);
ret = check_object_signature(the_repository, repl, buffer, size,
type_name(*tagged_type));
free(buffer);
return ret;

12
cache.h
View File

@ -1322,15 +1322,19 @@ int parse_loose_header(const char *hdr, struct object_info *oi);
/**
* With in-core object data in "buf", rehash it to make sure the
* object name actually matches "oid" to detect object corruption.
* With "buf" == NULL, try reading the object named with "oid" using
* the streaming interface and rehash it to do the same.
*
* A negative value indicates an error, usually that the OID is not
* what we expected, but it might also indicate another error.
*/
int check_object_signature(struct repository *r, const struct object_id *oid,
void *buf, unsigned long size, const char *type,
struct object_id *real_oidp);
void *buf, unsigned long size, const char *type);
/**
* A streaming version of check_object_signature().
* Try reading the object named with "oid" using
* the streaming interface and rehash it to do the same.
*/
int stream_object_signature(struct repository *r, const struct object_id *oid);
int finalize_object_file(const char *tmpfile, const char *filename);

View File

@ -1067,22 +1067,25 @@ int format_object_header(char *str, size_t size, enum object_type type,
}
int check_object_signature(struct repository *r, const struct object_id *oid,
void *buf, unsigned long size, const char *type,
struct object_id *real_oidp)
void *buf, unsigned long size, const char *type)
{
struct object_id tmp;
struct object_id *real_oid = real_oidp ? real_oidp : &tmp;
struct object_id real_oid;
hash_object_file(r->hash_algo, buf, size, type, &real_oid);
return !oideq(oid, &real_oid) ? -1 : 0;
}
int stream_object_signature(struct repository *r, const struct object_id *oid)
{
struct object_id real_oid;
unsigned long size;
enum object_type obj_type;
struct git_istream *st;
git_hash_ctx c;
char hdr[MAX_HEADER_LEN];
int hdrlen;
if (buf) {
hash_object_file(r->hash_algo, buf, size, type, real_oid);
return !oideq(oid, real_oid) ? -1 : 0;
}
st = open_istream(r, oid, &obj_type, &size, NULL);
if (!st)
return -1;
@ -1105,9 +1108,9 @@ int check_object_signature(struct repository *r, const struct object_id *oid,
break;
r->hash_algo->update_fn(&c, buf, readlen);
}
r->hash_algo->final_oid_fn(real_oid, &c);
r->hash_algo->final_oid_fn(&real_oid, &c);
close_istream(st);
return !oideq(oid, real_oid) ? -1 : 0;
return !oideq(oid, &real_oid) ? -1 : 0;
}
int git_open_cloexec(const char *name, int flags)
@ -2611,9 +2614,10 @@ int read_loose_object(const char *path,
git_inflate_end(&stream);
goto out;
}
if (check_object_signature(the_repository, expected_oid,
*contents, *size,
oi->type_name->buf, real_oid) < 0)
hash_object_file(the_repository->hash_algo,
*contents, *size, oi->type_name->buf,
real_oid);
if (!oideq(expected_oid, real_oid))
goto out;
}

View File

@ -279,7 +279,7 @@ struct object *parse_object(struct repository *r, const struct object_id *oid)
if ((obj && obj->type == OBJ_BLOB && repo_has_object_file(r, oid)) ||
(!obj && repo_has_object_file(r, oid) &&
oid_object_info(r, oid, NULL) == OBJ_BLOB)) {
if (check_object_signature(r, repl, NULL, 0, NULL, NULL) < 0) {
if (stream_object_signature(r, repl) < 0) {
error(_("hash mismatch %s"), oid_to_hex(oid));
return NULL;
}
@ -290,7 +290,7 @@ struct object *parse_object(struct repository *r, const struct object_id *oid)
buffer = repo_read_object_file(r, oid, &type, &size);
if (buffer) {
if (check_object_signature(r, repl, buffer, size,
type_name(type), NULL) < 0) {
type_name(type)) < 0) {
free(buffer);
error(_("hash mismatch %s"), oid_to_hex(repl));
return NULL;

View File

@ -127,7 +127,7 @@ static int verify_packfile(struct repository *r,
if (type == OBJ_BLOB && big_file_threshold <= size) {
/*
* Let check_object_signature() check it with
* Let stream_object_signature() check it with
* the streaming interface; no point slurping
* the data in-core only to discard.
*/
@ -142,8 +142,11 @@ static int verify_packfile(struct repository *r,
err = error("cannot unpack %s from %s at offset %"PRIuMAX"",
oid_to_hex(&oid), p->pack_name,
(uintmax_t)entries[i].offset);
else if (check_object_signature(r, &oid, data, size,
type_name(type), NULL) < 0)
else if (data && check_object_signature(r, &oid, data, size,
type_name(type)) < 0)
err = error("packed %s from %s is corrupt",
oid_to_hex(&oid), p->pack_name);
else if (!data && stream_object_signature(r, &oid) < 0)
err = error("packed %s from %s is corrupt",
oid_to_hex(&oid), p->pack_name);
else if (fn) {