Browse Source

Merge branch 'jc/verify-loose-object-header'

Codepaths that read from an on-disk loose object were too loose in
validating what they are reading is a proper object file and
sometimes read past the data they read from the disk, which has
been corrected.  H/t to Gustavo Grieco for reporting.

* jc/verify-loose-object-header:
  unpack_sha1_header(): detect malformed object header
  streaming: make sure to notice corrupt object
maint
Junio C Hamano 8 years ago
parent
commit
71a57ab32d
  1. 26
      sha1_file.c
  2. 12
      streaming.c

26
sha1_file.c

@ -1646,7 +1646,9 @@ unsigned long unpack_object_header_buffer(const unsigned char *buf, @@ -1646,7 +1646,9 @@ unsigned long unpack_object_header_buffer(const unsigned char *buf,
return used;
}

int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz)
static int unpack_sha1_short_header(git_zstream *stream,
unsigned char *map, unsigned long mapsize,
void *buffer, unsigned long bufsiz)
{
/* Get the data stream */
memset(stream, 0, sizeof(*stream));
@ -1659,13 +1661,31 @@ int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long ma @@ -1659,13 +1661,31 @@ int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long ma
return git_inflate(stream, 0);
}

int unpack_sha1_header(git_zstream *stream,
unsigned char *map, unsigned long mapsize,
void *buffer, unsigned long bufsiz)
{
int status = unpack_sha1_short_header(stream, map, mapsize,
buffer, bufsiz);

if (status < Z_OK)
return status;

/* Make sure we have the terminating NUL */
if (!memchr(buffer, '\0', stream->next_out - (unsigned char *)buffer))
return -1;
return 0;
}

static int unpack_sha1_header_to_strbuf(git_zstream *stream, unsigned char *map,
unsigned long mapsize, void *buffer,
unsigned long bufsiz, struct strbuf *header)
{
int status;

status = unpack_sha1_header(stream, map, mapsize, buffer, bufsiz);
status = unpack_sha1_short_header(stream, map, mapsize, buffer, bufsiz);
if (status < Z_OK)
return -1;

/*
* Check if entire header is unpacked in the first iteration.
@ -1756,6 +1776,8 @@ static int parse_sha1_header_extended(const char *hdr, struct object_info *oi, @@ -1756,6 +1776,8 @@ static int parse_sha1_header_extended(const char *hdr, struct object_info *oi,
*/
for (;;) {
char c = *hdr++;
if (!c)
return -1;
if (c == ' ')
break;
type_len++;

12
streaming.c

@ -337,17 +337,17 @@ static open_method_decl(loose) @@ -337,17 +337,17 @@ static open_method_decl(loose)
st->u.loose.mapped = map_sha1_file(sha1, &st->u.loose.mapsize);
if (!st->u.loose.mapped)
return -1;
if (unpack_sha1_header(&st->z,
st->u.loose.mapped,
st->u.loose.mapsize,
st->u.loose.hdr,
sizeof(st->u.loose.hdr)) < 0) {
if ((unpack_sha1_header(&st->z,
st->u.loose.mapped,
st->u.loose.mapsize,
st->u.loose.hdr,
sizeof(st->u.loose.hdr)) < 0) ||
(parse_sha1_header(st->u.loose.hdr, &st->size) < 0)) {
git_inflate_end(&st->z);
munmap(st->u.loose.mapped, st->u.loose.mapsize);
return -1;
}

parse_sha1_header(st->u.loose.hdr, &st->size);
st->u.loose.hdr_used = strlen(st->u.loose.hdr) + 1;
st->u.loose.hdr_avail = st->z.total_out;
st->z_state = z_used;

Loading…
Cancel
Save