mirror of
https://github.com/lz4/lz4.git
synced 2024-11-25 02:43:36 +08:00
Fix LZ4_decompress_fast_continue() bug
It specified the external dictionary location incorrectly. Add tests that expose this bug with both normal compilation and ASAN.
This commit is contained in:
parent
8195ba8f7b
commit
920bf21714
@ -1366,7 +1366,7 @@ int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const ch
|
||||
lz4sd->prefixEnd += originalSize;
|
||||
} else {
|
||||
lz4sd->extDictSize = lz4sd->prefixSize;
|
||||
lz4sd->externalDict = (BYTE*)dest - lz4sd->extDictSize;
|
||||
lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
|
||||
result = LZ4_decompress_generic(source, dest, 0, originalSize,
|
||||
endOnOutputSize, full, 0,
|
||||
usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
|
||||
|
@ -97,6 +97,9 @@ frametest: $(LZ4DIR)/lz4frame.o $(LZ4DIR)/lz4.o $(LZ4DIR)/lz4hc.o $(LZ4DIR)/xxha
|
||||
frametest32: $(LZ4DIR)/lz4frame.c $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c $(LZ4DIR)/xxhash.c frametest.c
|
||||
$(CC) -m32 $(FLAGS) $^ -o $@$(EXT)
|
||||
|
||||
fasttest: $(LZ4DIR)/lz4.o fasttest.c
|
||||
$(CC) $(FLAGS) $^ -o $@$(EXT)
|
||||
|
||||
datagen : $(PRGDIR)/datagen.c datagencli.c
|
||||
$(CC) $(FLAGS) -I$(PRGDIR) $^ -o $@$(EXT)
|
||||
|
||||
@ -119,7 +122,7 @@ versionsTest:
|
||||
#FreeBSD targets
|
||||
ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU FreeBSD))
|
||||
|
||||
test: test-lz4 test-lz4c test-frametest test-fullbench test-fuzzer test-mem
|
||||
test: test-lz4 test-lz4c test-fasttest test-frametest test-fullbench test-fuzzer test-mem
|
||||
|
||||
test32: test-lz4c32 test-frametest32 test-fullbench32 test-fuzzer32 test-mem32
|
||||
|
||||
@ -267,6 +270,9 @@ test-frametest: frametest
|
||||
test-frametest32: frametest32
|
||||
./frametest32 $(FUZZER_TIME)
|
||||
|
||||
test-fasttest: fasttest
|
||||
./fasttest
|
||||
|
||||
test-mem: lz4 datagen fuzzer frametest fullbench
|
||||
@echo "\n ---- valgrind tests : memory analyzer ----"
|
||||
valgrind --leak-check=yes --error-exitcode=1 ./datagen -g50M > $(VOID)
|
||||
|
138
tests/fasttest.c
Normal file
138
tests/fasttest.c
Normal file
@ -0,0 +1,138 @@
|
||||
/**************************************
|
||||
* Compiler Options
|
||||
**************************************/
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# define _CRT_SECURE_NO_WARNINGS // for MSVC
|
||||
# define snprintf sprintf_s
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wmissing-braces" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************
|
||||
* Includes
|
||||
**************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "lz4.h"
|
||||
|
||||
|
||||
/* Returns non-zero on failure. */
|
||||
int test_compress(const char *input, int inSize, char *output, int outSize)
|
||||
{
|
||||
LZ4_stream_t lz4Stream_body = { 0 };
|
||||
LZ4_stream_t* lz4Stream = &lz4Stream_body;
|
||||
|
||||
int inOffset = 0;
|
||||
int outOffset = 0;
|
||||
|
||||
if (inSize & 3) return -1;
|
||||
|
||||
while (inOffset < inSize) {
|
||||
const int length = inSize >> 2;
|
||||
if (inSize > 1024) return -2;
|
||||
if (outSize - (outOffset + 8) < LZ4_compressBound(length)) return -3;
|
||||
{
|
||||
const int outBytes = LZ4_compress_continue(
|
||||
lz4Stream, input + inOffset, output + outOffset + 8, length);
|
||||
if(outBytes <= 0) return -4;
|
||||
memcpy(output + outOffset, &length, 4); /* input length */
|
||||
memcpy(output + outOffset + 4, &outBytes, 4); /* output length */
|
||||
inOffset += length;
|
||||
outOffset += outBytes + 8;
|
||||
}
|
||||
}
|
||||
if (outOffset + 8 > outSize) return -5;
|
||||
memset(output + outOffset, 0, 4);
|
||||
memset(output + outOffset + 4, 0, 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void swap(void **a, void **b) {
|
||||
void *tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
/* Returns non-zero on failure. Not a safe function. */
|
||||
int test_decompress(const char *uncompressed, const char *compressed)
|
||||
{
|
||||
char outBufferA[1024];
|
||||
char spacing; /* So prefixEnd != dest */
|
||||
char outBufferB[1024];
|
||||
char *output = outBufferA;
|
||||
char *lastOutput = outBufferB;
|
||||
LZ4_streamDecode_t lz4StreamDecode_body = { 0 };
|
||||
LZ4_streamDecode_t* lz4StreamDecode = &lz4StreamDecode_body;
|
||||
int offset = 0;
|
||||
int unOffset = 0;
|
||||
int lastBytes = 0;
|
||||
|
||||
(void)spacing;
|
||||
|
||||
for(;;) {
|
||||
int32_t bytes;
|
||||
int32_t unBytes;
|
||||
/* Read uncompressed size and compressed size */
|
||||
memcpy(&unBytes, compressed + offset, 4);
|
||||
memcpy(&bytes, compressed + offset + 4, 4);
|
||||
offset += 8;
|
||||
/* Check if we reached end of stream or error */
|
||||
if(bytes == 0 && unBytes == 0) return 0;
|
||||
if(bytes <= 0 || unBytes <= 0 || unBytes > 1024) return 1;
|
||||
|
||||
/* Put the last output in the dictionary */
|
||||
LZ4_setStreamDecode(lz4StreamDecode, lastOutput, lastBytes);
|
||||
/* Decompress */
|
||||
bytes = LZ4_decompress_fast_continue(
|
||||
lz4StreamDecode, compressed + offset, output, unBytes);
|
||||
if(bytes <= 0) return 2;
|
||||
/* Check result */
|
||||
{
|
||||
int r = memcmp(uncompressed + unOffset, output, unBytes);
|
||||
if (r) return 3;
|
||||
}
|
||||
swap((void**)&output, (void**)&lastOutput);
|
||||
offset += bytes;
|
||||
unOffset += unBytes;
|
||||
lastBytes = unBytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char input[] =
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello!"
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello!"
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello!"
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello!"
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello!"
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello!"
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello!"
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello!"
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello!"
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello!"
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello!"
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello!"
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello!"
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello!"
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello!"
|
||||
"Hello Hello Hello Hello Hello Hello Hello Hello";
|
||||
char output[LZ4_COMPRESSBOUND(4096)];
|
||||
int r;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
if ((r = test_compress(input, sizeof(input), output, sizeof(output)))) {
|
||||
return r;
|
||||
}
|
||||
if ((r = test_decompress(input, output))) {
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user