From fe66e78b96ff3b8b167f02aacbc7c0721b893611 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 13 Jan 2018 22:18:04 -0800 Subject: lz4io: fixed minor ressource leak --- programs/lz4io.c | 1 + 1 file changed, 1 insertion(+) diff --git a/programs/lz4io.c b/programs/lz4io.c index 2cf0c1c..3502038 100644 --- a/programs/lz4io.c +++ b/programs/lz4io.c @@ -459,6 +459,7 @@ static void* LZ4IO_createDict(const char* dictFilename, size_t *dictSize) { memcpy(dictBuf + circularBufSize - dictStart, circularBuf, dictLen - (circularBufSize - dictStart)); } + fclose(dictFile); free(circularBuf); return dictBuf; -- cgit v0.12 From 8e69328d6198783cde1d9fa8c18b7cdb900bbae3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 13 Jan 2018 22:24:32 -0800 Subject: programs/datagen : attempt to please static analyzer with an assert() to reduce false positive --- programs/datagen.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/programs/datagen.c b/programs/datagen.c index 7285d69..24a2da2 100644 --- a/programs/datagen.c +++ b/programs/datagen.c @@ -31,6 +31,7 @@ #include /* malloc */ #include /* FILE, fwrite */ #include /* memcpy */ +#include /************************************** @@ -78,7 +79,10 @@ static void RDG_fillLiteralDistrib(litDistribTable lt, double ld) while (u lastChar) character = firstChar; } @@ -103,13 +107,11 @@ void RDG_genBlock(void* buffer, size_t buffSize, size_t prefixSize, double match U32* seed = seedPtr; /* special case */ - while (matchProba >= 1.0) - { + while (matchProba >= 1.0) { size_t size0 = RDG_rand(seed) & 3; size0 = (size_t)1 << (16 + size0 * 2); size0 += RDG_rand(seed) & (size0-1); /* because size0 is power of 2*/ - if (buffSize < pos + size0) - { + if (buffSize < pos + size0) { memset(buffPtr+pos, 0, buffSize-pos); return; } @@ -125,11 +127,9 @@ void RDG_genBlock(void* buffer, size_t buffSize, size_t prefixSize, double match } /* Generate compressible data */ - while (pos < buffSize) - { + while (pos < buffSize) { /* Select : Literal (char) or Match (within 32K) */ - if (RDG_RAND15BITS < matchProba32) - { + if (RDG_RAND15BITS < matchProba32) { /* Copy (within 32K) */ size_t match; size_t d; @@ -140,9 +140,7 @@ void RDG_genBlock(void* buffer, size_t buffSize, size_t prefixSize, double match d = pos + length; if (d > buffSize) d = buffSize; while (pos < d) buffPtr[pos++] = buffPtr[match++]; - } - else - { + } else { /* Literal (noise) */ size_t d; size_t length = RDG_RANDLENGTH; @@ -180,12 +178,11 @@ void RDG_genOut(unsigned long long size, double matchProba, double litProba, uns RDG_genBlock(buff, RDG_DICTSIZE, 0, matchProba, lt, &seed); /* Generate compressible data */ - while (total < size) - { + while (total < size) { RDG_genBlock(buff, RDG_DICTSIZE+RDG_BLOCKSIZE, RDG_DICTSIZE, matchProba, lt, &seed); if (size-total < RDG_BLOCKSIZE) genBlockSize = (size_t)(size-total); total += genBlockSize; - fwrite(buff, 1, genBlockSize, stdout); + fwrite(buff, 1, genBlockSize, stdout); /* should check potential write error */ /* update dict */ memcpy(buff, buff + RDG_BLOCKSIZE, RDG_DICTSIZE); } -- cgit v0.12 From 4d61ebc9c8738fc79301d8ef7e27920d4b300913 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 13 Jan 2018 22:39:39 -0800 Subject: modified formulation for LZ4F_compressBound() previous version used an intentional overflow, which is defined since it uses unsigned type, but static analyzer complain about it. --- lib/lz4frame.c | 10 +++++----- lib/lz4frame.h | 38 +++++++++++++++++++------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/lib/lz4frame.c b/lib/lz4frame.c index 488ab75..62e7010 100644 --- a/lib/lz4frame.c +++ b/lib/lz4frame.c @@ -281,7 +281,7 @@ static size_t LZ4F_compressBound_internal(size_t srcSize, size_t const bufferedSize = MIN(alreadyBuffered, maxBuffered); size_t const maxSrcSize = srcSize + bufferedSize; unsigned const nbFullBlocks = (unsigned)(maxSrcSize / blockSize); - size_t const partialBlockSize = (srcSize - (srcSize==0)) & (blockSize-1); /* 0 => -1 == MAX => blockSize-1 */ + size_t const partialBlockSize = maxSrcSize & (blockSize-1); size_t const lastBlockSize = flush ? partialBlockSize : 0; unsigned const nbBlocks = nbFullBlocks + (lastBlockSize>0); @@ -604,10 +604,10 @@ size_t LZ4F_compressBegin(LZ4F_cctx* cctxPtr, } -/* LZ4F_compressBound() : - * @ return size of Dst buffer given a srcSize to handle worst case situations. - * The LZ4F_frameInfo_t structure is optional : if NULL, preferences will be set to cover worst case situations. - * This function cannot fail. +/* LZ4F_compressBound() : + * @return minimum capacity of dstBuffer for a given srcSize to handle worst case scenario. + * LZ4F_preferences_t structure is optional : if NULL, preferences will be set to cover worst case scenario. + * This function cannot fail. */ size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr) { diff --git a/lib/lz4frame.h b/lib/lz4frame.h index 675aeeb..eb55e45 100644 --- a/lib/lz4frame.h +++ b/lib/lz4frame.h @@ -248,19 +248,19 @@ LZ4FLIB_API size_t LZ4F_compressBegin(LZ4F_cctx* cctx, const LZ4F_preferences_t* prefsPtr); /*! LZ4F_compressBound() : - * Provides dstCapacity given a srcSize to guarantee operation success in worst case situations. - * prefsPtr is optional : you can provide NULL as argument, preferences will be set to cover worst case scenario. - * Result is always the same for a srcSize and prefsPtr, so it can be trusted to size reusable buffers. - * When srcSize==0, LZ4F_compressBound() provides an upper bound for LZ4F_flush() and LZ4F_compressEnd() operations. + * Provides minimum dstCapacity for a given srcSize to guarantee operation success in worst case situations. + * prefsPtr is optional : when NULL is provided, preferences will be set to cover worst case scenario. + * Result is always the same for a srcSize and prefsPtr, so it can be trusted to size reusable buffers. + * When srcSize==0, LZ4F_compressBound() provides an upper bound for LZ4F_flush() and LZ4F_compressEnd() operations. */ LZ4FLIB_API size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* prefsPtr); /*! LZ4F_compressUpdate() : - * LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary. - * An important rule is that dstCapacity MUST be large enough to ensure operation success even in worst case situations. - * This value is provided by LZ4F_compressBound(). - * If this condition is not respected, LZ4F_compress() will fail (result is an errorCode). - * LZ4F_compressUpdate() doesn't guarantee error recovery. When an error occurs, compression context must be freed or resized. + * LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary. + * An important rule is that dstCapacity MUST be large enough to ensure operation success even in worst case situations. + * This value is provided by LZ4F_compressBound(). + * If this condition is not respected, LZ4F_compress() will fail (result is an errorCode). + * LZ4F_compressUpdate() doesn't guarantee error recovery. When an error occurs, compression context must be freed or resized. * `cOptPtr` is optional : NULL can be provided, in which case all options are set to default. * @return : number of bytes written into `dstBuffer` (it can be zero, meaning input data was just buffered). * or an error code if it fails (which can be tested using LZ4F_isError()) @@ -268,8 +268,8 @@ LZ4FLIB_API size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* LZ4FLIB_API size_t LZ4F_compressUpdate(LZ4F_cctx* cctx, void* dstBuffer, size_t dstCapacity, const void* srcBuffer, size_t srcSize, const LZ4F_compressOptions_t* cOptPtr); /*! LZ4F_flush() : - * When data must be generated and sent immediately, without waiting for a block to be completely filled, - * it's possible to call LZ4_flush(). It will immediately compress any data buffered within cctx. + * When data must be generated and sent immediately, without waiting for a block to be completely filled, + * it's possible to call LZ4_flush(). It will immediately compress any data buffered within cctx. * `dstCapacity` must be large enough to ensure the operation will be successful. * `cOptPtr` is optional : it's possible to provide NULL, all options will be set to default. * @return : number of bytes written into dstBuffer (it can be zero, which means there was no data stored within cctx) @@ -303,14 +303,14 @@ typedef struct { /* Resource management */ -/*!LZ4F_createDecompressionContext() : - * Create an LZ4F_dctx object, to track all decompression operations. - * The version provided MUST be LZ4F_VERSION. - * The function provides a pointer to an allocated and initialized LZ4F_dctx object. - * The result is an errorCode, which can be tested using LZ4F_isError(). - * dctx memory can be released using LZ4F_freeDecompressionContext(); - * The result of LZ4F_freeDecompressionContext() is indicative of the current state of decompressionContext when being released. - * That is, it should be == 0 if decompression has been completed fully and correctly. +/*! LZ4F_createDecompressionContext() : + * Create an LZ4F_dctx object, to track all decompression operations. + * The version provided MUST be LZ4F_VERSION. + * The function provides a pointer to an allocated and initialized LZ4F_dctx object. + * The result is an errorCode, which can be tested using LZ4F_isError(). + * dctx memory can be released using LZ4F_freeDecompressionContext(); + * The result of LZ4F_freeDecompressionContext() is indicative of the current state of decompressionContext when being released. + * That is, it should be == 0 if decompression has been completed fully and correctly. */ LZ4FLIB_API LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_dctx** dctxPtr, unsigned version); LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_dctx* dctx); -- cgit v0.12 From 18b4c66d257a583b09e85243d21a23638b618411 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 13 Jan 2018 22:47:46 -0800 Subject: ensure a ptr is non-null with an assert() to help static analyzer understanding this condition. --- lib/lz4frame.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/lz4frame.c b/lib/lz4frame.c index 62e7010..b5c868f 100644 --- a/lib/lz4frame.c +++ b/lib/lz4frame.c @@ -70,6 +70,14 @@ You can contact the author at : /*-************************************ * Debug **************************************/ +#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=1) +# include +#else +# ifndef assert +# define assert(condition) ((void)0) +# endif +#endif + #define LZ4F_STATIC_ASSERT(c) { enum { LZ4F_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ @@ -1439,6 +1447,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx, case dstage_decodeCBlock: if (dctx->frameInfo.blockChecksumFlag) { dctx->tmpInTarget -= 4; + assert(selectedIn != NULL); /* selectedIn is defined at this stage (either srcPtr, or dctx->tmpIn) */ { U32 const readBlockCrc = LZ4F_readLE32(selectedIn + dctx->tmpInTarget); U32 const calcBlockCrc = XXH32(selectedIn, dctx->tmpInTarget, 0); if (readBlockCrc != calcBlockCrc) -- cgit v0.12 From 75e22d133e0726c6e3d7124eb18edfb9cb09400e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 13 Jan 2018 22:52:17 -0800 Subject: minor : try to tell static analyzer that we don't care if fseek() fails as already explained in comments. --- programs/lz4io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/lz4io.c b/programs/lz4io.c index 3502038..927928a 100644 --- a/programs/lz4io.c +++ b/programs/lz4io.c @@ -429,7 +429,7 @@ static void* LZ4IO_createDict(const char* dictFilename, size_t *dictSize) { /* opportunistically seek to the part of the file we care about. If this */ /* fails it's not a problem since we'll just read everything anyways. */ if (strcmp(dictFilename, stdinmark)) { - UTIL_fseek(dictFile, -LZ4_MAX_DICT_SIZE, SEEK_END); + (void)UTIL_fseek(dictFile, -LZ4_MAX_DICT_SIZE, SEEK_END); } do { -- cgit v0.12