pkt-line: add size parameter to packet_length()

hex2chr() takes care not to run over the end of a NUL-terminated string. It's used in packet_length(), but both callers of that function pass a four-byte buffer, making NUL-checks unnecessary. packet_length() could accidentally be used with a pointer to a buffer of unknown size at new call-sites, though, and the compiler wouldn't complain. Add a size parameter plus check, and remove the NUL-checks by calling hexval() directly. This trades three NUL checks against one size check and the ability to report the use of a short buffer at runtime. If any of the four bytes is NUL or -- more generally -- not a hexadecimal digit, then packet_length() still returns a negative value. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed Jul 7, 2023 at 23:47 UTC 3e81b896f769dfdb479363acb00bdc6b076cfd55
3 files changed +11 -6
pkt-line.c
+8 -4
@@ -373,10 +373,14 @@ static int get_packet_data(int fd, char **src_buf, size_t *src_size,
373 return ret;
374 }
375
376 -int packet_length(const char lenbuf_hex[4])
376 +int packet_length(const char lenbuf_hex[4], size_t size)
377 {
378 - int val = hex2chr(lenbuf_hex);
379 - return (val < 0) ? val : (val << 8) | hex2chr(lenbuf_hex + 2);
378 + if (size < 4)
379 + BUG("buffer too small");
380 + return hexval(lenbuf_hex[0]) << 12 |
381 + hexval(lenbuf_hex[1]) << 8 |
382 + hexval(lenbuf_hex[2]) << 4 |
383 + hexval(lenbuf_hex[3]);
384 }
385
386 static char *find_packfile_uri_path(const char *buffer)
@@ -419,7 +423,7 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
423 return PACKET_READ_EOF;
424 }
425
422 - len = packet_length(linelen);
426 + len = packet_length(linelen, sizeof(linelen));
427
428 if (len < 0) {
429 if (options & PACKET_READ_GENTLE_ON_READ_ERROR)
pkt-line.h
+1 -1
@@ -94,7 +94,7 @@ int packet_read(int fd, char *buffer, unsigned size, int options);
94 * If lenbuf_hex contains non-hex characters, return -1. Otherwise, return the
95 * numeric value of the length header.
96 */
97 -int packet_length(const char lenbuf_hex[4]);
97 +int packet_length(const char lenbuf_hex[4], size_t size);
98
99 /*
100 * Read a packetized line into a buffer like the 'packet_read()' function but
remote-curl.c
+2 -1
@@ -763,7 +763,8 @@ static void check_pktline(struct check_pktline_state *state, const char *ptr, si
763 size -= digits_remaining;
764
765 if (state->len_filled == 4) {
766 - state->remaining = packet_length(state->len_buf);
766 + state->remaining = packet_length(state->len_buf,
767 + sizeof(state->len_buf));
768 if (state->remaining < 0) {
769 die(_("remote-curl: bad line length character: %.4s"), state->len_buf);
770 } else if (state->remaining == 2) {