]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
CLEANUP: pattern: ensure that payload and payload_lv always stay in the buffer
authorWilly Tarreau <w@1wt.eu>
Wed, 25 Apr 2012 17:19:43 +0000 (19:19 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2012 18:57:18 +0000 (20:57 +0200)
A test was already performed which worked by pure luck due to integer types,
otherwise it would have been possible to start checking for an offset out of
the buffer's bounds if the buffer size was large enough to allow an integer
wrap. Let's perform explicit checks and use unsigned ints for offsets instead
of risking being hit later.

src/proto_tcp.c

index 69e9765f56dacff4e54fa4784e14225aacdcfee3..cc60bc37e6197b05f91ce7f09e88a6d7590b25de 100644 (file)
@@ -1486,10 +1486,10 @@ static int
 smp_fetch_payload_lv(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                      const struct arg *arg_p, struct sample *smp)
 {
-       int len_offset = arg_p[0].data.uint;
-       int len_size = arg_p[1].data.uint;
-       int buf_offset = arg_p[2].data.uint;
-       int buf_size = 0;
+       unsigned int len_offset = arg_p[0].data.uint;
+       unsigned int len_size = arg_p[1].data.uint;
+       unsigned int buf_offset;
+       unsigned int buf_size = 0;
        struct buffer *b;
        int i;
 
@@ -1512,11 +1512,6 @@ smp_fetch_payload_lv(struct proxy *px, struct session *l4, void *l7, unsigned in
                buf_size = (buf_size << 8) + ((unsigned char *)b->p)[i + len_offset];
        }
 
-       if (!buf_size) {
-               smp->flags = 0;
-               return 0;
-       }
-
        /* buf offset may be implicit, absolute or relative */
        buf_offset = len_offset + len_size;
        if (arg_p[2].type == ARGT_UINT)
@@ -1524,6 +1519,12 @@ smp_fetch_payload_lv(struct proxy *px, struct session *l4, void *l7, unsigned in
        else if (arg_p[2].type == ARGT_SINT)
                buf_offset += arg_p[2].data.sint;
 
+       if (!buf_size || buf_size > b->size || buf_offset + buf_size > b->size) {
+               /* will never match */
+               smp->flags = 0;
+               return 0;
+       }
+
        if (buf_offset + buf_size > b->i)
                goto too_short;
 
@@ -1542,8 +1543,8 @@ static int
 smp_fetch_payload(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                   const struct arg *arg_p, struct sample *smp)
 {
-       int buf_offset = arg_p[0].data.uint;
-       int buf_size = arg_p[1].data.uint;
+       unsigned int buf_offset = arg_p[0].data.uint;
+       unsigned int buf_size = arg_p[1].data.uint;
        struct buffer *b;
 
        if (!l4)
@@ -1554,6 +1555,12 @@ smp_fetch_payload(struct proxy *px, struct session *l4, void *l7, unsigned int o
        if (!b)
                return 0;
 
+       if (!buf_size || buf_size > b->size || buf_offset + buf_size > b->size) {
+               /* will never match */
+               smp->flags = 0;
+               return 0;
+       }
+
        if (buf_offset + buf_size > b->i)
                goto too_short;