summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYann Collet <Cyan4973@users.noreply.github.com>2020-09-18 03:23:06 (GMT)
committerGitHub <noreply@github.com>2020-09-18 03:23:06 (GMT)
commitd568a6d15cdd06d3f131adaa32299d7535772723 (patch)
treebfc37ea083bf6a8101d2635c096370122a47ff00
parent1328c38a1507e9d6984685451909a6976a49ece9 (diff)
parent4f57219a2247a807e2b65f61501a48e37e261ab8 (diff)
downloadlz4-d568a6d15cdd06d3f131adaa32299d7535772723.zip
lz4-d568a6d15cdd06d3f131adaa32299d7535772723.tar.gz
lz4-d568a6d15cdd06d3f131adaa32299d7535772723.tar.bz2
Merge pull request #918 from lz4/usan_null
Properly fix #847
-rw-r--r--Makefile9
-rw-r--r--lib/lz4.c55
-rw-r--r--lib/lz4frame.c5
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/Makefile2
-rw-r--r--tests/frametest.c6
6 files changed, 66 insertions, 12 deletions
diff --git a/Makefile b/Makefile
index ab695ea..c1869f6 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/lib/lz4.c b/lib/lz4.c
index 0628eac..2222d53 100644
--- a/lib/lz4.c
+++ b/lib/lz4.c
@@ -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);