Commit 8b8f5d97 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'compress-3.16-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull compress bugfixes from Greg KH:
 "Here are two bugfixes for some compression functions that resolve some
  errors when uncompressing some pathalogical data.  Both were found by
  Don A  Bailey"

* tag 'compress-3.16-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core:
  lz4: ensure length does not wrap
  lzo: properly check for overruns
parents 04b5da4a 206204a1
...@@ -72,6 +72,8 @@ static int lz4_uncompress(const char *source, char *dest, int osize) ...@@ -72,6 +72,8 @@ static int lz4_uncompress(const char *source, char *dest, int osize)
len = *ip++; len = *ip++;
for (; len == 255; length += 255) for (; len == 255; length += 255)
len = *ip++; len = *ip++;
if (unlikely(length > (size_t)(length + len)))
goto _output_error;
length += len; length += len;
} }
......
...@@ -19,11 +19,31 @@ ...@@ -19,11 +19,31 @@
#include <linux/lzo.h> #include <linux/lzo.h>
#include "lzodefs.h" #include "lzodefs.h"
#define HAVE_IP(x) ((size_t)(ip_end - ip) >= (size_t)(x)) #define HAVE_IP(t, x) \
#define HAVE_OP(x) ((size_t)(op_end - op) >= (size_t)(x)) (((size_t)(ip_end - ip) >= (size_t)(t + x)) && \
#define NEED_IP(x) if (!HAVE_IP(x)) goto input_overrun (((t + x) >= t) && ((t + x) >= x)))
#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)
int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
unsigned char *out, size_t *out_len) unsigned char *out, size_t *out_len)
...@@ -58,14 +78,14 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, ...@@ -58,14 +78,14 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
while (unlikely(*ip == 0)) { while (unlikely(*ip == 0)) {
t += 255; t += 255;
ip++; ip++;
NEED_IP(1); NEED_IP(1, 0);
} }
t += 15 + *ip++; t += 15 + *ip++;
} }
t += 3; t += 3;
copy_literal_run: copy_literal_run:
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) #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; const unsigned char *ie = ip + t;
unsigned char *oe = op + t; unsigned char *oe = op + t;
do { do {
...@@ -81,8 +101,8 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, ...@@ -81,8 +101,8 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
} else } else
#endif #endif
{ {
NEED_OP(t); NEED_OP(t, 0);
NEED_IP(t + 3); NEED_IP(t, 3);
do { do {
*op++ = *ip++; *op++ = *ip++;
} while (--t > 0); } while (--t > 0);
...@@ -95,7 +115,7 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, ...@@ -95,7 +115,7 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
m_pos -= t >> 2; m_pos -= t >> 2;
m_pos -= *ip++ << 2; m_pos -= *ip++ << 2;
TEST_LB(m_pos); TEST_LB(m_pos);
NEED_OP(2); NEED_OP(2, 0);
op[0] = m_pos[0]; op[0] = m_pos[0];
op[1] = m_pos[1]; op[1] = m_pos[1];
op += 2; op += 2;
...@@ -119,10 +139,10 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, ...@@ -119,10 +139,10 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
while (unlikely(*ip == 0)) { while (unlikely(*ip == 0)) {
t += 255; t += 255;
ip++; ip++;
NEED_IP(1); NEED_IP(1, 0);
} }
t += 31 + *ip++; t += 31 + *ip++;
NEED_IP(2); NEED_IP(2, 0);
} }
m_pos = op - 1; m_pos = op - 1;
next = get_unaligned_le16(ip); next = get_unaligned_le16(ip);
...@@ -137,10 +157,10 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, ...@@ -137,10 +157,10 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
while (unlikely(*ip == 0)) { while (unlikely(*ip == 0)) {
t += 255; t += 255;
ip++; ip++;
NEED_IP(1); NEED_IP(1, 0);
} }
t += 7 + *ip++; t += 7 + *ip++;
NEED_IP(2); NEED_IP(2, 0);
} }
next = get_unaligned_le16(ip); next = get_unaligned_le16(ip);
ip += 2; ip += 2;
...@@ -154,7 +174,7 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, ...@@ -154,7 +174,7 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
if (op - m_pos >= 8) { if (op - m_pos >= 8) {
unsigned char *oe = op + t; unsigned char *oe = op + t;
if (likely(HAVE_OP(t + 15))) { if (likely(HAVE_OP(t, 15))) {
do { do {
COPY8(op, m_pos); COPY8(op, m_pos);
op += 8; op += 8;
...@@ -164,7 +184,7 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, ...@@ -164,7 +184,7 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
m_pos += 8; m_pos += 8;
} while (op < oe); } while (op < oe);
op = oe; op = oe;
if (HAVE_IP(6)) { if (HAVE_IP(6, 0)) {
state = next; state = next;
COPY4(op, ip); COPY4(op, ip);
op += next; op += next;
...@@ -172,7 +192,7 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, ...@@ -172,7 +192,7 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
continue; continue;
} }
} else { } else {
NEED_OP(t); NEED_OP(t, 0);
do { do {
*op++ = *m_pos++; *op++ = *m_pos++;
} while (op < oe); } while (op < oe);
...@@ -181,7 +201,7 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, ...@@ -181,7 +201,7 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
#endif #endif
{ {
unsigned char *oe = op + t; unsigned char *oe = op + t;
NEED_OP(t); NEED_OP(t, 0);
op[0] = m_pos[0]; op[0] = m_pos[0];
op[1] = m_pos[1]; op[1] = m_pos[1];
op += 2; op += 2;
...@@ -194,15 +214,15 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, ...@@ -194,15 +214,15 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
state = next; state = next;
t = next; t = next;
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
if (likely(HAVE_IP(6) && HAVE_OP(4))) { if (likely(HAVE_IP(6, 0) && HAVE_OP(4, 0))) {
COPY4(op, ip); COPY4(op, ip);
op += t; op += t;
ip += t; ip += t;
} else } else
#endif #endif
{ {
NEED_IP(t + 3); NEED_IP(t, 3);
NEED_OP(t); NEED_OP(t, 0);
while (t > 0) { while (t > 0) {
*op++ = *ip++; *op++ = *ip++;
t--; t--;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment