Skip to content

Commit b11ed18

Browse files
daverodgmantorvalds
authored andcommitted
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>
1 parent 6147e13 commit b11ed18

File tree

3 files changed

+12
-9
lines changed

3 files changed

+12
-9
lines changed

Documentation/lzo.txt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,11 @@ Byte sequences
102102
dictionary which is empty, and that it will always be
103103
invalid at this place.
104104

105-
17 : bitstream version. If the first byte is 17, the next byte
106-
gives the bitstream version (version 1 only). If the first byte
107-
is not 17, the bitstream version is 0.
105+
17 : bitstream version. If the first byte is 17, and compressed
106+
stream length is at least 5 bytes (length of shortest possible
107+
versioned bitstream), the next byte gives the bitstream version
108+
(version 1 only).
109+
Otherwise, the bitstream version is 0.
108110

109111
18..21 : copy 0..3 literals
110112
state = (byte - 17) = 0..3 [ copy <state> literals ]

lib/lzo/lzo1x_compress.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,13 +291,14 @@ int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
291291
{
292292
const unsigned char *ip = in;
293293
unsigned char *op = out;
294+
unsigned char *data_start;
294295
size_t l = in_len;
295296
size_t t = 0;
296297
signed char state_offset = -2;
297298
unsigned int m4_max_offset;
298299

299-
// LZO v0 will never write 17 as first byte,
300-
// so this is used to version the bitstream
300+
// LZO v0 will never write 17 as first byte (except for zero-length
301+
// input), so this is used to version the bitstream
301302
if (bitstream_version > 0) {
302303
*op++ = 17;
303304
*op++ = bitstream_version;
@@ -306,6 +307,8 @@ int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
306307
m4_max_offset = M4_MAX_OFFSET_V0;
307308
}
308309

310+
data_start = op;
311+
309312
while (l > 20) {
310313
size_t ll = l <= (m4_max_offset + 1) ? l : (m4_max_offset + 1);
311314
uintptr_t ll_end = (uintptr_t) ip + ll;
@@ -324,7 +327,7 @@ int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
324327
if (t > 0) {
325328
const unsigned char *ii = in + in_len - t;
326329

327-
if (op == out && t <= 238) {
330+
if (op == data_start && t <= 238) {
328331
*op++ = (17 + t);
329332
} else if (t <= 3) {
330333
op[state_offset] |= t;

lib/lzo/lzo1x_decompress_safe.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,9 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
5454
if (unlikely(in_len < 3))
5555
goto input_overrun;
5656

57-
if (likely(*ip == 17)) {
57+
if (likely(in_len >= 5) && likely(*ip == 17)) {
5858
bitstream_version = ip[1];
5959
ip += 2;
60-
if (unlikely(in_len < 5))
61-
goto input_overrun;
6260
} else {
6361
bitstream_version = 0;
6462
}

0 commit comments

Comments
 (0)