Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8b8f5d97 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -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;
		}
		}


+41 −21
Original line number Original line Diff line number Diff line
@@ -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--;