From: Christopher Faulet Date: Wed, 27 Jan 2021 14:17:13 +0000 (+0100) Subject: MINOR: h1: Raise the chunk size limit up to (2^52 - 1) X-Git-Tag: v2.4-dev7~72 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=405f05465252498429fb9dc38db40f0803f7cb69;p=thirdparty%2Fhaproxy.git MINOR: h1: Raise the chunk size limit up to (2^52 - 1) The allowed chunk size was historically limited to 2GB to avoid risk of overflow. This restriction is no longer necessary because the chunk size is immediately stored into a 64bits integer after the parsing. Thus, it is now possible to raise this limit. However to never fed possibly bogus values from languages that use floats for their integers, we don't get more than 13 hexa-digit (2^52 - 1). 4 petabytes is probably enough ! This patch should fix the issue #1065. It may be backported as far as 2.1. For the 2.0, the legacy HTTP part must be reviewed. But there is honestely no reason to do so. --- diff --git a/include/haproxy/h1.h b/include/haproxy/h1.h index 3c085801bb..858db7d02f 100644 --- a/include/haproxy/h1.h +++ b/include/haproxy/h1.h @@ -244,12 +244,12 @@ static inline int h1_skip_chunk_crlf(const struct buffer *buf, int start, int st * start of the body and the start of the data. Note: this function is designed * to parse wrapped CRLF at the end of the buffer. */ -static inline int h1_parse_chunk_size(const struct buffer *buf, int start, int stop, unsigned int *res) +static inline int h1_parse_chunk_size(const struct buffer *buf, int start, int stop, uint64_t *res) { const char *ptr = b_peek(buf, start); const char *ptr_old = ptr; const char *end = b_wrap(buf); - unsigned int chunk = 0; + uint64_t chunk = 0; stop -= start; // bytes left start = stop; // bytes to transfer @@ -267,9 +267,13 @@ static inline int h1_parse_chunk_size(const struct buffer *buf, int start, int s break; if (unlikely(++ptr >= end)) ptr = b_orig(buf); - if (unlikely(chunk & 0xF8000000)) /* integer overflow will occur if result >= 2GB */ - goto error; chunk = (chunk << 4) + c; + if (unlikely(chunk & 0xF0000000000000)) { + /* Don't get more than 13 hexa-digit (2^52 - 1) to never fed possibly + * bogus values from languages that use floats for their integers + */ + goto error; + } stop--; } diff --git a/src/h1_htx.c b/src/h1_htx.c index e11db04f2f..1a1c897323 100644 --- a/src/h1_htx.c +++ b/src/h1_htx.c @@ -477,7 +477,7 @@ int h1_parse_msg_data(struct h1m *h1m, struct htx **dsthtx, total += ret; } if (h1m->state == H1_MSG_CHUNK_SIZE) { - unsigned int chksz; + uint64_t chksz; ret = h1_parse_chunk_size(srcbuf, ofs, b_data(srcbuf), &chksz); if (ret <= 0)