ALSA: seq: Fix race at timer setup and close
[pandora-kernel.git] / lib / lzo / lzo1x_decompress_safe.c
index 8563081..a1c387f 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_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
 
-#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)
+/* This MAX_255_COUNT is the maximum number of times we can add 255 to a base
+ * count without overflowing an integer. The multiply will overflow when
+ * multiplying 255 by more than MAXINT/255. The sum will overflow earlier
+ * depending on the base count. Since the base count is taken from a u8
+ * and a few bits, it is safe to assume that it will always be lower than
+ * or equal to 2*255, thus we can always prevent any overflow by accepting
+ * two less 255 steps. See Documentation/lzo.txt for more information.
+ */
+#define MAX_255_COUNT      ((((size_t)~0) / 255) - 2)
 
 int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
                          unsigned char *out, size_t *out_len)
@@ -75,17 +65,24 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
                if (t < 16) {
                        if (likely(state == 0)) {
                                if (unlikely(t == 0)) {
+                                       size_t offset;
+                                       const unsigned char *ip_last = ip;
+
                                        while (unlikely(*ip == 0)) {
-                                               t += 255;
                                                ip++;
-                                               NEED_IP(1, 0);
+                                               NEED_IP(1);
                                        }
-                                       t += 15 + *ip++;
+                                       offset = ip - ip_last;
+                                       if (unlikely(offset > MAX_255_COUNT))
+                                               return LZO_E_ERROR;
+
+                                       offset = (offset << 8) - offset;
+                                       t += offset + 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 +98,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 +112,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;
@@ -136,13 +133,20 @@ copy_literal_run:
                } else if (t >= 32) {
                        t = (t & 31) + (3 - 1);
                        if (unlikely(t == 2)) {
+                               size_t offset;
+                               const unsigned char *ip_last = ip;
+
                                while (unlikely(*ip == 0)) {
-                                       t += 255;
                                        ip++;
-                                       NEED_IP(1, 0);
+                                       NEED_IP(1);
                                }
-                               t += 31 + *ip++;
-                               NEED_IP(2, 0);
+                               offset = ip - ip_last;
+                               if (unlikely(offset > MAX_255_COUNT))
+                                       return LZO_E_ERROR;
+
+                               offset = (offset << 8) - offset;
+                               t += offset + 31 + *ip++;
+                               NEED_IP(2);
                        }
                        m_pos = op - 1;
                        next = get_unaligned_le16(ip);
@@ -154,13 +158,20 @@ copy_literal_run:
                        m_pos -= (t & 8) << 11;
                        t = (t & 7) + (3 - 1);
                        if (unlikely(t == 2)) {
+                               size_t offset;
+                               const unsigned char *ip_last = ip;
+
                                while (unlikely(*ip == 0)) {
-                                       t += 255;
                                        ip++;
-                                       NEED_IP(1, 0);
+                                       NEED_IP(1);
                                }
-                               t += 7 + *ip++;
-                               NEED_IP(2, 0);
+                               offset = ip - ip_last;
+                               if (unlikely(offset > MAX_255_COUNT))
+                                       return LZO_E_ERROR;
+
+                               offset = (offset << 8) - offset;
+                               t += offset + 7 + *ip++;
+                               NEED_IP(2);
                        }
                        next = get_unaligned_le16(ip);
                        ip += 2;
@@ -174,7 +185,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 +195,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 +203,7 @@ copy_literal_run:
                                        continue;
                                }
                        } else {
-                               NEED_OP(t, 0);
+                               NEED_OP(t);
                                do {
                                        *op++ = *m_pos++;
                                } while (op < oe);
@@ -201,7 +212,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 +225,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--;