lib/lzo: fix bugs for very short or empty input
For very short input data (0 - 1 bytes), lzo-rle was not behaving correctly. Fix this behaviour and update documentation accordingly. For zero-length input, lzo v0 outputs an end-of-stream marker only, which was misinterpreted by lzo-rle as a bitstream version number. Ensure bitstream versions > 0 require a minimum stream length of 5. Also fixes a bug in handling the tail for very short inputs when a bitstream version is present. Link: http://lkml.kernel.org/r/20190326165857.34613-1-dave.rodgman@arm.com Signed-off-by: Dave Rodgman <dave.rodgman@arm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
6147e136ff
commit
b11ed18efa
|
@ -102,9 +102,11 @@ Byte sequences
|
||||||
dictionary which is empty, and that it will always be
|
dictionary which is empty, and that it will always be
|
||||||
invalid at this place.
|
invalid at this place.
|
||||||
|
|
||||||
17 : bitstream version. If the first byte is 17, the next byte
|
17 : bitstream version. If the first byte is 17, and compressed
|
||||||
gives the bitstream version (version 1 only). If the first byte
|
stream length is at least 5 bytes (length of shortest possible
|
||||||
is not 17, the bitstream version is 0.
|
versioned bitstream), the next byte gives the bitstream version
|
||||||
|
(version 1 only).
|
||||||
|
Otherwise, the bitstream version is 0.
|
||||||
|
|
||||||
18..21 : copy 0..3 literals
|
18..21 : copy 0..3 literals
|
||||||
state = (byte - 17) = 0..3 [ copy <state> literals ]
|
state = (byte - 17) = 0..3 [ copy <state> literals ]
|
||||||
|
|
|
@ -291,13 +291,14 @@ int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
|
||||||
{
|
{
|
||||||
const unsigned char *ip = in;
|
const unsigned char *ip = in;
|
||||||
unsigned char *op = out;
|
unsigned char *op = out;
|
||||||
|
unsigned char *data_start;
|
||||||
size_t l = in_len;
|
size_t l = in_len;
|
||||||
size_t t = 0;
|
size_t t = 0;
|
||||||
signed char state_offset = -2;
|
signed char state_offset = -2;
|
||||||
unsigned int m4_max_offset;
|
unsigned int m4_max_offset;
|
||||||
|
|
||||||
// LZO v0 will never write 17 as first byte,
|
// LZO v0 will never write 17 as first byte (except for zero-length
|
||||||
// so this is used to version the bitstream
|
// input), so this is used to version the bitstream
|
||||||
if (bitstream_version > 0) {
|
if (bitstream_version > 0) {
|
||||||
*op++ = 17;
|
*op++ = 17;
|
||||||
*op++ = bitstream_version;
|
*op++ = bitstream_version;
|
||||||
|
@ -306,6 +307,8 @@ int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
|
||||||
m4_max_offset = M4_MAX_OFFSET_V0;
|
m4_max_offset = M4_MAX_OFFSET_V0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data_start = op;
|
||||||
|
|
||||||
while (l > 20) {
|
while (l > 20) {
|
||||||
size_t ll = l <= (m4_max_offset + 1) ? l : (m4_max_offset + 1);
|
size_t ll = l <= (m4_max_offset + 1) ? l : (m4_max_offset + 1);
|
||||||
uintptr_t ll_end = (uintptr_t) ip + ll;
|
uintptr_t ll_end = (uintptr_t) ip + ll;
|
||||||
|
@ -324,7 +327,7 @@ int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
|
||||||
if (t > 0) {
|
if (t > 0) {
|
||||||
const unsigned char *ii = in + in_len - t;
|
const unsigned char *ii = in + in_len - t;
|
||||||
|
|
||||||
if (op == out && t <= 238) {
|
if (op == data_start && t <= 238) {
|
||||||
*op++ = (17 + t);
|
*op++ = (17 + t);
|
||||||
} else if (t <= 3) {
|
} else if (t <= 3) {
|
||||||
op[state_offset] |= t;
|
op[state_offset] |= t;
|
||||||
|
|
|
@ -54,11 +54,9 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
|
||||||
if (unlikely(in_len < 3))
|
if (unlikely(in_len < 3))
|
||||||
goto input_overrun;
|
goto input_overrun;
|
||||||
|
|
||||||
if (likely(*ip == 17)) {
|
if (likely(in_len >= 5) && likely(*ip == 17)) {
|
||||||
bitstream_version = ip[1];
|
bitstream_version = ip[1];
|
||||||
ip += 2;
|
ip += 2;
|
||||||
if (unlikely(in_len < 5))
|
|
||||||
goto input_overrun;
|
|
||||||
} else {
|
} else {
|
||||||
bitstream_version = 0;
|
bitstream_version = 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue