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 3c08580..858db7d 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 e11db04..1a1c897 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)