summaryrefslogtreecommitdiff
path: root/Build/source/libs/graphite2/graphite2-src/src/Decompressor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/graphite2/graphite2-src/src/Decompressor.cpp')
-rw-r--r--Build/source/libs/graphite2/graphite2-src/src/Decompressor.cpp59
1 files changed, 35 insertions, 24 deletions
diff --git a/Build/source/libs/graphite2/graphite2-src/src/Decompressor.cpp b/Build/source/libs/graphite2/graphite2-src/src/Decompressor.cpp
index 4b8b1b4958d..26a4291392c 100644
--- a/Build/source/libs/graphite2/graphite2-src/src/Decompressor.cpp
+++ b/Build/source/libs/graphite2/graphite2-src/src/Decompressor.cpp
@@ -43,29 +43,32 @@ u32 read_literal(u8 const * &s, u8 const * const e, u32 l) {
return l;
}
-bool read_sequence(u8 const * &src, u8 const * const end, u8 const * &literal, u32 & literal_len, u32 & match_len, u32 & match_dist)
+bool read_sequence(u8 const * &src, u8 const * const end, u8 const * &literal,
+ u32 & literal_len, u32 & match_len, u32 & match_dist)
{
u8 const token = *src++;
literal_len = read_literal(src, end, token >> 4);
literal = src;
src += literal_len;
-
- if (src > end - 2 || src < literal)
+
+ // Normal exit for end of stream, wrap arround check and parital match check.
+ if (src > end - sizeof(u16) || src < literal)
return false;
match_dist = *src++;
match_dist |= *src++ << 8;
- match_len = read_literal(src, end, token & 0xf);
-
- return src <= end-5;
+ match_len = read_literal(src, end, token & 0xf) + MINMATCH;
+
+ // Malformed stream check.
+ return src <= end-MINCODA;
}
}
int lz4::decompress(void const *in, size_t in_size, void *out, size_t out_size)
{
- if (out_size <= in_size || in_size < sizeof(unsigned long)+1)
+ if (out_size <= in_size || in_size < MINSRCSIZE)
return -1;
u8 const * src = static_cast<u8 const *>(in),
@@ -74,39 +77,47 @@ int lz4::decompress(void const *in, size_t in_size, void *out, size_t out_size)
u8 * dst = static_cast<u8*>(out),
* const dst_end = dst + out_size;
-
+
+ // Check the in and out size hasn't wrapped around.
+ if (src >= src_end || dst >= dst_end)
+ return -1;
+
u32 literal_len = 0,
match_len = 0,
match_dist = 0;
-
- while (read_sequence(src, src_end, literal, literal_len, match_len, match_dist))
+
+ while (read_sequence(src, src_end, literal, literal_len, match_len,
+ match_dist))
{
if (literal_len != 0)
{
- // Copy in literal. At this point the last full sequence must be at
- // least MINMATCH + 5 from the end of the output buffer.
- if (align(literal_len) > unsigned(dst_end - dst - (MINMATCH+5)) || dst_end - dst < MINMATCH + 5)
+ // Copy in literal. At this point the a minimal literal + minminal
+ // match plus the coda (1 + 2 + 5) must be 8 bytes or more allowing
+ // us to remain within the src buffer for an overrun_copy on
+ // machines upto 64 bits.
+ if (align(literal_len) > out_size)
return -1;
dst = overrun_copy(dst, literal, literal_len);
+ out_size -= literal_len;
}
// Copy, possibly repeating, match from earlier in the
// decoded output.
u8 const * const pcpy = dst - match_dist;
if (pcpy < static_cast<u8*>(out)
- || pcpy >= dst
- || match_len > unsigned(dst_end - dst - (MINMATCH+5))
- || dst_end - dst < MINMATCH + 5)
+ || match_len > unsigned(out_size - LASTLITERALS)
+ // Wrap around checks:
+ || out_size < LASTLITERALS || pcpy >= dst)
return -1;
- if (dst > pcpy+sizeof(unsigned long)
- && dst + align(match_len + MINMATCH) <= dst_end)
- dst = overrun_copy(dst, pcpy, match_len + MINMATCH);
- else
- dst = safe_copy(dst, pcpy, match_len + MINMATCH);
+ if (dst > pcpy+sizeof(unsigned long)
+ && align(match_len) <= out_size)
+ dst = overrun_copy(dst, pcpy, match_len);
+ else
+ dst = safe_copy(dst, pcpy, match_len);
+ out_size -= match_len;
}
-
- if (literal_len > src_end - literal
- || literal_len > dst_end - dst)
+
+ if (literal > src_end - literal_len || literal_len > out_size)
return -1;
dst = fast_copy(dst, literal, literal_len);