Revert "lzo: properly check for overruns"
authorWilly Tarreau <w@1wt.eu>
Sat, 27 Sep 2014 10:31:36 +0000 (12:31 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 30 Oct 2014 16:35:11 +0000 (09:35 -0700)
commit af958a38a60c7ca3d8a39c918c1baa2ff7b6b233 upstream.

This reverts commit 206a81c ("lzo: properly check for overruns").

As analysed by Willem Pinckaers, this fix is still incomplete on
certain rare corner cases, and it is easier to restart from the
original code.

Reported-by: Willem Pinckaers <willem@lekkertech.net>
Cc: "Don A. Bailey" <donb@securitymouse.com>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
lib/lzo/lzo1x_decompress_safe.c

index 8563081e8da38fb81e0335d2589c9fcebcd81266..569985d522d518a8992929d5924b6a5062ff9e93 100644 (file)
 #include <linux/lzo.h>
 #include "lzodefs.h"
 
-#define HAVE_IP(t, x)                                  \
-       (((size_t)(ip_end - ip) >= (size_t)(t + x)) &&  \
-        (((t + x) >= t) && ((t + x) >= x)))
-
-#define HAVE_OP(t, x)                                  \
-       (((size_t)(op_end - op) >= (size_t)(t + x)) &&  \
-        (((t + x) >= t) && ((t + x) >= x)))
-
-#define NEED_IP(t, x)                                  \
-       do {                                            \
-               if (!HAVE_IP(t, x))                     \
-                       goto input_overrun;             \
-       } while (0)
-
-#define NEED_OP(t, x)                                  \
-       do {                                            \
-               if (!HAVE_OP(t, x))                     \
-                       goto output_overrun;            \
-       } while (0)
-
-#define TEST_LB(m_pos)                                 \
-       do {                                            \
-               if ((m_pos) < out)                      \
-                       goto lookbehind_overrun;        \
-       } while (0)
+#define HAVE_IP(x)      ((size_t)(ip_end - ip) >= (size_t)(x))
+#define HAVE_OP(x)      ((size_t)(op_end - op) >= (size_t)(x))
+#define NEED_IP(x)      if (!HAVE_IP(x)) goto input_overrun
+#define NEED_OP(x)      if (!HAVE_OP(x)) goto output_overrun
+#define TEST_LB(m_pos)  if ((m_pos) < out) goto lookbehind_overrun
 
 int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
                          unsigned char *out, size_t *out_len)
@@ -78,14 +58,14 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
                                        while (unlikely(*ip == 0)) {
                                                t += 255;
                                                ip++;
-                                               NEED_IP(1, 0);
+                                               NEED_IP(1);
                                        }
                                        t += 15 + *ip++;
                                }
                                t += 3;
 copy_literal_run:
 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
-                               if (likely(HAVE_IP(t, 15) && HAVE_OP(t, 15))) {
+                               if (likely(HAVE_IP(t + 15) && HAVE_OP(t + 15))) {
                                        const unsigned char *ie = ip + t;
                                        unsigned char *oe = op + t;
                                        do {
@@ -101,8 +81,8 @@ copy_literal_run:
                                } else
 #endif
                                {
-                                       NEED_OP(t, 0);
-                                       NEED_IP(t, 3);
+                                       NEED_OP(t);
+                                       NEED_IP(t + 3);
                                        do {
                                                *op++ = *ip++;
                                        } while (--t > 0);
@@ -115,7 +95,7 @@ copy_literal_run:
                                m_pos -= t >> 2;
                                m_pos -= *ip++ << 2;
                                TEST_LB(m_pos);
-                               NEED_OP(2, 0);
+                               NEED_OP(2);
                                op[0] = m_pos[0];
                                op[1] = m_pos[1];
                                op += 2;
@@ -139,10 +119,10 @@ copy_literal_run:
                                while (unlikely(*ip == 0)) {
                                        t += 255;
                                        ip++;
-                                       NEED_IP(1, 0);
+                                       NEED_IP(1);
                                }
                                t += 31 + *ip++;
-                               NEED_IP(2, 0);
+                               NEED_IP(2);
                        }
                        m_pos = op - 1;
                        next = get_unaligned_le16(ip);
@@ -157,10 +137,10 @@ copy_literal_run:
                                while (unlikely(*ip == 0)) {
                                        t += 255;
                                        ip++;
-                                       NEED_IP(1, 0);
+                                       NEED_IP(1);
                                }
                                t += 7 + *ip++;
-                               NEED_IP(2, 0);
+                               NEED_IP(2);
                        }
                        next = get_unaligned_le16(ip);
                        ip += 2;
@@ -174,7 +154,7 @@ copy_literal_run:
 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
                if (op - m_pos >= 8) {
                        unsigned char *oe = op + t;
-                       if (likely(HAVE_OP(t, 15))) {
+                       if (likely(HAVE_OP(t + 15))) {
                                do {
                                        COPY8(op, m_pos);
                                        op += 8;
@@ -184,7 +164,7 @@ copy_literal_run:
                                        m_pos += 8;
                                } while (op < oe);
                                op = oe;
-                               if (HAVE_IP(6, 0)) {
+                               if (HAVE_IP(6)) {
                                        state = next;
                                        COPY4(op, ip);
                                        op += next;
@@ -192,7 +172,7 @@ copy_literal_run:
                                        continue;
                                }
                        } else {
-                               NEED_OP(t, 0);
+                               NEED_OP(t);
                                do {
                                        *op++ = *m_pos++;
                                } while (op < oe);
@@ -201,7 +181,7 @@ copy_literal_run:
 #endif
                {
                        unsigned char *oe = op + t;
-                       NEED_OP(t, 0);
+                       NEED_OP(t);
                        op[0] = m_pos[0];
                        op[1] = m_pos[1];
                        op += 2;
@@ -214,15 +194,15 @@ match_next:
                state = next;
                t = next;
 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
-               if (likely(HAVE_IP(6, 0) && HAVE_OP(4, 0))) {
+               if (likely(HAVE_IP(6) && HAVE_OP(4))) {
                        COPY4(op, ip);
                        op += t;
                        ip += t;
                } else
 #endif
                {
-                       NEED_IP(t, 3);
-                       NEED_OP(t, 0);
+                       NEED_IP(t + 3);
+                       NEED_OP(t);
                        while (t > 0) {
                                *op++ = *ip++;
                                t--;