diff options
author | Yann Collet <Cyan4973@users.noreply.github.com> | 2020-09-18 03:23:06 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-18 03:23:06 (GMT) |
commit | d568a6d15cdd06d3f131adaa32299d7535772723 (patch) | |
tree | bfc37ea083bf6a8101d2635c096370122a47ff00 | |
parent | 1328c38a1507e9d6984685451909a6976a49ece9 (diff) | |
parent | 4f57219a2247a807e2b65f61501a48e37e261ab8 (diff) | |
download | lz4-d568a6d15cdd06d3f131adaa32299d7535772723.zip lz4-d568a6d15cdd06d3f131adaa32299d7535772723.tar.gz lz4-d568a6d15cdd06d3f131adaa32299d7535772723.tar.bz2 |
Merge pull request #918 from lz4/usan_null
Properly fix #847
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | lib/lz4.c | 55 | ||||
-rw-r--r-- | lib/lz4frame.c | 5 | ||||
-rw-r--r-- | tests/.gitignore | 1 | ||||
-rw-r--r-- | tests/Makefile | 2 | ||||
-rw-r--r-- | tests/frametest.c | 6 |
6 files changed, 66 insertions, 12 deletions
@@ -124,8 +124,8 @@ check: .PHONY: test test: - $(MAKE) -C $(TESTDIR) $@ - $(MAKE) -C $(EXDIR) $@ + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" $(MAKE) -C $(TESTDIR) $@ + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" $(MAKE) -C $(EXDIR) $@ clangtest: CFLAGS ?= -O3 clangtest: CFLAGS += -Werror -Wconversion -Wno-sign-conversion @@ -142,8 +142,11 @@ clangtest-native: clean @CFLAGS="-O3 -Werror -Wconversion -Wno-sign-conversion" $(MAKE) -C $(PRGDIR) native CC=clang @CFLAGS="-O3 -Werror -Wconversion -Wno-sign-conversion" $(MAKE) -C $(TESTDIR) native CC=clang +usan: CC = clang +usan: CFLAGS = -O3 -g -fsanitize=undefined -fno-sanitize-recover=undefined -fsanitize-recover=pointer-overflow +usan: LDFLAGS = $(CFLAGS) usan: clean - CC=clang CFLAGS="-O3 -g -fsanitize=undefined" $(MAKE) test FUZZER_TIME="-T30s" NB_LOOPS=-i1 + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" $(MAKE) test FUZZER_TIME="-T30s" NB_LOOPS=-i1 usan32: clean CFLAGS="-m32 -O3 -g -fsanitize=undefined" $(MAKE) test FUZZER_TIME="-T30s" NB_LOOPS=-i1 @@ -819,8 +819,12 @@ LZ4_prepareTable(LZ4_stream_t_internal* const cctx, } /** LZ4_compress_generic() : - inlined, to ensure branches are decided at compilation time */ -LZ4_FORCE_INLINE int LZ4_compress_generic( + * inlined, to ensure branches are decided at compilation time. + * Presumed already validated at this stage: + * - source != NULL + * - inputSize > 0 + */ +LZ4_FORCE_INLINE int LZ4_compress_generic_validated( LZ4_stream_t_internal* const cctx, const char* const source, char* const dest, @@ -867,11 +871,11 @@ LZ4_FORCE_INLINE int LZ4_compress_generic( U32 offset = 0; U32 forwardH; - DEBUGLOG(5, "LZ4_compress_generic: srcSize=%i, tableType=%u", inputSize, tableType); + DEBUGLOG(5, "LZ4_compress_generic_validated: srcSize=%i, tableType=%u", inputSize, tableType); + assert(ip != NULL); /* If init conditions are not met, we don't have to mark stream * as having dirty context, since no action was taken yet */ if (outputDirective == fillOutput && maxOutputSize < 1) { return 0; } /* Impossible to store anything */ - if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) { return 0; } /* Unsupported inputSize, too large (or negative) */ if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) { return 0; } /* Size too large (not within 64K limit) */ if (tableType==byPtr) assert(dictDirective==noDict); /* only supported use case with byPtr */ assert(acceleration >= 1); @@ -1204,12 +1208,52 @@ _last_literals: if (outputDirective == fillOutput) { *inputConsumed = (int) (((const char*)ip)-source); } - DEBUGLOG(5, "LZ4_compress_generic: compressed %i bytes into %i bytes", inputSize, (int)(((char*)op) - dest)); result = (int)(((char*)op) - dest); assert(result > 0); + DEBUGLOG(5, "LZ4_compress_generic: compressed %i bytes into %i bytes", inputSize, result); return result; } +/** LZ4_compress_generic() : + * inlined, to ensure branches are decided at compilation time; + * takes care of src == (NULL, 0) + * and forward the rest to LZ4_compress_generic_validated */ +LZ4_FORCE_INLINE int LZ4_compress_generic( + LZ4_stream_t_internal* const cctx, + const char* const src, + char* const dst, + const int srcSize, + int *inputConsumed, /* only written when outputDirective == fillOutput */ + const int dstCapacity, + const limitedOutput_directive outputDirective, + const tableType_t tableType, + const dict_directive dictDirective, + const dictIssue_directive dictIssue, + const int acceleration) +{ + DEBUGLOG(5, "LZ4_compress_generic: srcSize=%i, dstCapacity=%i", + srcSize, dstCapacity); + + if ((U32)srcSize > (U32)LZ4_MAX_INPUT_SIZE) { return 0; } /* Unsupported srcSize, too large (or negative) */ + if (srcSize == 0) { /* src == NULL supported if srcSize == 0 */ + DEBUGLOG(5, "Generating an empty block"); + assert(outputDirective == notLimited || dstCapacity >= 1); + assert(dst != NULL); + dst[0] = 0; + if (outputDirective == fillOutput) { + assert (inputConsumed != NULL); + *inputConsumed = 0; + } + return 1; + } + assert(src != NULL); + + return LZ4_compress_generic_validated(cctx, src, dst, srcSize, + inputConsumed, /* only written into if outputDirective == fillOutput */ + dstCapacity, outputDirective, + tableType, dictDirective, dictIssue, acceleration); +} + int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) { @@ -2077,6 +2121,7 @@ LZ4_decompress_generic( /* end of decoding */ if (endOnInput) { + DEBUGLOG(5, "decoded %i bytes", (int) (((char*)op)-dst)); return (int) (((char*)op)-dst); /* Nb of output bytes decoded */ } else { return (int) (((const char*)ip)-src); /* Nb of input bytes read */ diff --git a/lib/lz4frame.c b/lib/lz4frame.c index e11f1c8..890fc96 100644 --- a/lib/lz4frame.c +++ b/lib/lz4frame.c @@ -750,6 +750,7 @@ static size_t LZ4F_makeBlock(void* dst, (int)(srcSize), (int)(srcSize-1), level, cdict); if (cSize == 0) { /* compression failed */ + DEBUGLOG(5, "LZ4F_makeBlock: compression failed, creating a raw block (size %u)", (U32)srcSize); cSize = (U32)srcSize; LZ4F_writeLE32(cSizePtr, cSize | LZ4F_BLOCKUNCOMPRESSED_FLAG); memcpy(cSizePtr+BHSize, src, srcSize); @@ -1487,15 +1488,17 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx, size_t const nextCBlockSize = blockHeader & 0x7FFFFFFFU; size_t const crcSize = dctx->frameInfo.blockChecksumFlag * BFSize; if (blockHeader==0) { /* frameEnd signal, no more block */ + DEBUGLOG(5, "end of frame"); dctx->dStage = dstage_getSuffix; break; } if (nextCBlockSize > dctx->maxBlockSize) { return err0r(LZ4F_ERROR_maxBlockSize_invalid); } - if (LZ4F_readLE32(selectedIn) & LZ4F_BLOCKUNCOMPRESSED_FLAG) { + if (blockHeader & LZ4F_BLOCKUNCOMPRESSED_FLAG) { /* next block is uncompressed */ dctx->tmpInTarget = nextCBlockSize; + DEBUGLOG(5, "next block is uncompressed (size %u)", (U32)nextCBlockSize); if (dctx->frameInfo.blockChecksumFlag) { (void)XXH32_reset(&dctx->blockChecksum, 0); } diff --git a/tests/.gitignore b/tests/.gitignore index 0d13df8..99351af 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -11,6 +11,7 @@ fasttest roundTripTest checkTag checkFrame +decompress-partial # test artefacts tmp* diff --git a/tests/Makefile b/tests/Makefile index 5a6ec59..43c9651 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -35,7 +35,7 @@ PYTHON ?= python3 DEBUGLEVEL?= 1 DEBUGFLAGS = -g -DLZ4_DEBUG=$(DEBUGLEVEL) -CFLAGS ?= -O3 # can select custom optimization flags. For example : CFLAGS=-O2 make +CFLAGS ?= -O3 # can select custom optimization flags. Example : CFLAGS=-O2 make CFLAGS += -Wall -Wextra -Wundef -Wcast-qual -Wcast-align -Wshadow \ -Wswitch-enum -Wdeclaration-after-statement -Wstrict-prototypes \ -Wpointer-arith -Wstrict-aliasing=1 diff --git a/tests/frametest.c b/tests/frametest.c index 236a98c..54c7fd2 100644 --- a/tests/frametest.c +++ b/tests/frametest.c @@ -785,7 +785,7 @@ typedef enum { o_contiguous, o_noncontiguous, o_overwrite } o_scenario_e; static void locateBuffDiff(const void* buff1, const void* buff2, size_t size, o_scenario_e o_scenario) { - if (displayLevel >= 5) { + if (displayLevel >= 2) { size_t p=0; const BYTE* b1=(const BYTE*)buff1; const BYTE* b2=(const BYTE*)buff2; @@ -862,8 +862,10 @@ size_t test_lz4f_decompression_wBuffers( "Decompression overwrites beyond assigned dst size", op[oSizeMax], mark); } - if (LZ4F_getErrorCode(moreToFlush) == LZ4F_ERROR_contentChecksum_invalid) + if (LZ4F_getErrorCode(moreToFlush) == LZ4F_ERROR_contentChecksum_invalid) { + DISPLAYLEVEL(2, "checksum error detected \n"); locateBuffDiff(srcRef, dst, decompressedSize, o_scenario); + } if (LZ4F_isError(moreToFlush)) return moreToFlush; XXH64_update(&xxh64, op, oSize); |