consolidate two copies of new style object header parsing code.
Also while we are at it, remove redundant typename[] array from unpack_sha1_header. The only reason it is different from the type_names[] array in object.c module is that this code cares about the subset of object types that are valid in a loose object, so prepare a separate array of boolean that tells us which types are valid, and share the name translation with the others. Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
501524e938
commit
ad1ed5ee89
87
sha1_file.c
87
sha1_file.c
@ -711,17 +711,39 @@ int legacy_loose_object(unsigned char *map)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep)
|
||||
{
|
||||
unsigned shift;
|
||||
unsigned char c;
|
||||
unsigned long size;
|
||||
unsigned long used = 0;
|
||||
|
||||
c = buf[used++];
|
||||
*type = (c >> 4) & 7;
|
||||
size = c & 15;
|
||||
shift = 4;
|
||||
while (c & 0x80) {
|
||||
if (len <= used)
|
||||
return 0;
|
||||
if (sizeof(long) * 8 <= shift)
|
||||
return 0;
|
||||
c = buf[used++];
|
||||
size += (c & 0x7f) << shift;
|
||||
shift += 7;
|
||||
}
|
||||
*sizep = size;
|
||||
return used;
|
||||
}
|
||||
|
||||
static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz)
|
||||
{
|
||||
unsigned char c;
|
||||
unsigned int bits;
|
||||
unsigned long size;
|
||||
static const char *typename[8] = {
|
||||
NULL, /* OBJ_EXT */
|
||||
"commit", "tree", "blob", "tag",
|
||||
NULL, NULL, NULL
|
||||
unsigned long size, used;
|
||||
static const char valid_loose_object_type[8] = {
|
||||
0, /* OBJ_EXT */
|
||||
1, 1, 1, 1, /* "commit", "tree", "blob", "tag" */
|
||||
0, /* "delta" and others are invalid in a loose object */
|
||||
};
|
||||
const char *type;
|
||||
enum object_type type;
|
||||
|
||||
/* Get the data stream */
|
||||
memset(stream, 0, sizeof(*stream));
|
||||
@ -735,22 +757,11 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
|
||||
return inflate(stream, 0);
|
||||
}
|
||||
|
||||
c = *map++;
|
||||
mapsize--;
|
||||
type = typename[(c >> 4) & 7];
|
||||
if (!type)
|
||||
used = unpack_object_header_gently(map, mapsize, &type, &size);
|
||||
if (!used || !valid_loose_object_type[type])
|
||||
return -1;
|
||||
|
||||
bits = 4;
|
||||
size = c & 0xf;
|
||||
while ((c & 0x80)) {
|
||||
if (bits >= 8*sizeof(long))
|
||||
return -1;
|
||||
c = *map++;
|
||||
size += (c & 0x7f) << bits;
|
||||
bits += 7;
|
||||
mapsize--;
|
||||
}
|
||||
map += used;
|
||||
mapsize -= used;
|
||||
|
||||
/* Set up the stream for the rest.. */
|
||||
stream->next_in = map;
|
||||
@ -758,7 +769,8 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
|
||||
inflateInit(stream);
|
||||
|
||||
/* And generate the fake traditional header */
|
||||
stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu", type, size);
|
||||
stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu",
|
||||
type_names[type], size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -916,25 +928,18 @@ static int packed_delta_info(unsigned char *base_sha1,
|
||||
static unsigned long unpack_object_header(struct packed_git *p, unsigned long offset,
|
||||
enum object_type *type, unsigned long *sizep)
|
||||
{
|
||||
unsigned shift;
|
||||
unsigned char c;
|
||||
unsigned long size;
|
||||
unsigned long used;
|
||||
|
||||
if (offset >= p->pack_size)
|
||||
if (p->pack_size <= offset)
|
||||
die("object offset outside of pack file");
|
||||
c = *((unsigned char *)p->pack_base + offset++);
|
||||
*type = (c >> 4) & 7;
|
||||
size = c & 15;
|
||||
shift = 4;
|
||||
while (c & 0x80) {
|
||||
if (offset >= p->pack_size)
|
||||
die("object offset outside of pack file");
|
||||
c = *((unsigned char *)p->pack_base + offset++);
|
||||
size += (c & 0x7f) << shift;
|
||||
shift += 7;
|
||||
}
|
||||
*sizep = size;
|
||||
return offset;
|
||||
|
||||
used = unpack_object_header_gently((unsigned char *)p->pack_base +
|
||||
offset,
|
||||
p->pack_size - offset, type, sizep);
|
||||
if (!used)
|
||||
die("object offset outside of pack file");
|
||||
|
||||
return offset + used;
|
||||
}
|
||||
|
||||
int check_reuse_pack_delta(struct packed_git *p, unsigned long offset,
|
||||
|
Loading…
Reference in New Issue
Block a user