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
This commit is contained in:
@@ -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 @@
|
|||||||
#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,
|
|||||||
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 @@ copy_literal_run:
|
|||||||
} 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 @@ copy_literal_run:
|
|||||||
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 @@ copy_literal_run:
|
|||||||
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 @@ copy_literal_run:
|
|||||||
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 @@ copy_literal_run:
|
|||||||
#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 @@ copy_literal_run:
|
|||||||
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 @@ copy_literal_run:
|
|||||||
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 @@ copy_literal_run:
|
|||||||
#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 @@ match_next:
|
|||||||
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--;
|
||||||
|
Reference in New Issue
Block a user