diff mbox series

[v3,12/17] object-file.c: return -2 on "header too long" in unpack_loose_header()

Message ID patch-12.17-77f2cd439c-20210520T111610Z-avarab@gmail.com (mailing list archive)
State New, archived
Headers show
Series fsck: better "invalid object" error reporting | expand

Commit Message

Ævar Arnfjörð Bjarmason May 20, 2021, 11:23 a.m. UTC
Split up the return code for "header too long" from the generic
negative return value unpack_loose_header() returns, and report via
error() if we exceed MAX_HEADER_LEN.

As a test added earlier in this series in t1006-cat-file.sh shows
we'll correctly emit zlib errors from zlib.c already in this case, so
we have no need to carry those return codes further down the
stack. Let's instead just return -2 saying we ran into the
MAX_HEADER_LEN limit, or other negative values for "unable to unpack
<OID> header".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 object-file.c       | 15 ++++++++++-----
 object-store.h      |  6 ++++--
 t/t1006-cat-file.sh |  2 +-
 3 files changed, 15 insertions(+), 8 deletions(-)

Comments

Jonathan Tan May 27, 2021, 5:54 p.m. UTC | #1
> diff --git a/object-store.h b/object-store.h
> index 740edcac30..9accb614fc 100644
> --- a/object-store.h
> +++ b/object-store.h
> @@ -481,13 +481,15 @@ int for_each_packed_object(each_packed_object_fn, void *,
>   * unpack_loose_header() initializes the data stream needed to unpack
>   * a loose object header.
>   *
> - * Returns 0 on success. Returns negative values on error.
> + * Returns 0 on success. Returns negative values on error. If the
> + * header exceeds MAX_HEADER_LEN -2 will be returned.
>   *
>   * It will only parse up to MAX_HEADER_LEN bytes unless an optional
>   * "hdrbuf" argument is non-NULL. This is intended for use with
>   * OBJECT_INFO_ALLOW_UNKNOWN_TYPE to extract the bad type for (error)
>   * reporting. The full header will be extracted to "hdrbuf" for use
> - * with parse_loose_header().
> + * with parse_loose_header(), -2 will still be returned from this
> + * function to indicate that the header was too long.
>   */
>  int unpack_loose_header(git_zstream *stream, unsigned char *map,
>  			unsigned long mapsize, void *buffer,

Can the return type be an enum in this case?

> diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
> index d3d3fd733a..f12b06150e 100755
> --- a/t/t1006-cat-file.sh
> +++ b/t/t1006-cat-file.sh
> @@ -440,7 +440,7 @@ bogus_sha1=$(echo_without_newline "$bogus_content" | git hash-object -t $bogus_t
>  
>  test_expect_success 'die on broken object with large type under -t and -s without --allow-unknown-type' '
>  	cat >err.expect <<-EOF &&
> -	error: unable to unpack $bogus_sha1 header
> +	error: header for $bogus_sha1 too long, exceeds 32 bytes
>  	fatal: git cat-file: could not get object info
>  	EOF

Ah, the error message is much more informative - thanks.
diff mbox series

Patch

diff --git a/object-file.c b/object-file.c
index d4bdf86657..7623ada1aa 100644
--- a/object-file.c
+++ b/object-file.c
@@ -1240,10 +1240,10 @@  int unpack_loose_header(git_zstream *stream,
 	/*
 	 * We have a header longer than MAX_HEADER_LEN. We abort early
 	 * unless under we're running as e.g. "cat-file
-	 * --allow-unknown-type".
+	 * --allow-unknown-type". A -2 is "header too long"
 	 */
 	if (!header)
-		return -1;
+		return -2;
 
 	/*
 	 * buffer[0..bufsiz] was not large enough.  Copy the partial
@@ -1264,7 +1264,7 @@  int unpack_loose_header(git_zstream *stream,
 		stream->next_out = buffer;
 		stream->avail_out = bufsiz;
 	} while (status != Z_STREAM_END);
-	return -1;
+	return -2;
 }
 
 static void *unpack_loose_rest(git_zstream *stream,
@@ -1433,9 +1433,14 @@  static int loose_object_info(struct repository *r,
 	hdr_ret = unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr),
 				      allow_unknown ? &hdrbuf : NULL);
 	if (hdr_ret < 0) {
-		status = error(_("unable to unpack %s header"),
-			       oid_to_hex(oid));
+		if (hdr_ret == -2)
+			status = error(_("header for %s too long, exceeds %d bytes"),
+				       oid_to_hex(oid), MAX_HEADER_LEN);
+		else
+			status = error(_("unable to unpack %s header"),
+				       oid_to_hex(oid));
 	}
+
 	if (!status && parse_loose_header(hdrbuf.len ? hdrbuf.buf : hdr, oi) < 0) {
 		status = error(_("unable to parse %s header"), oid_to_hex(oid));
 	}
diff --git a/object-store.h b/object-store.h
index 740edcac30..9accb614fc 100644
--- a/object-store.h
+++ b/object-store.h
@@ -481,13 +481,15 @@  int for_each_packed_object(each_packed_object_fn, void *,
  * unpack_loose_header() initializes the data stream needed to unpack
  * a loose object header.
  *
- * Returns 0 on success. Returns negative values on error.
+ * Returns 0 on success. Returns negative values on error. If the
+ * header exceeds MAX_HEADER_LEN -2 will be returned.
  *
  * It will only parse up to MAX_HEADER_LEN bytes unless an optional
  * "hdrbuf" argument is non-NULL. This is intended for use with
  * OBJECT_INFO_ALLOW_UNKNOWN_TYPE to extract the bad type for (error)
  * reporting. The full header will be extracted to "hdrbuf" for use
- * with parse_loose_header().
+ * with parse_loose_header(), -2 will still be returned from this
+ * function to indicate that the header was too long.
  */
 int unpack_loose_header(git_zstream *stream, unsigned char *map,
 			unsigned long mapsize, void *buffer,
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index d3d3fd733a..f12b06150e 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -440,7 +440,7 @@  bogus_sha1=$(echo_without_newline "$bogus_content" | git hash-object -t $bogus_t
 
 test_expect_success 'die on broken object with large type under -t and -s without --allow-unknown-type' '
 	cat >err.expect <<-EOF &&
-	error: unable to unpack $bogus_sha1 header
+	error: header for $bogus_sha1 too long, exceeds 32 bytes
 	fatal: git cat-file: could not get object info
 	EOF