object-file.c: return ULHR_TOO_LONG on "header too long"

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 ULHR_TOO_LONG 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> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ævar Arnfjörð Bjarmason committed Oct 1, 2021 at 11:16 UTC 5848fb11acd0b6aad6ba9e3e71bd91485e0d4c71
4 files changed +13 -5
cache.h
+4 -1
@@ -1311,16 +1311,19 @@ int git_open_cloexec(const char *name, int flags);
1311 *
1312 * - ULHR_OK on success
1313 * - ULHR_BAD on error
1314 + * - ULHR_TOO_LONG if the header was too long
1315 *
1316 * It will only parse up to MAX_HEADER_LEN bytes unless an optional
1317 * "hdrbuf" argument is non-NULL. This is intended for use with
1318 * OBJECT_INFO_ALLOW_UNKNOWN_TYPE to extract the bad type for (error)
1319 * reporting. The full header will be extracted to "hdrbuf" for use
1319 - * with parse_loose_header().
1320 + * with parse_loose_header(), ULHR_TOO_LONG will still be returned
1321 + * from this function to indicate that the header was too long.
1322 */
1323 enum unpack_loose_header_result {
1324 ULHR_OK,
1325 ULHR_BAD,
1326 + ULHR_TOO_LONG,
1327 };
1328 enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
1329 unsigned char *map,
object-file.c
+6 -2
@@ -1245,7 +1245,7 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
1245 * --allow-unknown-type".
1246 */
1247 if (!header)
1248 - return ULHR_BAD;
1248 + return ULHR_TOO_LONG;
1249
1250 /*
1251 * buffer[0..bufsiz] was not large enough. Copy the partial
@@ -1266,7 +1266,7 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
1266 stream->next_out = buffer;
1267 stream->avail_out = bufsiz;
1268 } while (status != Z_STREAM_END);
1269 - return ULHR_BAD;
1269 + return ULHR_TOO_LONG;
1270 }
1271
1272 static void *unpack_loose_rest(git_zstream *stream,
@@ -1439,6 +1439,10 @@ static int loose_object_info(struct repository *r,
1439 status = error(_("unable to unpack %s header"),
1440 oid_to_hex(oid));
1441 break;
1442 + case ULHR_TOO_LONG:
1443 + status = error(_("header for %s too long, exceeds %d bytes"),
1444 + oid_to_hex(oid), MAX_HEADER_LEN);
1445 + break;
1446 }
1447
1448 if (status < 0) {
streaming.c
+1
@@ -235,6 +235,7 @@ static int open_istream_loose(struct git_istream *st, struct repository *r,
235 case ULHR_OK:
236 break;
237 case ULHR_BAD:
238 + case ULHR_TOO_LONG:
239 goto error;
240 }
241 if (parse_loose_header(st->u.loose.hdr, &oi, 0) < 0)
t/t1006-cat-file.sh
+2 -2
@@ -356,12 +356,12 @@ do
356 if test "$arg2" = "-p"
357 then
358 cat >expect <<-EOF
359 - error: unable to unpack $bogus_long_sha1 header
359 + error: header for $bogus_long_sha1 too long, exceeds 32 bytes
360 fatal: Not a valid object name $bogus_long_sha1
361 EOF
362 else
363 cat >expect <<-EOF
364 - error: unable to unpack $bogus_long_sha1 header
364 + error: header for $bogus_long_sha1 too long, exceeds 32 bytes
365 fatal: git cat-file: could not get object info
366 EOF
367 fi &&