better validation on delta base object offsets
In one case, it was possible to have a bad offset equal to 0 effectively pointing a delta onto itself and crashing git after too many recursions. In the other cases, a negative offset could result due to off_t being signed. Catch those. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
0e8189e270
commit
d8f325563d
@ -1038,10 +1038,10 @@ static void check_object(struct object_entry *entry)
|
|||||||
c = buf[used_0++];
|
c = buf[used_0++];
|
||||||
ofs = (ofs << 7) + (c & 127);
|
ofs = (ofs << 7) + (c & 127);
|
||||||
}
|
}
|
||||||
if (ofs >= entry->in_pack_offset)
|
ofs = entry->in_pack_offset - ofs;
|
||||||
|
if (ofs <= 0 || ofs >= entry->in_pack_offset)
|
||||||
die("delta base offset out of bound for %s",
|
die("delta base offset out of bound for %s",
|
||||||
sha1_to_hex(entry->idx.sha1));
|
sha1_to_hex(entry->idx.sha1));
|
||||||
ofs = entry->in_pack_offset - ofs;
|
|
||||||
if (reuse_delta && !entry->preferred_base) {
|
if (reuse_delta && !entry->preferred_base) {
|
||||||
struct revindex_entry *revidx;
|
struct revindex_entry *revidx;
|
||||||
revidx = find_pack_revindex(p, ofs);
|
revidx = find_pack_revindex(p, ofs);
|
||||||
|
@ -370,6 +370,8 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
|
|||||||
base_offset = (base_offset << 7) + (c & 127);
|
base_offset = (base_offset << 7) + (c & 127);
|
||||||
}
|
}
|
||||||
base_offset = obj_list[nr].offset - base_offset;
|
base_offset = obj_list[nr].offset - base_offset;
|
||||||
|
if (base_offset <= 0 || base_offset >= obj_list[nr].offset)
|
||||||
|
die("offset value out of bound for delta base object");
|
||||||
|
|
||||||
delta_data = get_data(delta_size);
|
delta_data = get_data(delta_size);
|
||||||
if (dry_run || !delta_data) {
|
if (dry_run || !delta_data) {
|
||||||
|
@ -334,7 +334,7 @@ static void *unpack_raw_entry(struct object_entry *obj, union delta_base *delta_
|
|||||||
base_offset = (base_offset << 7) + (c & 127);
|
base_offset = (base_offset << 7) + (c & 127);
|
||||||
}
|
}
|
||||||
delta_base->offset = obj->idx.offset - base_offset;
|
delta_base->offset = obj->idx.offset - base_offset;
|
||||||
if (delta_base->offset >= obj->idx.offset)
|
if (delta_base->offset <= 0 || delta_base->offset >= obj->idx.offset)
|
||||||
bad_object(obj->idx.offset, "delta base offset is out of bound");
|
bad_object(obj->idx.offset, "delta base offset is out of bound");
|
||||||
break;
|
break;
|
||||||
case OBJ_COMMIT:
|
case OBJ_COMMIT:
|
||||||
|
@ -1355,7 +1355,7 @@ static off_t get_delta_base(struct packed_git *p,
|
|||||||
base_offset = (base_offset << 7) + (c & 127);
|
base_offset = (base_offset << 7) + (c & 127);
|
||||||
}
|
}
|
||||||
base_offset = delta_obj_offset - base_offset;
|
base_offset = delta_obj_offset - base_offset;
|
||||||
if (base_offset >= delta_obj_offset)
|
if (base_offset <= 0 || base_offset >= delta_obj_offset)
|
||||||
return 0; /* out of bound */
|
return 0; /* out of bound */
|
||||||
*curpos += used;
|
*curpos += used;
|
||||||
} else if (type == OBJ_REF_DELTA) {
|
} else if (type == OBJ_REF_DELTA) {
|
||||||
|
Reference in New Issue
Block a user