Download raw body.
fix object header parser for zero-length object headers
By code inspection I found that got_object_read_header() will pass
non-NUL-terminated strings into strnlen() if an object file is empty.
The patch below tidies up relevant code, makes the parser more robust,
and takes potential empty input into account.
The header is simple, a tag string which identifies the object type
such as "commit ", followed by the object size encoded as an ASCII
number string, followed by \0.
If you want to see an example, just decompress any object from one of the
directories "objects/[0-9a-f][0-9a-f]/" in any repository, using the
script util/uncompress-loose-object.sh from the got source tree.
You need to run 'pkg_add qpdf' to install zlib-flate which is used by
this script.
ok?
diff 8669fd5c8f1a790cfe005834fd9fbd34ceef71f6 be9053848281194022cfb726e21a361af43cadba
blob - b4f415940ee578ecafa1e8ceca60032674013904
blob + 799a16dd7e542f69c5669859576f374888904a16
--- lib/object_parse.c
+++ lib/object_parse.c
@@ -196,13 +196,12 @@ got_object_parse_header(struct got_object **obj, char
GOT_OBJ_TYPE_TAG,
};
int type = 0;
- size_t size = 0, hdrlen = 0;
+ size_t size = 0;
size_t i;
*obj = NULL;
- hdrlen = strnlen(buf, len) + 1 /* '\0' */;
- if (hdrlen > len)
+ if (memchr(buf, '\0', len) == NULL)
return got_error(GOT_ERR_BAD_OBJ_HDR);
for (i = 0; i < nitems(obj_labels); i++) {
@@ -210,12 +209,10 @@ got_object_parse_header(struct got_object **obj, char
size_t label_len = strlen(label);
const char *errstr;
- if (strncmp(buf, label, label_len) != 0)
+ if (len <= label_len || strncmp(buf, label, label_len) != 0)
continue;
type = obj_types[i];
- if (len <= label_len)
- return got_error(GOT_ERR_BAD_OBJ_HDR);
size = strtonum(buf + label_len, 0, LONG_MAX, &errstr);
if (errstr != NULL)
return got_error(GOT_ERR_BAD_OBJ_HDR);
@@ -229,7 +226,7 @@ got_object_parse_header(struct got_object **obj, char
if (*obj == NULL)
return got_error_from_errno("calloc");
(*obj)->type = type;
- (*obj)->hdrlen = hdrlen;
+ (*obj)->hdrlen = strnlen(buf, len) + 1 /* '\0' */;
(*obj)->size = size;
return NULL;
}
@@ -249,6 +246,7 @@ got_object_read_header(struct got_object **obj, int fd
buf = malloc(zbsize);
if (buf == NULL)
return got_error_from_errno("malloc");
+ buf[0] = '\0';
err = got_inflate_init(&zb, buf, zbsize, NULL);
if (err)
fix object header parser for zero-length object headers