Download raw body.
fix object header parser for zero-length object headers
On Fri, Jan 28, 2022 at 01:02:28PM +0100, Stefan Sperling wrote: > 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? 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) > -- Tracey Emery
fix object header parser for zero-length object headers