]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: h1: Raise the chunk size limit up to (2^52 - 1)
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 27 Jan 2021 14:17:13 +0000 (15:17 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 28 Jan 2021 15:37:14 +0000 (16:37 +0100)
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.

include/haproxy/h1.h
src/h1_htx.c

index 3c085801bb2e76f21cd07a25d0796087ba91ebe5..858db7d02f1f1e0e3110beeb72b42abbbce2201f 100644 (file)
@@ -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--;
        }
 
index e11db04f2f8a36e96c2ff1eda0508d39428be594..1a1c897323e125bc09a1001f2d54dc6569b0d322 100644 (file)
@@ -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)