|
@@ -25,6 +25,16 @@
|
|
|
#define NEED_OP(x) if (!HAVE_OP(x)) goto output_overrun
|
|
|
#define TEST_LB(m_pos) if ((m_pos) < out) goto lookbehind_overrun
|
|
|
|
|
|
+/* 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)
|
|
|
{
|
|
@@ -55,12 +65,19 @@ 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);
|
|
|
}
|
|
|
- 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:
|
|
@@ -116,12 +133,19 @@ 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);
|
|
|
}
|
|
|
- t += 31 + *ip++;
|
|
|
+ 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;
|
|
@@ -134,12 +158,19 @@ 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);
|
|
|
}
|
|
|
- t += 7 + *ip++;
|
|
|
+ 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);
|