From c491df54eca484654d14b3608406c35ab7366ec6 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 4 Apr 2019 17:03:05 -0700 Subject: created LZ4_initStreamHC() - promoted LZ4_resetStreamHC_fast() to stable - moved LZ4_resetStreamHC() to deprecated (but do not generate a warning yet) - Updated doc, to highlight difference between init and reset - switched all invocations of LZ4_resetStreamHC() onto LZ4_initStreamHC() - misc: ensure `make all` also builds /tests --- Makefile | 6 ++- lib/lz4frame.c | 126 ++++++++++++++++++++++++++++----------------------- lib/lz4hc.c | 132 +++++++++++++++++++++++++++++------------------------- lib/lz4hc.h | 75 ++++++++++++++++++++----------- tests/fullbench.c | 15 ++++--- tests/fuzzer.c | 42 ++++++++--------- 6 files changed, 225 insertions(+), 171 deletions(-) diff --git a/Makefile b/Makefile index df54c73..f3c6ce2 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,7 @@ endif default: lib-release lz4-release .PHONY: all -all: allmost examples manuals +all: allmost examples manuals build_tests .PHONY: allmost allmost: lib lz4 @@ -75,6 +75,10 @@ examples: liblz4.a manuals: @$(MAKE) -C contrib/gen_manual $@ +.PHONY: build_tests +build_tests: + @$(MAKE) -C $(TESTDIR) all + .PHONY: clean clean: @$(MAKE) -C $(LZ4DIR) $@ > $(VOID) diff --git a/lib/lz4frame.c b/lib/lz4frame.c index 2164470..f076204 100644 --- a/lib/lz4frame.c +++ b/lib/lz4frame.c @@ -1,41 +1,44 @@ /* -LZ4 auto-framing library -Copyright (C) 2011-2016, Yann Collet. - -BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -You can contact the author at : -- LZ4 homepage : http://www.lz4.org -- LZ4 source repository : https://github.com/lz4/lz4 -*/ + * LZ4 auto-framing library + * Copyright (C) 2011-2016, Yann Collet. + * + * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at : + * - LZ4 homepage : http://www.lz4.org + * - LZ4 source repository : https://github.com/lz4/lz4 + */ /* LZ4F is a stand-alone API to create LZ4-compressed Frames -* in full conformance with specification v1.6.1 . -* This library rely upon memory management capabilities. -* */ + * in full conformance with specification v1.6.1 . + * This library rely upon memory management capabilities (malloc, free) + * provided either by , + * or redirected towards another library of user's choice + * (see Memory Routines below). + */ /*-************************************ @@ -62,20 +65,27 @@ You can contact the author at : /*-************************************ * Memory routines **************************************/ +/* + * User may redirect invocations of + * malloc(), calloc() and free() + * towards another library or solution of their choice + * by modifying below section. + */ #include /* malloc, calloc, free */ #define ALLOC(s) malloc(s) -#ifndef LZ4_SRC_INCLUDED -#define ALLOC_AND_ZERO(s) calloc(1,(s)) +#ifndef LZ4_SRC_INCLUDED /* avoid redefinition when sources are coalesced */ +# define ALLOC_AND_ZERO(s) calloc(1,(s)) #endif #define FREEMEM(p) free(p) + #include /* memset, memcpy, memmove */ -#ifndef LZ4_SRC_INCLUDED -#define MEM_INIT memset +#ifndef LZ4_SRC_INCLUDED /* avoid redefinition when sources are coalesced */ +# define MEM_INIT memset #endif /*-************************************ -* Includes +* Library declarations **************************************/ #define LZ4F_STATIC_LINKING_ONLY #include "lz4frame.h" @@ -606,11 +616,12 @@ size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr, if (cctxPtr->lz4CtxAlloc < ctxTypeID) { FREEMEM(cctxPtr->lz4CtxPtr); if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) { - cctxPtr->lz4CtxPtr = (void*)LZ4_createStream(); + cctxPtr->lz4CtxPtr = LZ4_createStream(); } else { - cctxPtr->lz4CtxPtr = (void*)LZ4_createStreamHC(); + cctxPtr->lz4CtxPtr = LZ4_createStreamHC(); } - if (cctxPtr->lz4CtxPtr == NULL) return err0r(LZ4F_ERROR_allocation_failed); + if (cctxPtr->lz4CtxPtr == NULL) + return err0r(LZ4F_ERROR_allocation_failed); cctxPtr->lz4CtxAlloc = ctxTypeID; cctxPtr->lz4CtxState = ctxTypeID; } else if (cctxPtr->lz4CtxState != ctxTypeID) { @@ -619,7 +630,7 @@ size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr, if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) { LZ4_resetStream((LZ4_stream_t *) cctxPtr->lz4CtxPtr); } else { - LZ4_resetStreamHC((LZ4_streamHC_t *) cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel); + LZ4_initStreamHC((LZ4_streamHC_t *) cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel); } cctxPtr->lz4CtxState = ctxTypeID; } @@ -1268,9 +1279,10 @@ static void LZ4F_updateDict(LZ4F_dctx* dctx, return; } - if (dstPtr - dstBufferStart + dstSize >= 64 KB) { /* history in dstBuffer becomes large enough to become dictionary */ + assert(dstPtr >= dstBufferStart); + if ((size_t)(dstPtr - dstBufferStart) + dstSize >= 64 KB) { /* history in dstBuffer becomes large enough to become dictionary */ dctx->dict = (const BYTE*)dstBufferStart; - dctx->dictSize = dstPtr - dstBufferStart + dstSize; + dctx->dictSize = (size_t)(dstPtr - dstBufferStart) + dstSize; return; } @@ -1286,7 +1298,7 @@ static void LZ4F_updateDict(LZ4F_dctx* dctx, } if (withinTmp) { /* copy relevant dict portion in front of tmpOut within tmpOutBuffer */ - size_t const preserveSize = dctx->tmpOut - dctx->tmpOutBuffer; + size_t const preserveSize = (size_t)(dctx->tmpOut - dctx->tmpOutBuffer); size_t copySize = 64 KB - dctx->tmpOutSize; const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart; if (dctx->tmpOutSize > 64 KB) copySize = 0; @@ -1371,7 +1383,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx, case dstage_getFrameHeader: if ((size_t)(srcEnd-srcPtr) >= maxFHSize) { /* enough to decode - shortcut */ - size_t const hSize = LZ4F_decodeHeader(dctx, srcPtr, srcEnd-srcPtr); /* will update dStage appropriately */ + size_t const hSize = LZ4F_decodeHeader(dctx, srcPtr, (size_t)(srcEnd-srcPtr)); /* will update dStage appropriately */ if (LZ4F_isError(hSize)) return hSize; srcPtr += hSize; break; @@ -1593,13 +1605,13 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx, dict, (int)dictSize); if (decodedSize < 0) return err0r(LZ4F_ERROR_GENERIC); /* decompression failed */ if (dctx->frameInfo.contentChecksumFlag) - XXH32_update(&(dctx->xxh), dstPtr, decodedSize); + XXH32_update(&(dctx->xxh), dstPtr, (size_t)decodedSize); if (dctx->frameInfo.contentSize) - dctx->frameRemainingSize -= decodedSize; + dctx->frameRemainingSize -= (size_t)decodedSize; /* dictionary management */ if (dctx->frameInfo.blockMode==LZ4F_blockLinked) - LZ4F_updateDict(dctx, dstPtr, decodedSize, dstStart, 0); + LZ4F_updateDict(dctx, dstPtr, (size_t)decodedSize, dstStart, 0); dstPtr += decodedSize; dctx->dStage = dstage_getBlockHeader; @@ -1636,10 +1648,10 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx, if (decodedSize < 0) /* decompression failed */ return err0r(LZ4F_ERROR_decompressionFailed); if (dctx->frameInfo.contentChecksumFlag) - XXH32_update(&(dctx->xxh), dctx->tmpOut, decodedSize); + XXH32_update(&(dctx->xxh), dctx->tmpOut, (size_t)decodedSize); if (dctx->frameInfo.contentSize) - dctx->frameRemainingSize -= decodedSize; - dctx->tmpOutSize = decodedSize; + dctx->frameRemainingSize -= (size_t)decodedSize; + dctx->tmpOutSize = (size_t)decodedSize; dctx->tmpOutStart = 0; dctx->dStage = dstage_flushOut; } @@ -1767,7 +1779,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx, && ((unsigned)(dctx->dStage)-2 < (unsigned)(dstage_getSuffix)-2) ) /* valid stages : [init ... getSuffix[ */ { if (dctx->dStage == dstage_flushOut) { - size_t const preserveSize = dctx->tmpOut - dctx->tmpOutBuffer; + size_t const preserveSize = (size_t)(dctx->tmpOut - dctx->tmpOutBuffer); size_t copySize = 64 KB - dctx->tmpOutSize; const BYTE* oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart; if (dctx->tmpOutSize > 64 KB) copySize = 0; @@ -1791,8 +1803,8 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx, } } - *srcSizePtr = (srcPtr - srcStart); - *dstSizePtr = (dstPtr - dstStart); + *srcSizePtr = (size_t)(srcPtr - srcStart); + *dstSizePtr = (size_t)(dstPtr - dstStart); return nextSrcSizeHint; } diff --git a/lib/lz4hc.c b/lib/lz4hc.c index 129bf0c..644b8eb 100644 --- a/lib/lz4hc.c +++ b/lib/lz4hc.c @@ -105,7 +105,7 @@ static void LZ4HC_clearTables (LZ4HC_CCtx_internal* hc4) static void LZ4HC_init (LZ4HC_CCtx_internal* hc4, const BYTE* start) { - uptrval startingOffset = hc4->end - hc4->base; + uptrval startingOffset = (uptrval)(hc4->end - hc4->base); if (startingOffset > 1 GB) { LZ4HC_clearTables(hc4); startingOffset = 0; @@ -266,7 +266,7 @@ LZ4HC_InsertAndGetWiderMatch ( if (LZ4_read16(iLowLimit + longest - 1) == LZ4_read16(matchPtr - lookBackLength + longest - 1)) { if (LZ4_read32(matchPtr) == pattern) { int const back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, lowPrefixPtr) : 0; - matchLength = MINMATCH + LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit); + matchLength = MINMATCH + (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit); matchLength -= back; if (matchLength > longest) { longest = matchLength; @@ -280,7 +280,7 @@ LZ4HC_InsertAndGetWiderMatch ( int back = 0; const BYTE* vLimit = ip + (dictLimit - matchIndex); if (vLimit > iHighLimit) vLimit = iHighLimit; - matchLength = LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH; + matchLength = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH; if ((ip+matchLength == vLimit) && (vLimit < iHighLimit)) matchLength += LZ4_count(ip+matchLength, lowPrefixPtr, iHighLimit); back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictStart) : 0; @@ -293,11 +293,11 @@ LZ4HC_InsertAndGetWiderMatch ( if (chainSwap && matchLength==longest) { /* better match => select a better chain */ assert(lookBackLength==0); /* search forward only */ - if (matchIndex + longest <= ipIndex) { + if (matchIndex + (U32)longest <= ipIndex) { U32 distanceToNextMatch = 1; int pos; for (pos = 0; pos <= longest - MINMATCH; pos++) { - U32 const candidateDist = DELTANEXTU16(chainTable, matchIndex + pos); + U32 const candidateDist = DELTANEXTU16(chainTable, matchIndex + (U32)pos); if (candidateDist > distanceToNextMatch) { distanceToNextMatch = candidateDist; matchChainPos = pos; @@ -353,12 +353,14 @@ LZ4HC_InsertAndGetWiderMatch ( } } /* PA optimization */ /* follow current chain */ - matchIndex -= DELTANEXTU16(chainTable, matchIndex+matchChainPos); + matchIndex -= DELTANEXTU16(chainTable, matchIndex + matchChainPos); } /* while ((matchIndex>=lowestMatchIndex) && (nbAttempts)) */ - if (dict == usingDictCtxHc && nbAttempts && ipIndex - lowestMatchIndex < MAX_DISTANCE) { - size_t const dictEndOffset = dictCtx->end - dictCtx->base; + if ( dict == usingDictCtxHc + && nbAttempts + && ipIndex - lowestMatchIndex < MAX_DISTANCE) { + size_t const dictEndOffset = (size_t)(dictCtx->end - dictCtx->base); U32 dictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)]; assert(dictEndOffset <= 1 GB); matchIndex = dictMatchIndex + lowestMatchIndex - (U32)dictEndOffset; @@ -370,22 +372,19 @@ LZ4HC_InsertAndGetWiderMatch ( int back = 0; const BYTE* vLimit = ip + (dictEndOffset - dictMatchIndex); if (vLimit > iHighLimit) vLimit = iHighLimit; - mlt = LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH; + mlt = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH; back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictCtx->base + dictCtx->dictLimit) : 0; mlt -= back; if (mlt > longest) { longest = mlt; *matchpos = base + matchIndex + back; *startpos = ip + back; - } - } + } } { U32 const nextOffset = DELTANEXTU16(dictCtx->chainTable, dictMatchIndex); dictMatchIndex -= nextOffset; matchIndex -= nextOffset; - } - } - } + } } } return longest; } @@ -518,7 +517,7 @@ LZ4_FORCE_INLINE int LZ4HC_compress_hashChain ( /* Main Loop */ while (ip <= mflimit) { - ml = LZ4HC_InsertAndFindBestMatch (ctx, ip, matchlimit, &ref, maxNbAttempts, patternAnalysis, dict); + ml = LZ4HC_InsertAndFindBestMatch(ctx, ip, matchlimit, &ref, maxNbAttempts, patternAnalysis, dict); if (mldictCtx == NULL); return LZ4HC_compress_generic_internal(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit, noDictCtx); } -static int LZ4HC_compress_generic_dictCtx ( - LZ4HC_CCtx_internal* const ctx, - const char* const src, - char* const dst, - int* const srcSizePtr, - int const dstCapacity, - int cLevel, - limitedOutput_directive limit - ) +static int +LZ4HC_compress_generic_dictCtx ( + LZ4HC_CCtx_internal* const ctx, + const char* const src, + char* const dst, + int* const srcSizePtr, + int const dstCapacity, + int cLevel, + limitedOutput_directive limit + ) { const size_t position = ctx->end - ctx->base - ctx->lowLimit; assert(ctx->dictCtx != NULL); @@ -807,15 +808,16 @@ static int LZ4HC_compress_generic_dictCtx ( } } -static int LZ4HC_compress_generic ( - LZ4HC_CCtx_internal* const ctx, - const char* const src, - char* const dst, - int* const srcSizePtr, - int const dstCapacity, - int cLevel, - limitedOutput_directive limit - ) +static int +LZ4HC_compress_generic ( + LZ4HC_CCtx_internal* const ctx, + const char* const src, + char* const dst, + int* const srcSizePtr, + int const dstCapacity, + int cLevel, + limitedOutput_directive limit + ) { if (ctx->dictCtx == NULL) { return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit); @@ -842,7 +844,7 @@ int LZ4_compress_HC_extStateHC_fastReset (void* state, const char* src, char* ds int LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel) { if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0; /* Error : state is not aligned for pointers (32 or 64 bits) */ - LZ4_resetStreamHC ((LZ4_streamHC_t*)state, compressionLevel); + LZ4_initStreamHC (state, compressionLevel); /* full initialization, as there is no guarantee on state's content (could be freshly malloc'ed) */ return LZ4_compress_HC_extStateHC_fastReset(state, src, dst, srcSize, dstCapacity, compressionLevel); } @@ -861,12 +863,10 @@ int LZ4_compress_HC(const char* src, char* dst, int srcSize, int dstCapacity, in return cSize; } -/* LZ4_compress_HC_destSize() : - * only compatible with regular HC parser */ int LZ4_compress_HC_destSize(void* LZ4HC_Data, const char* source, char* dest, int* sourceSizePtr, int targetDestSize, int cLevel) { LZ4HC_CCtx_internal* const ctx = &((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse; - LZ4_resetStreamHC((LZ4_streamHC_t*)LZ4HC_Data, cLevel); + LZ4_initStreamHC(LZ4HC_Data, cLevel); /* full initialization, as there is no guarantee on state's content (could be freshly malloc'ed) */ LZ4HC_init(ctx, (const BYTE*) source); return LZ4HC_compress_generic(ctx, source, dest, sourceSizePtr, targetDestSize, cLevel, limitedDestSize); } @@ -877,14 +877,16 @@ int LZ4_compress_HC_destSize(void* LZ4HC_Data, const char* source, char* dest, i * Streaming Functions **************************************/ /* allocation */ -LZ4_streamHC_t* LZ4_createStreamHC(void) { +LZ4_streamHC_t* LZ4_createStreamHC(void) +{ LZ4_streamHC_t* const LZ4_streamHCPtr = (LZ4_streamHC_t*)ALLOC(sizeof(LZ4_streamHC_t)); if (LZ4_streamHCPtr==NULL) return NULL; - LZ4_resetStreamHC(LZ4_streamHCPtr, LZ4HC_CLEVEL_DEFAULT); + LZ4_initStreamHC(LZ4_streamHCPtr, LZ4HC_CLEVEL_DEFAULT); /* full initialization, malloc'ed buffer can be full of garbage */ return LZ4_streamHCPtr; } -int LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr) { +int LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr) +{ DEBUGLOG(4, "LZ4_freeStreamHC(%p)", LZ4_streamHCPtr); if (!LZ4_streamHCPtr) return 0; /* support free on NULL */ free(LZ4_streamHCPtr); @@ -893,9 +895,10 @@ int LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr) { /* initialization */ -void LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) +void LZ4_initStreamHC (void* state, int compressionLevel) { - LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal) <= sizeof(size_t) * LZ4_STREAMHCSIZE_SIZET); /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */ + LZ4_streamHC_t* const LZ4_streamHCPtr = (LZ4_streamHC_t*)state; + LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal) <= LZ4_STREAMHCSIZE); /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */ DEBUGLOG(4, "LZ4_resetStreamHC(%p, %d)", LZ4_streamHCPtr, compressionLevel); LZ4_streamHCPtr->internal_donotuse.end = (const BYTE *)(ptrdiff_t)-1; LZ4_streamHCPtr->internal_donotuse.base = NULL; @@ -905,11 +908,17 @@ void LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel); } +/* just a stub */ +void LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) +{ + return LZ4_initStreamHC(LZ4_streamHCPtr, compressionLevel); +} + void LZ4_resetStreamHC_fast (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) { DEBUGLOG(4, "LZ4_resetStreamHC_fast(%p, %d)", LZ4_streamHCPtr, compressionLevel); if (LZ4_streamHCPtr->internal_donotuse.dirty) { - LZ4_resetStreamHC(LZ4_streamHCPtr, compressionLevel); + LZ4_initStreamHC(LZ4_streamHCPtr, compressionLevel); } else { LZ4_streamHCPtr->internal_donotuse.end -= (uptrval)LZ4_streamHCPtr->internal_donotuse.base; LZ4_streamHCPtr->internal_donotuse.base = NULL; @@ -938,7 +947,7 @@ int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, const char* dictionary, int dictionary += dictSize - 64 KB; dictSize = 64 KB; } - LZ4_resetStreamHC(LZ4_streamHCPtr, ctxPtr->compressionLevel); + LZ4_initStreamHC(LZ4_streamHCPtr, ctxPtr->compressionLevel); LZ4HC_init (ctxPtr, (const BYTE*)dictionary); ctxPtr->end = (const BYTE*)dictionary + dictSize; if (dictSize >= 4) LZ4HC_Insert (ctxPtr, ctxPtr->end-3); @@ -1029,8 +1038,8 @@ int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictS { U32 const endIndex = (U32)(streamPtr->end - streamPtr->base); streamPtr->end = (const BYTE*)safeBuffer + dictSize; streamPtr->base = streamPtr->end - endIndex; - streamPtr->dictLimit = endIndex - dictSize; - streamPtr->lowLimit = endIndex - dictSize; + streamPtr->dictLimit = endIndex - (U32)dictSize; + streamPtr->lowLimit = endIndex - (U32)dictSize; if (streamPtr->nextToUpdate < streamPtr->dictLimit) streamPtr->nextToUpdate = streamPtr->dictLimit; } return dictSize; @@ -1061,7 +1070,7 @@ int LZ4_resetStreamStateHC(void* state, char* inputBuffer) { LZ4HC_CCtx_internal *ctx = &((LZ4_streamHC_t*)state)->internal_donotuse; if ((((size_t)state) & (sizeof(void*)-1)) != 0) return 1; /* Error : pointer is not aligned for pointer (32 or 64 bits) */ - LZ4_resetStreamHC((LZ4_streamHC_t*)state, ((LZ4_streamHC_t*)state)->internal_donotuse.compressionLevel); + LZ4_initStreamHC((LZ4_streamHC_t*)state, ((LZ4_streamHC_t*)state)->internal_donotuse.compressionLevel); LZ4HC_init(ctx, (const BYTE*)inputBuffer); return 0; } @@ -1070,7 +1079,7 @@ void* LZ4_createHC (const char* inputBuffer) { LZ4_streamHC_t* hc4 = (LZ4_streamHC_t*)ALLOC(sizeof(LZ4_streamHC_t)); if (hc4 == NULL) return NULL; /* not enough memory */ - LZ4_resetStreamHC(hc4, 0 /* compressionLevel */); + LZ4_initStreamHC(hc4, 0 /* compressionLevel */); LZ4HC_init (&hc4->internal_donotuse, (const BYTE*)inputBuffer); return hc4; } @@ -1102,7 +1111,7 @@ char* LZ4_slideInputBufferHC(void* LZ4HC_Data) /* ================================================ - * LZ4 Optimal parser (levels 10-12) + * LZ4 Optimal parser (levels [LZ4HC_CLEVEL_OPT_MIN - LZ4HC_CLEVEL_MAX]) * ===============================================*/ typedef struct { int price; @@ -1115,8 +1124,9 @@ typedef struct { LZ4_FORCE_INLINE int LZ4HC_literalsPrice(int const litlen) { int price = litlen; + assert(litlen >= 0); if (litlen >= (int)RUN_MASK) - price += 1 + (litlen-RUN_MASK)/255; + price += 1 + ((litlen-(int)RUN_MASK) / 255); return price; } @@ -1125,11 +1135,13 @@ LZ4_FORCE_INLINE int LZ4HC_literalsPrice(int const litlen) LZ4_FORCE_INLINE int LZ4HC_sequencePrice(int litlen, int mlen) { int price = 1 + 2 ; /* token + 16-bit offset */ + assert(litlen >= 0); + assert(mlen >= MINMATCH); price += LZ4HC_literalsPrice(litlen); if (mlen >= (int)(ML_MASK+MINMATCH)) - price += 1 + (mlen-(ML_MASK+MINMATCH))/255; + price += 1 + ((mlen-(int)(ML_MASK+MINMATCH)) / 255); return price; } diff --git a/lib/lz4hc.h b/lib/lz4hc.h index d1772f3..91b14ee 100644 --- a/lib/lz4hc.h +++ b/lib/lz4hc.h @@ -84,9 +84,9 @@ LZ4LIB_API int LZ4_compress_HC_extStateHC(void* stateHC, const char* src, char* * Will compress as much data as possible from `src` * to fit into `targetDstSize` budget. * Result is provided in 2 parts : - * @return : the number of bytes written into 'dst' + * @return : the number of bytes written into 'dst' (necessarily <= targetDstSize) * or 0 if compression fails. - * `srcSizePtr` : value will be updated to indicate how much bytes were read from `src` + * `srcSizePtr` : on success, *srcSizePtr is updated to indicate how much bytes were read from `src` */ LZ4LIB_API int LZ4_compress_HC_destSize(void* stateHC, const char* src, char* dst, @@ -103,8 +103,8 @@ LZ4LIB_API int LZ4_compress_HC_destSize(void* stateHC, /*! LZ4_createStreamHC() and LZ4_freeStreamHC() : * These functions create and release memory for LZ4 HC streaming state. * Newly created states are automatically initialized. - * Existing states can be re-used several times, using LZ4_resetStreamHC(). - * These methods are API and ABI stable, they can be used in combination with a DLL. + * A same state can be used multiple times consecutively, + * starting with LZ4_resetStreamHC_fast() to start a new stream of blocks. */ LZ4LIB_API LZ4_streamHC_t* LZ4_createStreamHC(void); LZ4LIB_API int LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr); @@ -121,35 +121,38 @@ LZ4LIB_API int LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr); Selecting the compression level can be done with LZ4_resetStreamHC_fast() (starts a new stream) or LZ4_setCompressionLevel() (anytime, between blocks in the same stream) (experimental). - LZ4_resetStreamHC_fast() only works on states which have been properly initialized at least once. - - If state space is provided manually with no guarantee of its content, for example allocated on stack, - it must be fully initialized, using LZ4_resetStreamHC(). - LZ4_resetStreamHC() is heavier, and it's guaranteed to succeed on any valid memory segment. - In contrast, LZ4_resetStreamHC_fast() only works on states which have been properly initialized at least once. + LZ4_resetStreamHC_fast() only works on states which have been properly initialized at least once, + which is automatically the case when state is created using LZ4_createStreamHC(). After reset, a first "fictional block" can be designated as initial dictionary, using LZ4_loadDictHC() (Optional). Invoke LZ4_compress_HC_continue() to compress each successive block. The number of blocks is unlimited. - Previous input blocks (including initial dictionary when present) must remain accessible and unmodified during compression. + Previous input blocks, including initial dictionary when present, + must remain accessible and unmodified during compression. + + It's allowed to update compression level anytime between blocks, + using LZ4_setCompressionLevel() (experimental). - 'dst' buffer should be sized to handle worst case scenarios (see LZ4_compressBound()), ensuring compression success. - In case of failure, the API does not guarantee recovery, so the state _must_ be reset. - Whenever `dst` buffer size cannot be made >= LZ4_compressBound(), - consider using LZ4_compress_HC_continue_destSize() to ensure success. + 'dst' buffer should be sized to handle worst case scenarios + (see LZ4_compressBound(), it ensures compression success). + In case of failure, the API does not guarantee recovery, + so the state _must_ be reset. + To ensure compression success + whenever `dst` buffer size cannot be made >= LZ4_compressBound(), + consider using LZ4_compress_HC_continue_destSize(). Whenever previous input blocks can't be preserved unmodified in-place during compression of next blocks, it's possible to copy the last blocks into a more stable memory space, using LZ4_saveDictHC(). Return value of LZ4_saveDictHC() is the size of dictionary effectively saved into 'safeBuffer' (<= 64 KB) After completing a streaming compression, - it's possible to start a new stream of blocks, and re-use the same LZ4_streamHC_t state - by resetting it, using LZ4_resetStreamHC_fast(). + it's possible to start a new stream of blocks, using the same LZ4_streamHC_t state, + just by resetting it, using LZ4_resetStreamHC_fast(). */ -LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel); +LZ4LIB_API void LZ4_resetStreamHC_fast(LZ4_streamHC_t* streamHCPtr, int compressionLevel); LZ4LIB_API int LZ4_loadDictHC (LZ4_streamHC_t* streamHCPtr, const char* dictionary, int dictSize); LZ4LIB_API int LZ4_compress_HC_continue (LZ4_streamHC_t* streamHCPtr, @@ -239,22 +242,31 @@ struct LZ4HC_CCtx_internal #endif -/* do not use these definitions directly. - * allocate an LZ4_streamHC_t instead. */ +/* Do not use these definitions directly ! + * Declare or allocate an LZ4_streamHC_t instead. + */ #define LZ4_STREAMHCSIZE (4*LZ4HC_HASHTABLESIZE + 2*LZ4HC_MAXD + 56 + ((sizeof(void*)==16) ? 56 : 0) /* AS400*/ ) /* 262200 or 262256*/ #define LZ4_STREAMHCSIZE_SIZET (LZ4_STREAMHCSIZE / sizeof(size_t)) union LZ4_streamHC_u { size_t table[LZ4_STREAMHCSIZE_SIZET]; LZ4HC_CCtx_internal internal_donotuse; }; /* previously typedef'd to LZ4_streamHC_t */ + /* LZ4_streamHC_t : * This structure allows static allocation of LZ4 HC streaming state. - * State must be initialized using LZ4_resetStreamHC() before first use. + * This can be used to allocate statically, on state, or as part of a larger structure. + * + * Such state **must** be initialized using LZ4_initStreamHC() before first use. + * + * Note that invoking LZ4_initStreamHC() is not required when + * the state was created using LZ4_createStreamHC() (which is recommended). + * Using the normal builder, a newly created state is automatically initialized. * * Static allocation shall only be used in combination with static linking. - * When invoking LZ4 from a DLL, use create/free functions instead, which are API and ABI stable. */ +LZ4LIB_API void LZ4_initStreamHC (void* streamHCPtr, int compressionLevel); + /*-************************************ * Deprecated Functions @@ -264,11 +276,11 @@ union LZ4_streamHC_u { /* deprecated compression functions */ LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC (const char* source, char* dest, int inputSize); LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize); -LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC2 (const char* source, char* dest, int inputSize, int compressionLevel); -LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel); +LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC2 (const char* source, char* dest, int inputSize, int compressionLevel); +LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel); LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC_withStateHC (void* state, const char* source, char* dest, int inputSize); LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); -LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC2_withStateHC (void* state, const char* source, char* dest, int inputSize, int compressionLevel); +LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC2_withStateHC (void* state, const char* source, char* dest, int inputSize, int compressionLevel); LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_withStateHC(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel); LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize); LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize); @@ -284,12 +296,23 @@ LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_comp LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API void* LZ4_createHC (const char* inputBuffer); LZ4_DEPRECATED("use LZ4_saveDictHC() instead") LZ4LIB_API char* LZ4_slideInputBufferHC (void* LZ4HC_Data); LZ4_DEPRECATED("use LZ4_freeStreamHC() instead") LZ4LIB_API int LZ4_freeHC (void* LZ4HC_Data); -LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel); +LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel); LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel); LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API int LZ4_sizeofStreamStateHC(void); LZ4_DEPRECATED("use LZ4_resetStreamHC() instead") LZ4LIB_API int LZ4_resetStreamStateHC(void* state, char* inputBuffer); +/* LZ4_resetStreamHC() is now replaced by LZ4_initStreamHC(). + * The intention is to emphasize the difference with LZ4_resetStreamHC_fast(), + * which is now the recommended function to start a new stream of blocks, + * but cannot be used to initialize a memory segment containing arbitrary garbage data. + * + * It is recommended to switch to LZ4_initStreamHC(). + * LZ4_resetStreamHC() will generate deprecation warnings in a future version. + */ +LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel); + + #if defined (__cplusplus) } #endif diff --git a/tests/fullbench.c b/tests/fullbench.c index e08947d..faa50cb 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -243,7 +243,7 @@ static int local_LZ4_compress_forceDict(const char* in, char* out, int inSize) LZ4_streamHC_t LZ4_streamHC; static void local_LZ4_resetStreamHC(void) { - LZ4_resetStreamHC(&LZ4_streamHC, 0); + LZ4_initStreamHC(&LZ4_streamHC, 0); } static int local_LZ4_saveDictHC(const char* in, char* out, int inSize) @@ -327,16 +327,19 @@ static int local_LZ4_decompress_safe_partial(const char* in, char* out, int inSi /* frame functions */ static int local_LZ4F_compressFrame(const char* in, char* out, int inSize) { - return (int)LZ4F_compressFrame(out, LZ4F_compressFrameBound(inSize, NULL), in, inSize, NULL); + assert(inSize >= 0); + return (int)LZ4F_compressFrame(out, LZ4F_compressFrameBound((size_t)inSize, NULL), in, (size_t)inSize, NULL); } static LZ4F_decompressionContext_t g_dCtx; static int local_LZ4F_decompress(const char* in, char* out, int inSize, int outSize) { - size_t srcSize = inSize; - size_t dstSize = outSize; + size_t srcSize = (size_t)inSize; + size_t dstSize = (size_t)outSize; size_t result; + assert(inSize >= 0); + assert(outSize >= 0); result = LZ4F_decompress(g_dCtx, out, &dstSize, in, &srcSize, NULL); if (result!=0) { DISPLAY("Error decompressing frame : unfinished frame\n"); exit(8); } if (srcSize != (size_t)inSize) { DISPLAY("Error decompressing frame : read size incorrect\n"); exit(9); } @@ -439,7 +442,7 @@ int fullSpeedBench(const char** fileNamesTable, int nbFiles) char* out = compressed_buff; nbChunks = (int) (((int)benchedSize + (g_chunkSize-1))/ g_chunkSize); for (i=0; i g_chunkSize) { chunkP[i].origSize = g_chunkSize; remaining -= g_chunkSize; } else { chunkP[i].origSize = (int)remaining; remaining = 0; } chunkP[i].compressedBuffer = out; out += maxCompressedChunkSize; @@ -611,7 +614,7 @@ int fullSpeedBench(const char** fileNamesTable, int nbFiles) PROGRESS("%2i-%-34.34s :%10i -> %7.1f MB/s\r", loopNb, dName, (int)benchedSize, (double)benchedSize / bestTime / 1000000); /* CRC Checking */ - crcDecoded = XXH32(orig_buff, (int)benchedSize, 0); + crcDecoded = XXH32(orig_buff, benchedSize, 0); if (checkResult && (crcOriginal!=crcDecoded)) { DISPLAY("\n!!! WARNING !!! %14s : Invalid Checksum : %x != %x\n", inFileName, (unsigned)crcOriginal, (unsigned)crcDecoded); diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 69c763b..6ebbf20 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -309,13 +309,13 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c unsigned long long hcbytes = 0; unsigned long long ccbytes = 0; void* const CNBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH); - size_t const compressedBufferSize = LZ4_compressBound(FUZ_MAX_BLOCK_SIZE); + size_t const compressedBufferSize = (size_t)LZ4_compressBound(FUZ_MAX_BLOCK_SIZE); char* const compressedBuffer = (char*)malloc(compressedBufferSize); char* const decodedBuffer = (char*)malloc(FUZ_MAX_DICT_SIZE + FUZ_MAX_BLOCK_SIZE); size_t const labSize = 96 KB; void* const lowAddrBuffer = FUZ_createLowAddr(labSize); - void* const stateLZ4 = malloc(LZ4_sizeofState()); - void* const stateLZ4HC = malloc(LZ4_sizeofStateHC()); + void* const stateLZ4 = malloc((size_t)LZ4_sizeofState()); + void* const stateLZ4HC = malloc((size_t)LZ4_sizeofStateHC()); LZ4_stream_t LZ4dict; LZ4_streamHC_t LZ4dictHC; U32 coreRandState = seed; @@ -370,7 +370,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c const char* dict = block - dictSize; int compressedSize, HCcompressedSize; int blockContinueCompressedSize; - U32 const crcOrig = XXH32(block, blockSize, 0); + U32 const crcOrig = XXH32(block, (size_t)blockSize, 0); int ret; FUZ_displayUpdate(cycleNb); @@ -395,7 +395,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c DISPLAYLEVEL(5, "destSize : %7i/%7i; content%7i/%7i ", ret, targetSize, srcSize, blockSize); if (targetSize>0) { /* check correctness */ - U32 const crcBase = XXH32(block, srcSize, 0); + U32 const crcBase = XXH32(block, (size_t)srcSize, 0); char const canary = FUZ_rand(&randState) & 255; FUZ_CHECKTEST((ret==0), "LZ4_compress_destSize() compression failed"); FUZ_DISPLAYTEST(); @@ -430,7 +430,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c FUZ_CHECKTEST(srcSize > blockSize, "LZ4_compress_HC_destSize() fed more than src buffer !"); if (targetSize>0) { /* check correctness */ - U32 const crcBase = XXH32(block, srcSize, 0); + U32 const crcBase = XXH32(block, (size_t)srcSize, 0); char const canary = FUZ_rand(&randState) & 255; FUZ_CHECKTEST((ret==0), "LZ4_compress_HC_destSize() compression failed"); FUZ_DISPLAYTEST(); @@ -547,7 +547,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c FUZ_CHECKTEST(ret<0, "LZ4_decompress_safe failed despite amply sufficient space"); FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe did not regenerate original data"); FUZ_CHECKTEST(decodedBuffer[blockSize+1], "LZ4_decompress_safe overrun specified output buffer size"); - { U32 const crcCheck = XXH32(decodedBuffer, blockSize, 0); + { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe corrupted decoded data"); } @@ -582,7 +582,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c /* Test partial decoding => must work */ FUZ_DISPLAYTEST("test LZ4_decompress_safe_partial"); { size_t const missingBytes = FUZ_rand(&randState) % blockSize; - int const targetSize = (int)(blockSize - missingBytes); + int const targetSize = (int)((size_t)blockSize - missingBytes); char const sentinel = decodedBuffer[targetSize] = block[targetSize] ^ 0x5A; int const decResult = LZ4_decompress_safe_partial(compressedBuffer, decodedBuffer, compressedSize, targetSize, blockSize); FUZ_CHECKTEST(decResult<0, "LZ4_decompress_safe_partial failed despite valid input data (error:%i)", decResult); @@ -653,7 +653,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c memcpy(decodedBuffer, dict, dictSize); ret = LZ4_decompress_fast_usingDict(compressedBuffer, decodedBuffer+dictSize, blockSize, decodedBuffer, dictSize); FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_decompress_fast_usingDict did not read all compressed block input"); - { U32 const crcCheck = XXH32(decodedBuffer+dictSize, blockSize, 0); + { U32 const crcCheck = XXH32(decodedBuffer+dictSize, (size_t)blockSize, 0); if (crcCheck!=crcOrig) FUZ_findDiff(block, decodedBuffer); FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_fast_usingDict corrupted decoded data (dict %i)", dictSize); } @@ -661,7 +661,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c FUZ_DISPLAYTEST("test LZ4_decompress_safe_usingDict()"); ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer+dictSize, blockContinueCompressedSize, blockSize, decodedBuffer, dictSize); FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data"); - { U32 const crcCheck = XXH32(decodedBuffer+dictSize, blockSize, 0); + { U32 const crcCheck = XXH32(decodedBuffer+dictSize, (size_t)blockSize, 0); FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe_usingDict corrupted decoded data"); } @@ -830,7 +830,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c FUZ_DISPLAYTEST("LZ4_compress_HC_continue with an external dictionary"); dict -= (FUZ_rand(&randState) & 7); /* even bigger separation */ if (dict < (char*)CNBuffer) dict = (char*)CNBuffer; - LZ4_resetStreamHC (&LZ4dictHC, compressionLevel); + LZ4_initStreamHC (&LZ4dictHC, compressionLevel); LZ4_loadDictHC(&LZ4dictHC, dict, dictSize); LZ4_setCompressionLevel(&LZ4dictHC, compressionLevel-1); blockContinueCompressedSize = LZ4_compress_HC_continue(&LZ4dictHC, block, compressedBuffer, blockSize, (int)compressedBufferSize); @@ -855,7 +855,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize, dict, dictSize); FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data"); FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size"); - { U32 const crcCheck = XXH32(decodedBuffer, blockSize, 0); + { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); if (crcCheck!=crcOrig) FUZ_findDiff(block, decodedBuffer); FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe_usingDict corrupted decoded data"); } @@ -865,9 +865,9 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c { LZ4_streamHC_t LZ4_streamHC; - LZ4_resetStreamHC (&LZ4dictHC, compressionLevel); + LZ4_initStreamHC (&LZ4dictHC, compressionLevel); LZ4_loadDictHC(&LZ4dictHC, dict, dictSize); - LZ4_resetStreamHC (&LZ4_streamHC, compressionLevel); + LZ4_initStreamHC (&LZ4_streamHC, compressionLevel); LZ4_attach_HC_dictionary(&LZ4_streamHC, &LZ4dictHC); blockContinueCompressedSize = LZ4_compress_HC_continue(&LZ4_streamHC, block, compressedBuffer, blockSize, (int)compressedBufferSize); FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_HC_continue with ExtDictCtx failed"); @@ -901,7 +901,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize, dict, dictSize); FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data"); FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size"); - { U32 const crcCheck = XXH32(decodedBuffer, blockSize, 0); + { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); if (crcCheck!=crcOrig) FUZ_findDiff(block, decodedBuffer); FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe_usingDict corrupted decoded data"); } @@ -912,7 +912,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c { int const availableSpace = (FUZ_rand(&randState) % blockSize) + 5; int consumedSize = blockSize; FUZ_DISPLAYTEST(); - LZ4_resetStreamHC (&LZ4dictHC, compressionLevel); + LZ4_initStreamHC (&LZ4dictHC, compressionLevel); LZ4_loadDictHC(&LZ4dictHC, dict, dictSize); blockContinueCompressedSize = LZ4_compress_HC_continue_destSize(&LZ4dictHC, block, compressedBuffer, &consumedSize, availableSpace); DISPLAYLEVEL(5, " LZ4_compress_HC_continue_destSize : compressed %6i/%6i into %6i/%6i at cLevel=%i\n", consumedSize, blockSize, blockContinueCompressedSize, availableSpace, compressionLevel); @@ -925,8 +925,8 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, consumedSize, dict, dictSize); FUZ_CHECKTEST(ret!=consumedSize, "LZ4_decompress_safe_usingDict did not regenerate original data"); FUZ_CHECKTEST(decodedBuffer[consumedSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size") - { U32 const crcSrc = XXH32(block, consumedSize, 0); - U32 const crcDst = XXH32(decodedBuffer, consumedSize, 0); + { U32 const crcSrc = XXH32(block, (size_t)consumedSize, 0); + U32 const crcDst = XXH32(decodedBuffer, (size_t)consumedSize, 0); if (crcSrc!=crcDst) FUZ_findDiff(block, decodedBuffer); FUZ_CHECKTEST(crcSrc!=crcDst, "LZ4_decompress_safe_usingDict corrupted decoded data"); } @@ -1080,7 +1080,7 @@ static void FUZ_unitTests(int compressionLevel) /* simple HC compression test */ DISPLAYLEVEL(3, " Simple HC round-trip : "); { U64 const crc64 = XXH64(testInput, testCompressedSize, 0); - LZ4_resetStreamHC(&sHC, compressionLevel); + LZ4_initStreamHC(&sHC, compressionLevel); result = LZ4_compress_HC_continue(&sHC, testInput, testCompressed, testCompressedSize, testCompressedSize-1); FUZ_CHECKTEST(result==0, "LZ4_compressHC_limitedOutput_continue() compression failed"); FUZ_CHECKTEST(sHC.internal_donotuse.dirty, "Context should be clean"); @@ -1105,7 +1105,7 @@ static void FUZ_unitTests(int compressionLevel) memset(block, 0, blockSize); ((char*)dstBlock)[targetSize] = sentinel; - LZ4_resetStreamHC(&sHC, 3); + LZ4_initStreamHC(&sHC, 3); assert(blockSize < INT_MAX); srcSize = (int)blockSize; assert(targetSize < INT_MAX); @@ -1114,7 +1114,7 @@ static void FUZ_unitTests(int compressionLevel) FUZ_CHECKTEST(result!=4116, "LZ4_compress_HC_destSize() : compression must fill dstBuffer completely, but no more !"); FUZ_CHECKTEST(((char*)dstBlock)[targetSize] != sentinel, "LZ4_compress_HC_destSize()") - LZ4_resetStreamHC(&sHC, 3); /* make sure the context is clean after the test */ + LZ4_resetStreamHC_fast(&sHC, 3); /* make sure the context is clean after the test */ free(block); free(dstBlock); } -- cgit v0.12 From c3f8928f879f5ce89d9c32996ea991312e6c69ec Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 5 Apr 2019 10:41:16 -0700 Subject: fixed strict iso C90 --- lib/lz4hc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lz4hc.c b/lib/lz4hc.c index 644b8eb..9e8b77e 100644 --- a/lib/lz4hc.c +++ b/lib/lz4hc.c @@ -911,7 +911,7 @@ void LZ4_initStreamHC (void* state, int compressionLevel) /* just a stub */ void LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) { - return LZ4_initStreamHC(LZ4_streamHCPtr, compressionLevel); + LZ4_initStreamHC(LZ4_streamHCPtr, compressionLevel); } void LZ4_resetStreamHC_fast (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) -- cgit v0.12 From a4f1635b0a29580628c22fbccfd68bda122453bb Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 5 Apr 2019 11:47:06 -0700 Subject: fuzzer: fixed strict c99 with mmap+MAP_ANONYMOUS --- tests/frametest.c | 9 ++++----- tests/fuzzer.c | 4 +--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/frametest.c b/tests/frametest.c index 14906a0..fa005db 100644 --- a/tests/frametest.c +++ b/tests/frametest.c @@ -270,7 +270,7 @@ int basicTests(U32 seed, double compressibility) if (decResult != 0) goto _output_error; /* should finish now */ op += oSize; if (op>oend) { DISPLAY("decompression write overflow \n"); goto _output_error; } - { U64 const crcDest = XXH64(decodedBuffer, op-ostart, 1); + { U64 const crcDest = XXH64(decodedBuffer, (size_t)(op-ostart), 1); if (crcDest != crcOrig) goto _output_error; } } @@ -309,7 +309,6 @@ int basicTests(U32 seed, double compressibility) iSize = 15 - iSize; CHECK( LZ4F_getFrameInfo(dCtx, &fi, ip, &iSize) ); DISPLAYLEVEL(3, " correctly decoded \n"); - ip += iSize; } DISPLAYLEVEL(3, "Decode a buggy input : "); @@ -337,7 +336,7 @@ int basicTests(U32 seed, double compressibility) const BYTE* ip = (const BYTE*) compressedBuffer; const BYTE* const iend = ip + cSize; while (ip < iend) { - size_t oSize = oend-op; + size_t oSize = (size_t)(oend-op); size_t iSize = 1; CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) ); op += oSize; @@ -380,8 +379,8 @@ int basicTests(U32 seed, double compressibility) while (ip < iend) { unsigned const nbBits = FUZ_rand(&randState) % maxBits; size_t iSize = (FUZ_rand(&randState) & ((1< (size_t)(iend-ip)) iSize = iend-ip; + size_t oSize = (size_t)(oend-op); + if (iSize > (size_t)(iend-ip)) iSize = (size_t)(iend-ip); CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) ); op += oSize; ip += iSize; diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 6ebbf20..4cc80fa 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -37,6 +37,7 @@ * Dependencies **************************************/ #if defined(__unix__) && !defined(_AIX) /* must be included before platform.h for MAP_ANONYMOUS */ +# define _GNU_SOURCE /* MAP_ANONYMOUS even in -std=c99 mode */ # include /* mmap */ #endif #include "platform.h" /* _CRT_SECURE_NO_WARNINGS */ @@ -47,9 +48,6 @@ #include /* clock_t, clock, CLOCKS_PER_SEC */ #include #include /* INT_MAX */ -#if defined(__unix__) && defined(_AIX) -# include /* mmap */ -#endif #define LZ4_DISABLE_DEPRECATE_WARNINGS /* LZ4_decompress_fast */ #define LZ4_STATIC_LINKING_ONLY -- cgit v0.12 From 2a94faf462c53feb864c4ae4e857c4870a948da0 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 5 Apr 2019 11:55:34 -0700 Subject: fixed _GNU_SOURCE duplicate --- tests/fuzzer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 4cc80fa..1efe322 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -37,6 +37,7 @@ * Dependencies **************************************/ #if defined(__unix__) && !defined(_AIX) /* must be included before platform.h for MAP_ANONYMOUS */ +# undef _GNU_SOURCE /* in case it's already defined */ # define _GNU_SOURCE /* MAP_ANONYMOUS even in -std=c99 mode */ # include /* mmap */ #endif -- cgit v0.12 From 2ece0d83809849e68e9c194ff3d340982b527256 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 5 Apr 2019 12:54:13 -0700 Subject: created LZ4_initStream() - promoted LZ4_resetStream_fast() to stable - moved LZ4_resetStream() into deprecate, but without triggering a compiler warning - update all sources to no longer rely on LZ4_resetStream() note : LZ4_initStream() proposal is slightly different : it's able to initialize any buffer, provided that it's large enough. To this end, it accepts a void*, and returns an LZ4_stream_t*. --- doc/lz4_manual.html | 87 +++++++++++++++++---------------- examples/blockStreaming_doubleBuffer.c | 2 +- examples/dictionaryRandomAccess.c | 4 +- lib/lz4.c | 17 +++++-- lib/lz4.h | 88 +++++++++++++++++----------------- lib/lz4frame.c | 4 +- lib/lz4hc.h | 4 +- tests/fullbench.c | 4 +- tests/fuzzer.c | 6 +-- 9 files changed, 111 insertions(+), 105 deletions(-) diff --git a/doc/lz4_manual.html b/doc/lz4_manual.html index b738c8d..5db3ec9 100644 --- a/doc/lz4_manual.html +++ b/doc/lz4_manual.html @@ -155,9 +155,23 @@ int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int src

Streaming Compression Functions


 
-
void LZ4_resetStream (LZ4_stream_t* streamPtr);
-

An LZ4_stream_t structure can be allocated once and re-used multiple times. - Use this function to start compressing a new stream. +

void LZ4_resetStream_fast (LZ4_stream_t* streamPtr);
+

Use this to prepare an LZ4_stream_t for a new chain of dependent blocks + (e.g., LZ4_compress_fast_continue()). + + An LZ4_stream_t must be initialized once. + This is automatically done when created by LZ4_createStream(). + However, should the LZ4_stream_t be simply declared on stack (for example), + it's necessary to initialize first using LZ4_initStream(). + + After that, start any new stream with LZ4_resetStream_fast(). + A same LZ4_stream_t can be re-used multiple times consecutively + and compress multiple streams, + provided that it starts each new stream with LZ4_resetStream_fast(). + + LZ4_resetStream_fast() is much faster than LZ4_initStream(), + but is not compatible with memory regions containing garbage data. + For this reason, LZ4_stream_t must be initialized at least once,


@@ -290,43 +304,6 @@ int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream); define LZ4_PUBLISH_STATIC_FUNCTIONS when building the LZ4 library.
-
LZ4LIB_STATIC_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr);
-

Use this to prepare a context for a new chain of calls to a streaming API - (e.g., LZ4_compress_fast_continue()). - - Note: - To stay on the safe side, when LZ4_stream_t is used for the first time, - it should be either created using LZ4_createStream() or - initialized using LZ4_resetStream(). - - Note: - Using this in advance of a non-streaming-compression function is redundant, - since they all perform their own custom reset internally. - - Differences from LZ4_resetStream(): - When an LZ4_stream_t is known to be in an internally coherent state, - it will be prepared for a new compression with almost no work. - Otherwise, it will fall back to the full, expensive reset. - - LZ4_streams are guaranteed to be in a valid state when: - - returned from LZ4_createStream() - - reset by LZ4_resetStream() - - memset(stream, 0, sizeof(LZ4_stream_t)), though this is discouraged - - the stream was in a valid state and was reset by LZ4_resetStream_fast() - - the stream was in a valid state and was then used in any compression call - that returned success - - the stream was in an indeterminate state and was used in a compression - call that fully reset the state (e.g., LZ4_compress_fast_extState()) and - that returned success - - Note: - A stream that was used in a compression call that did not return success - (e.g., LZ4_compress_fast_continue()), can still be passed to this function, - however, it's history is not preserved because of previous compression - failure. - -


-
LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
 

A variant of LZ4_compress_fast_extState(). @@ -394,10 +371,24 @@ union LZ4_stream_u { LZ4_stream_t_internal internal_donotuse; } ; /* previously typedef'd to LZ4_stream_t */

information structure to track an LZ4 stream. - init this structure with LZ4_resetStream() before first use. - note : only use in association with static linking ! - this definition is not API/ABI safe, - it may change in a future version ! + LZ4_stream_t can also be created using LZ4_createStream(), which is recommended. + The structure definition can be convenient for static allocation + (on stack, or as part of larger structure). + Init this structure with LZ4_initStream() before first use. + note : only use this definition in association with static linking ! + this definition is not API/ABI safe, and may change in a future version. + +


+ +
LZ4_stream_t* LZ4_initStream (void* buffer, size_t size);
+

An LZ4_stream_t structure must be initialized at least once. + While this is automatically done when invoking LZ4_createStream(), + it's not when the structure is simply declared on stack (for example). + Use this function to properly initialize a newly declared LZ4_stream_t. + It can also accept any arbitrary buffer of sufficient size as input, + and will return a pointer of proper type upon initialization. + Note : initialization can fail if size < sizeof(LZ4_stream_t). + In which case, the function will @return NULL.


@@ -477,5 +468,13 @@ int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize,


+
//LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);
+

An LZ4_stream_t structure must be initialized at least once. + This is done with LZ4_initStream(), or LZ4_resetStream(). + Consider switching to LZ4_initStream(), + invoking LZ4_resetStream() will trigger deprecation warnings in the future. + +


+ diff --git a/examples/blockStreaming_doubleBuffer.c b/examples/blockStreaming_doubleBuffer.c index acb3455..3f719d3 100644 --- a/examples/blockStreaming_doubleBuffer.c +++ b/examples/blockStreaming_doubleBuffer.c @@ -44,7 +44,7 @@ void test_compress(FILE* outFp, FILE* inpFp) char inpBuf[2][BLOCK_BYTES]; int inpBufIndex = 0; - LZ4_resetStream(lz4Stream); + LZ4_initStream(lz4Stream, sizeof (*lz4Stream)); for(;;) { char* const inpPtr = inpBuf[inpBufIndex]; diff --git a/examples/dictionaryRandomAccess.c b/examples/dictionaryRandomAccess.c index 291fd08..ecb3b2d 100644 --- a/examples/dictionaryRandomAccess.c +++ b/examples/dictionaryRandomAccess.c @@ -11,7 +11,7 @@ #include #include -#define MIN(x, y) (x) < (y) ? (x) : (y) +#define MIN(x, y) ((x) < (y) ? (x) : (y)) enum { BLOCK_BYTES = 1024, /* 1 KiB of uncompressed data in a block */ @@ -63,7 +63,7 @@ void test_compress(FILE* outFp, FILE* inpFp, void *dict, int dictSize) int *offsetsEnd = offsets; - LZ4_resetStream(lz4Stream); + LZ4_initStream(lz4Stream, sizeof(*lz4Stream)); /* Write header magic */ write_bin(outFp, kTestMagic, sizeof(kTestMagic)); diff --git a/lib/lz4.c b/lib/lz4.c index df92162..e0fcf0f 100644 --- a/lib/lz4.c +++ b/lib/lz4.c @@ -1125,9 +1125,8 @@ _failure: int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) { - LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)state)->internal_donotuse; + LZ4_stream_t_internal* const ctx = & LZ4_initStream(state, sizeof(LZ4_stream_t)) -> internal_donotuse; if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; - LZ4_resetStream((LZ4_stream_t*)state); if (maxOutputSize >= LZ4_compressBound(inputSize)) { if (inputSize < LZ4_64Klimit) { return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, byU16, noDict, noDictIssue, acceleration); @@ -1221,7 +1220,7 @@ int LZ4_compress_default(const char* src, char* dst, int srcSize, int maxOutputS int LZ4_compress_fast_force(const char* src, char* dst, int srcSize, int dstCapacity, int acceleration) { LZ4_stream_t ctx; - LZ4_resetStream(&ctx); + LZ4_initStream(&ctx, sizeof(ctx)); if (srcSize < LZ4_64Klimit) { return LZ4_compress_generic(&ctx.internal_donotuse, src, dst, srcSize, NULL, dstCapacity, limitedOutput, byU16, noDict, noDictIssue, acceleration); @@ -1237,7 +1236,7 @@ int LZ4_compress_fast_force(const char* src, char* dst, int srcSize, int dstCapa * _continue() call without resetting it. */ static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize) { - LZ4_resetStream(state); + LZ4_initStream(state, sizeof (*state)); if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) { /* compression success is guaranteed */ return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1); @@ -1281,10 +1280,18 @@ LZ4_stream_t* LZ4_createStream(void) LZ4_STATIC_ASSERT(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal)); /* A compilation error here means LZ4_STREAMSIZE is not large enough */ DEBUGLOG(4, "LZ4_createStream %p", lz4s); if (lz4s == NULL) return NULL; - LZ4_resetStream(lz4s); + LZ4_initStream(lz4s, sizeof(*lz4s)); return lz4s; } +LZ4_stream_t* LZ4_initStream (void* buffer, size_t size) +{ + DEBUGLOG(5, "LZ4_initStream"); + if (size < sizeof(LZ4_stream_t)) return NULL; + MEM_INIT(buffer, 0, sizeof(LZ4_stream_t)); + return (LZ4_stream_t*)buffer; +} + void LZ4_resetStream (LZ4_stream_t* LZ4_stream) { DEBUGLOG(5, "LZ4_resetStream (ctx:%p)", LZ4_stream); diff --git a/lib/lz4.h b/lib/lz4.h index 1dc8e00..3fc67bb 100644 --- a/lib/lz4.h +++ b/lib/lz4.h @@ -238,11 +238,25 @@ typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */ LZ4LIB_API LZ4_stream_t* LZ4_createStream(void); LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr); -/*! LZ4_resetStream() : - * An LZ4_stream_t structure can be allocated once and re-used multiple times. - * Use this function to start compressing a new stream. +/*! LZ4_resetStream_fast() : v1.9.0+ + * Use this to prepare an LZ4_stream_t for a new chain of dependent blocks + * (e.g., LZ4_compress_fast_continue()). + * + * An LZ4_stream_t must be initialized once. + * This is automatically done when created by LZ4_createStream(). + * However, should the LZ4_stream_t be simply declared on stack (for example), + * it's necessary to initialize first using LZ4_initStream(). + * + * After that, start any new stream with LZ4_resetStream_fast(). + * A same LZ4_stream_t can be re-used multiple times consecutively + * and compress multiple streams, + * provided that it starts each new stream with LZ4_resetStream_fast(). + * + * LZ4_resetStream_fast() is much faster than LZ4_initStream(), + * but is not compatible with memory regions containing garbage data. + * For this reason, LZ4_stream_t must be initialized at least once, */ -LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr); +LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr); /*! LZ4_loadDict() : * Use this function to load a static dictionary into LZ4_stream_t. @@ -394,42 +408,6 @@ LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* src, char* dst, int sr #ifdef LZ4_STATIC_LINKING_ONLY -/*! LZ4_resetStream_fast() : - * Use this to prepare a context for a new chain of calls to a streaming API - * (e.g., LZ4_compress_fast_continue()). - * - * Note: - * To stay on the safe side, when LZ4_stream_t is used for the first time, - * it should be either created using LZ4_createStream() or - * initialized using LZ4_resetStream(). - * - * Note: - * Using this in advance of a non-streaming-compression function is redundant, - * since they all perform their own custom reset internally. - * - * Differences from LZ4_resetStream(): - * When an LZ4_stream_t is known to be in an internally coherent state, - * it will be prepared for a new compression with almost no work. - * Otherwise, it will fall back to the full, expensive reset. - * - * LZ4_streams are guaranteed to be in a valid state when: - * - returned from LZ4_createStream() - * - reset by LZ4_resetStream() - * - memset(stream, 0, sizeof(LZ4_stream_t)), though this is discouraged - * - the stream was in a valid state and was reset by LZ4_resetStream_fast() - * - the stream was in a valid state and was then used in any compression call - * that returned success - * - the stream was in an indeterminate state and was used in a compression - * call that fully reset the state (e.g., LZ4_compress_fast_extState()) and - * that returned success - * - * Note: - * A stream that was used in a compression call that did not return success - * (e.g., LZ4_compress_fast_continue()), can still be passed to this function, - * however, it's history is not preserved because of previous compression - * failure. - */ -LZ4LIB_STATIC_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr); /*! LZ4_compress_fast_extState_fastReset() : * A variant of LZ4_compress_fast_extState(). @@ -530,10 +508,12 @@ typedef struct { /*! LZ4_stream_t : * information structure to track an LZ4 stream. - * init this structure with LZ4_resetStream() before first use. - * note : only use in association with static linking ! - * this definition is not API/ABI safe, - * it may change in a future version ! + * LZ4_stream_t can also be created using LZ4_createStream(), which is recommended. + * The structure definition can be convenient for static allocation + * (on stack, or as part of larger structure). + * Init this structure with LZ4_initStream() before first use. + * note : only use this definition in association with static linking ! + * this definition is not API/ABI safe, and may change in a future version. */ #define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4 + ((sizeof(void*)==16) ? 4 : 0) /*AS-400*/ ) #define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(unsigned long long)) @@ -542,6 +522,18 @@ union LZ4_stream_u { LZ4_stream_t_internal internal_donotuse; } ; /* previously typedef'd to LZ4_stream_t */ +/*! LZ4_initStream() : + * An LZ4_stream_t structure must be initialized at least once. + * While this is automatically done when invoking LZ4_createStream(), + * it's not when the structure is simply declared on stack (for example). + * Use this function to properly initialize a newly declared LZ4_stream_t. + * It can also accept any arbitrary buffer of sufficient size as input, + * and will return a pointer of proper type upon initialization. + * Note : initialization can fail if size < sizeof(LZ4_stream_t). + * In which case, the function will @return NULL. + */ +LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size); + /*! LZ4_streamDecode_t : * information structure to track an LZ4 stream during decompression. @@ -652,6 +644,14 @@ int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const ch LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize); +/*! LZ4_resetStream() : + * An LZ4_stream_t structure must be initialized at least once. + * This is done with LZ4_initStream(), or LZ4_resetStream(). + * Consider switching to LZ4_initStream(), + * invoking LZ4_resetStream() will trigger deprecation warnings in the future. + */ +LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr); + #endif /* LZ4_H_2983827168210 */ diff --git a/lib/lz4frame.c b/lib/lz4frame.c index f076204..3b4fcee 100644 --- a/lib/lz4frame.c +++ b/lib/lz4frame.c @@ -446,7 +446,7 @@ size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity, if (preferencesPtr == NULL || preferencesPtr->compressionLevel < LZ4HC_CLEVEL_MIN) { - LZ4_resetStream(&lz4ctx); + LZ4_initStream(&lz4ctx, sizeof(lz4ctx)); cctxPtr->lz4CtxPtr = &lz4ctx; cctxPtr->lz4CtxAlloc = 1; cctxPtr->lz4CtxState = 1; @@ -628,7 +628,7 @@ size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr, /* otherwise, a sufficient buffer is allocated, but we need to * reset it to the correct context type */ if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) { - LZ4_resetStream((LZ4_stream_t *) cctxPtr->lz4CtxPtr); + LZ4_initStream((LZ4_stream_t *) cctxPtr->lz4CtxPtr, sizeof (LZ4_stream_t)); } else { LZ4_initStreamHC((LZ4_streamHC_t *) cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel); } diff --git a/lib/lz4hc.h b/lib/lz4hc.h index 91b14ee..fbf4518 100644 --- a/lib/lz4hc.h +++ b/lib/lz4hc.h @@ -152,7 +152,7 @@ LZ4LIB_API int LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr); just by resetting it, using LZ4_resetStreamHC_fast(). */ -LZ4LIB_API void LZ4_resetStreamHC_fast(LZ4_streamHC_t* streamHCPtr, int compressionLevel); +LZ4LIB_API void LZ4_resetStreamHC_fast(LZ4_streamHC_t* streamHCPtr, int compressionLevel); /* v1.9.0+ */ LZ4LIB_API int LZ4_loadDictHC (LZ4_streamHC_t* streamHCPtr, const char* dictionary, int dictSize); LZ4LIB_API int LZ4_compress_HC_continue (LZ4_streamHC_t* streamHCPtr, @@ -265,7 +265,7 @@ union LZ4_streamHC_u { * Static allocation shall only be used in combination with static linking. */ -LZ4LIB_API void LZ4_initStreamHC (void* streamHCPtr, int compressionLevel); +LZ4LIB_API void LZ4_initStreamHC (void* streamHCPtr, int compressionLevel); /* v1.9.0+ */ /*-************************************ diff --git a/tests/fullbench.c b/tests/fullbench.c index faa50cb..61d6b78 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -161,12 +161,12 @@ static size_t BMK_findMaxMem(U64 requiredMem) static LZ4_stream_t LZ4_stream; static void local_LZ4_resetDictT(void) { - LZ4_resetStream(&LZ4_stream); + LZ4_initStream(&LZ4_stream, sizeof(LZ4_stream)); } static void local_LZ4_createStream(void) { - LZ4_resetStream(&LZ4_stream); + LZ4_initStream(&LZ4_stream, sizeof(LZ4_stream)); } static int local_LZ4_saveDict(const char* in, char* out, int inSize) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 1efe322..d899cef 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -641,7 +641,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c /* Compress using dictionary */ FUZ_DISPLAYTEST("test LZ4_compress_fast_continue() with dictionary of size %i", dictSize); { LZ4_stream_t LZ4_stream; - LZ4_resetStream(&LZ4_stream); + LZ4_initStream(&LZ4_stream, sizeof(LZ4_stream)); LZ4_compress_fast_continue (&LZ4_stream, dict, compressedBuffer, dictSize, (int)compressedBufferSize, 1); /* Just to fill hash tables */ blockContinueCompressedSize = LZ4_compress_fast_continue (&LZ4_stream, block, compressedBuffer, blockSize, (int)compressedBufferSize, 1); FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_fast_continue failed"); @@ -742,7 +742,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c FUZ_DISPLAYTEST("LZ4_compress_fast_continue() after LZ4_attach_dictionary()"); LZ4_loadDict(&LZ4dict, dict, dictSize); - LZ4_resetStream(&LZ4_stream); + LZ4_initStream(&LZ4_stream, sizeof(LZ4_stream)); LZ4_attach_dictionary(&LZ4_stream, &LZ4dict); blockContinueCompressedSize = LZ4_compress_fast_continue(&LZ4_stream, block, compressedBuffer, blockSize, (int)compressedBufferSize, 1); FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_fast_continue using extDictCtx failed"); @@ -1000,7 +1000,7 @@ static void FUZ_unitTests(int compressionLevel) /* simple compression test */ crcOrig = XXH64(testInput, testCompressedSize, 0); - LZ4_resetStream(&streamingState); + LZ4_initStream(&streamingState, sizeof(streamingState)); result = LZ4_compress_fast_continue(&streamingState, testInput, testCompressed, testCompressedSize, testCompressedSize-1, 1); FUZ_CHECKTEST(result==0, "LZ4_compress_fast_continue() compression failed!"); FUZ_CHECKTEST(streamingState.internal_donotuse.dirty, "context should be clean") -- cgit v0.12 From 34f0004a5ed5ca5a113432bf2e433966d545133e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 5 Apr 2019 15:35:19 -0700 Subject: added comment on initStream + _extState_ as suggested by @felixhandte --- lib/lz4.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/lz4.h b/lib/lz4.h index 3fc67bb..5aa4229 100644 --- a/lib/lz4.h +++ b/lib/lz4.h @@ -242,19 +242,23 @@ LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr); * Use this to prepare an LZ4_stream_t for a new chain of dependent blocks * (e.g., LZ4_compress_fast_continue()). * - * An LZ4_stream_t must be initialized once. + * An LZ4_stream_t must be initialized once before usage. * This is automatically done when created by LZ4_createStream(). * However, should the LZ4_stream_t be simply declared on stack (for example), - * it's necessary to initialize first using LZ4_initStream(). + * it's necessary to initialize it first, using LZ4_initStream(). * - * After that, start any new stream with LZ4_resetStream_fast(). + * After init, start any new stream with LZ4_resetStream_fast(). * A same LZ4_stream_t can be re-used multiple times consecutively * and compress multiple streams, * provided that it starts each new stream with LZ4_resetStream_fast(). * * LZ4_resetStream_fast() is much faster than LZ4_initStream(), * but is not compatible with memory regions containing garbage data. - * For this reason, LZ4_stream_t must be initialized at least once, + * + * Note: it's only useful to call LZ4_resetStream_fast() + * in the context of streaming compression. + * The *extState* functions perform their own resets. + * Invoking LZ4_resetStream_fast() before is redundant, and even counterproductive. */ LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr); -- cgit v0.12 From c198a39a663d5a36d2d564a2a4140485e42404bb Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 8 Apr 2019 12:49:54 -0700 Subject: LZ4_initStream() checks alignment restriction updated associated documentation --- lib/lz4.c | 7 +++++++ lib/lz4.h | 17 ++++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/lib/lz4.c b/lib/lz4.c index e0fcf0f..a2e58c0 100644 --- a/lib/lz4.c +++ b/lib/lz4.c @@ -1284,10 +1284,17 @@ LZ4_stream_t* LZ4_createStream(void) return lz4s; } +static size_t LZ4_stream_t_alignment(void) +{ + struct { char c; LZ4_stream_t t; } t_a; + return sizeof(t_a) - sizeof(t_a.t); +} + LZ4_stream_t* LZ4_initStream (void* buffer, size_t size) { DEBUGLOG(5, "LZ4_initStream"); if (size < sizeof(LZ4_stream_t)) return NULL; + if (((size_t)buffer) & (LZ4_stream_t_alignment() - 1)) return NULL; /* alignment check */ MEM_INIT(buffer, 0, sizeof(LZ4_stream_t)); return (LZ4_stream_t*)buffer; } diff --git a/lib/lz4.h b/lib/lz4.h index 5aa4229..e55e1c6 100644 --- a/lib/lz4.h +++ b/lib/lz4.h @@ -528,13 +528,16 @@ union LZ4_stream_u { /*! LZ4_initStream() : * An LZ4_stream_t structure must be initialized at least once. - * While this is automatically done when invoking LZ4_createStream(), - * it's not when the structure is simply declared on stack (for example). - * Use this function to properly initialize a newly declared LZ4_stream_t. - * It can also accept any arbitrary buffer of sufficient size as input, - * and will return a pointer of proper type upon initialization. - * Note : initialization can fail if size < sizeof(LZ4_stream_t). - * In which case, the function will @return NULL. + * This is automatically done when invoking LZ4_createStream(), + * but it's not when the structure is simply declared on stack (for example). + * + * Use LZ4_initStream() to properly initialize a newly declared LZ4_stream_t. + * It can also initialize any arbitrary buffer of sufficient size, + * and will @return a pointer of proper type upon initialization. + * + * Note : initialization fails if size and alignment conditions are not respected. + * In which case, the function will @return NULL. + * Note2: An LZ4_stream_t structure guarantees correct alignment and size. */ LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size); -- cgit v0.12 From 5db9a2f8b6476b588bae84205718bdb7f3a1967e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 8 Apr 2019 13:45:01 -0700 Subject: added make list target to tests --- tests/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/Makefile b/tests/Makefile index 7d49b31..bc88ece 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -151,12 +151,18 @@ endif DD:=dd +.PHONY: list +list: + @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs +.PHONY: test test: test-lz4 test-lz4c test-frametest test-fullbench test-fuzzer test-install test-amalgamation +.PHONY: test32 test32: CFLAGS+=-m32 test32: test +.PHONY: test-amalgamation test-amalgamation: $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c cat $(LZ4DIR)/lz4.c > lz4_all.c cat $(LZ4DIR)/lz4hc.c >> lz4_all.c -- cgit v0.12 From 249703ae2e4e6cce5fc098b3e1443deb6ad42e29 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 8 Apr 2019 13:49:26 -0700 Subject: slightly faster huge file test level down 5->4 size down 6G->5G --- tests/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Makefile b/tests/Makefile index bc88ece..5495f48 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -327,7 +327,7 @@ test-lz4-dict: lz4 datagen test-lz4-hugefile: lz4 datagen @echo "\n ---- test huge files compression/decompression ----" ./datagen -g6GB | $(LZ4) -vB5D | $(LZ4) -qt - ./datagen -g6GB | $(LZ4) -v5BD | $(LZ4) -qt + ./datagen -g5GB | $(LZ4) -v4BD | $(LZ4) -qt # test large file size [2-4] GB @./datagen -g3G -P100 | $(LZ4) -vv | $(LZ4) --decompress --force --sparse - tmphf1 @ls -ls tmphf1 -- cgit v0.12 From 3f5f10c63e257c2e4b056f9a69d068c47f1c85f0 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 8 Apr 2019 14:01:32 -0700 Subject: fixed cleaning tmp directory --- tests/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 5495f48..792c22c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -115,15 +115,15 @@ checkFrame : lz4frame.o lz4.o lz4hc.o xxhash.o checkFrame.c clean: @$(MAKE) -C $(LZ4DIR) $@ > $(VOID) @$(MAKE) -C $(PRGDIR) $@ > $(VOID) - @$(RM) core *.o *.test tmp* \ + @$(RM) -rf core *.o *.test tmp* \ fullbench-dll$(EXT) fullbench-lib$(EXT) \ fullbench$(EXT) fullbench32$(EXT) \ fuzzer$(EXT) fuzzer32$(EXT) \ frametest$(EXT) frametest32$(EXT) \ fasttest$(EXT) roundTripTest$(EXT) \ datagen$(EXT) checkTag$(EXT) \ - frameTest$(EXT) - @rm -fR $(TESTDIR) + frameTest$(EXT) + @$(RM) -rf $(TESTDIR) @echo Cleaning completed .PHONY: versionsTest -- cgit v0.12 From b92681f3c0cf0b054e6f235f338ee2dcb92ec37b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 8 Apr 2019 14:10:59 -0700 Subject: fullbench: assert lz4_stream_t initialization --- tests/fullbench.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/fullbench.c b/tests/fullbench.c index 61d6b78..34c9b7b 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -161,12 +161,14 @@ static size_t BMK_findMaxMem(U64 requiredMem) static LZ4_stream_t LZ4_stream; static void local_LZ4_resetDictT(void) { - LZ4_initStream(&LZ4_stream, sizeof(LZ4_stream)); + void* const r = LZ4_initStream(&LZ4_stream, sizeof(LZ4_stream)); + assert(r != NULL); } static void local_LZ4_createStream(void) { - LZ4_initStream(&LZ4_stream, sizeof(LZ4_stream)); + void* const r = LZ4_initStream(&LZ4_stream, sizeof(LZ4_stream)); + assert(r != NULL); } static int local_LZ4_saveDict(const char* in, char* out, int inSize) -- cgit v0.12 From da19cc79da6eb7aba915e6deae57ca5c7ac6930f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 8 Apr 2019 14:21:09 -0700 Subject: checkFrame: removed %zu not liked by mingw --- tests/checkFrame.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/tests/checkFrame.c b/tests/checkFrame.c index f7e7a50..50c0405 100644 --- a/tests/checkFrame.c +++ b/tests/checkFrame.c @@ -1,6 +1,6 @@ /* checkFrame - verify frame headers - Copyright (C) Yann Collet 2014-2016 + Copyright (C) Yann Collet 2014-present GPL v2 License @@ -159,8 +159,12 @@ int frameCheck(cRess_t ress, FILE* const srcFile, unsigned bsid, size_t blockSiz curblocksize = 0; remaining = readSize - pos; nextToLoad = LZ4F_getFrameInfo(ress.ctx, &frameInfo, (char*)(ress.srcBuffer)+pos, &remaining); - if (LZ4F_isError(nextToLoad)) EXM_THROW(22, "Error getting frame info: %s", LZ4F_getErrorName(nextToLoad)); /* XXX */ - if (frameInfo.blockSizeID != bsid) EXM_THROW(23, "Block size ID %u != expected %u", frameInfo.blockSizeID, bsid); + if (LZ4F_isError(nextToLoad)) + EXM_THROW(22, "Error getting frame info: %s", + LZ4F_getErrorName(nextToLoad)); + if (frameInfo.blockSizeID != bsid) + EXM_THROW(23, "Block size ID %u != expected %u", + frameInfo.blockSizeID, bsid); pos += remaining; /* nextToLoad should be block header size */ remaining = nextToLoad; @@ -189,7 +193,8 @@ int frameCheck(cRess_t ress, FILE* const srcFile, unsigned bsid, size_t blockSiz /* detect small block due to end of frame; the final 4-byte frame checksum could be left in the buffer */ if ((curblocksize != 0) && (nextToLoad > 4)) { if (curblocksize != blockSize) - EXM_THROW(25, "Block size %zu != expected %zu, pos %zu\n", curblocksize, blockSize, pos); + EXM_THROW(25, "Block size %u != expected %u, pos %u\n", + (unsigned)curblocksize, (unsigned)blockSize, (unsigned)pos); } curblocksize = 0; } @@ -220,7 +225,7 @@ int FUZ_usage(const char* programName) int main(int argc, const char** argv) { int argNb; - int bsid=0; + unsigned bsid=0; size_t blockSize=0; const char* const programName = argv[0]; @@ -262,7 +267,7 @@ int main(int argc, const char** argv) bsid=0; while ((*argument>='0') && (*argument<='9')) { bsid *= 10; - bsid += *argument - '0'; + bsid += (unsigned)(*argument - '0'); argument++; } break; @@ -272,7 +277,7 @@ int main(int argc, const char** argv) blockSize=0; while ((*argument>='0') && (*argument<='9')) { blockSize *= 10; - blockSize += *argument - '0'; + blockSize += (size_t)(*argument - '0'); argument++; } break; -- cgit v0.12 From 111df0fa45729538cc8ec526c71e854d0f15dc2e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 8 Apr 2019 16:47:21 -0700 Subject: removed LZ4_stream_t alignment test on Visual it fails on x86 32-bit mode : Visual reports an alignment of 8-bytes (even with alignof()) but actually only align LZ4_stream_t on 4 bytes. The alignment check then fails, resulting in missed initialization. --- lib/lz4.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/lz4.c b/lib/lz4.c index a2e58c0..04a30e7 100644 --- a/lib/lz4.c +++ b/lib/lz4.c @@ -1284,17 +1284,25 @@ LZ4_stream_t* LZ4_createStream(void) return lz4s; } +#ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 : + it reports an aligment of 8-bytes, + while actually aligning LZ4_stream_t on 4 bytes. */ static size_t LZ4_stream_t_alignment(void) { struct { char c; LZ4_stream_t t; } t_a; return sizeof(t_a) - sizeof(t_a.t); } +#endif LZ4_stream_t* LZ4_initStream (void* buffer, size_t size) { DEBUGLOG(5, "LZ4_initStream"); if (size < sizeof(LZ4_stream_t)) return NULL; +#ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 : + it reports an aligment of 8-bytes, + while actually aligning LZ4_stream_t on 4 bytes. */ if (((size_t)buffer) & (LZ4_stream_t_alignment() - 1)) return NULL; /* alignment check */ +#endif MEM_INIT(buffer, 0, sizeof(LZ4_stream_t)); return (LZ4_stream_t*)buffer; } -- cgit v0.12 From 5ef4f3ce913dae19f6bcd065a2b231c5461e4233 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 8 Apr 2019 16:51:22 -0700 Subject: check some more initialization result ensure it's not NULL. --- lib/lz4.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/lz4.c b/lib/lz4.c index 04a30e7..5fbc7c7 100644 --- a/lib/lz4.c +++ b/lib/lz4.c @@ -1126,6 +1126,7 @@ _failure: int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) { LZ4_stream_t_internal* const ctx = & LZ4_initStream(state, sizeof(LZ4_stream_t)) -> internal_donotuse; + assert(ctx != NULL); if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; if (maxOutputSize >= LZ4_compressBound(inputSize)) { if (inputSize < LZ4_64Klimit) { @@ -1236,7 +1237,8 @@ int LZ4_compress_fast_force(const char* src, char* dst, int srcSize, int dstCapa * _continue() call without resetting it. */ static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize) { - LZ4_initStream(state, sizeof (*state)); + void* const s = LZ4_initStream(state, sizeof (*state)); + assert(s != NULL); (void)s; if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) { /* compression success is guaranteed */ return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1); @@ -1307,6 +1309,8 @@ LZ4_stream_t* LZ4_initStream (void* buffer, size_t size) return (LZ4_stream_t*)buffer; } +/* resetStream is now deprecated, + * prefer initStream() which is more general */ void LZ4_resetStream (LZ4_stream_t* LZ4_stream) { DEBUGLOG(5, "LZ4_resetStream (ctx:%p)", LZ4_stream); -- cgit v0.12 From 14c71dfa9cc7161e1283e27bc688fd2bbeb637a2 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 9 Apr 2019 13:55:42 -0700 Subject: modified LZ4_initStreamHC() to look like LZ4_initStream() it is now a pure initializer, for statically allocated states. It can initialize any memory area, and because of this, requires size. --- doc/lz4_manual.html | 31 +++++++++------ lib/lz4.c | 1 + lib/lz4frame.c | 3 +- lib/lz4hc.c | 109 +++++++++++++++++++++++++++++++++++----------------- lib/lz4hc.h | 6 +-- tests/fullbench.c | 2 +- tests/fuzzer.c | 39 ++++++++++--------- 7 files changed, 119 insertions(+), 72 deletions(-) diff --git a/doc/lz4_manual.html b/doc/lz4_manual.html index 5db3ec9..1c6dba7 100644 --- a/doc/lz4_manual.html +++ b/doc/lz4_manual.html @@ -159,19 +159,23 @@ int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int src

Use this to prepare an LZ4_stream_t for a new chain of dependent blocks (e.g., LZ4_compress_fast_continue()). - An LZ4_stream_t must be initialized once. + An LZ4_stream_t must be initialized once before usage. This is automatically done when created by LZ4_createStream(). However, should the LZ4_stream_t be simply declared on stack (for example), - it's necessary to initialize first using LZ4_initStream(). + it's necessary to initialize it first, using LZ4_initStream(). - After that, start any new stream with LZ4_resetStream_fast(). + After init, start any new stream with LZ4_resetStream_fast(). A same LZ4_stream_t can be re-used multiple times consecutively and compress multiple streams, provided that it starts each new stream with LZ4_resetStream_fast(). LZ4_resetStream_fast() is much faster than LZ4_initStream(), but is not compatible with memory regions containing garbage data. - For this reason, LZ4_stream_t must be initialized at least once, + + Note: it's only useful to call LZ4_resetStream_fast() + in the context of streaming compression. + The *extState* functions perform their own resets. + Invoking LZ4_resetStream_fast() before is redundant, and even counterproductive.


@@ -382,13 +386,16 @@ union LZ4_stream_u {
LZ4_stream_t* LZ4_initStream (void* buffer, size_t size);
 

An LZ4_stream_t structure must be initialized at least once. - While this is automatically done when invoking LZ4_createStream(), - it's not when the structure is simply declared on stack (for example). - Use this function to properly initialize a newly declared LZ4_stream_t. - It can also accept any arbitrary buffer of sufficient size as input, - and will return a pointer of proper type upon initialization. - Note : initialization can fail if size < sizeof(LZ4_stream_t). - In which case, the function will @return NULL. + This is automatically done when invoking LZ4_createStream(), + but it's not when the structure is simply declared on stack (for example). + + Use LZ4_initStream() to properly initialize a newly declared LZ4_stream_t. + It can also initialize any arbitrary buffer of sufficient size, + and will @return a pointer of proper type upon initialization. + + Note : initialization fails if size and alignment conditions are not respected. + In which case, the function will @return NULL. + Note2: An LZ4_stream_t structure guarantees correct alignment and size.


@@ -468,7 +475,7 @@ int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize,


-
//LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);
+
void LZ4_resetStream (LZ4_stream_t* streamPtr);
 

An LZ4_stream_t structure must be initialized at least once. This is done with LZ4_initStream(), or LZ4_resetStream(). Consider switching to LZ4_initStream(), diff --git a/lib/lz4.c b/lib/lz4.c index 5fbc7c7..34587ce 100644 --- a/lib/lz4.c +++ b/lib/lz4.c @@ -1299,6 +1299,7 @@ static size_t LZ4_stream_t_alignment(void) LZ4_stream_t* LZ4_initStream (void* buffer, size_t size) { DEBUGLOG(5, "LZ4_initStream"); + if (buffer == NULL) return NULL; if (size < sizeof(LZ4_stream_t)) return NULL; #ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 : it reports an aligment of 8-bytes, diff --git a/lib/lz4frame.c b/lib/lz4frame.c index 3b4fcee..efe38da 100644 --- a/lib/lz4frame.c +++ b/lib/lz4frame.c @@ -630,7 +630,8 @@ size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr, if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) { LZ4_initStream((LZ4_stream_t *) cctxPtr->lz4CtxPtr, sizeof (LZ4_stream_t)); } else { - LZ4_initStreamHC((LZ4_streamHC_t *) cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel); + LZ4_initStreamHC((LZ4_streamHC_t *) cctxPtr->lz4CtxPtr, sizeof(LZ4_streamHC_t)); + LZ4_setCompressionLevel((LZ4_streamHC_t *) cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel); } cctxPtr->lz4CtxState = ctxTypeID; } diff --git a/lib/lz4hc.c b/lib/lz4hc.c index 9e8b77e..693337a 100644 --- a/lib/lz4hc.c +++ b/lib/lz4hc.c @@ -103,7 +103,7 @@ static void LZ4HC_clearTables (LZ4HC_CCtx_internal* hc4) MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable)); } -static void LZ4HC_init (LZ4HC_CCtx_internal* hc4, const BYTE* start) +static void LZ4HC_init_internal (LZ4HC_CCtx_internal* hc4, const BYTE* start) { uptrval startingOffset = (uptrval)(hc4->end - hc4->base); if (startingOffset > 1 GB) { @@ -239,7 +239,7 @@ LZ4HC_InsertAndGetWiderMatch ( const BYTE* const dictBase = hc4->dictBase; int const lookBackLength = (int)(ip-iLowLimit); int nbAttempts = maxNbAttempts; - int matchChainPos = 0; + U32 matchChainPos = 0; U32 const pattern = LZ4_read32(ip); U32 matchIndex; repeat_state_e repeat = rep_untested; @@ -300,7 +300,7 @@ LZ4HC_InsertAndGetWiderMatch ( U32 const candidateDist = DELTANEXTU16(chainTable, matchIndex + (U32)pos); if (candidateDist > distanceToNextMatch) { distanceToNextMatch = candidateDist; - matchChainPos = pos; + matchChainPos = (U32)pos; } } if (distanceToNextMatch > 1) { if (distanceToNextMatch > matchIndex) break; /* avoid overflow */ @@ -793,7 +793,7 @@ LZ4HC_compress_generic_dictCtx ( limitedOutput_directive limit ) { - const size_t position = ctx->end - ctx->base - ctx->lowLimit; + const size_t position = (size_t)(ctx->end - ctx->base) - ctx->lowLimit; assert(ctx->dictCtx != NULL); if (position >= 64 KB) { ctx->dictCtx = NULL; @@ -827,14 +827,31 @@ LZ4HC_compress_generic ( } -int LZ4_sizeofStateHC(void) { return sizeof(LZ4_streamHC_t); } +int LZ4_sizeofStateHC(void) { return (int)sizeof(LZ4_streamHC_t); } +#ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 : + * it reports an aligment of 8-bytes, + * while actually aligning LZ4_streamHC_t on 4 bytes. */ +static size_t LZ4_streamHC_t_alignment(void) +{ + struct { char c; LZ4_streamHC_t t; } t_a; + return sizeof(t_a) - sizeof(t_a.t); +} +#endif + +/* state is presumed correctly initialized, + * in which case its size and alignment have already been validate */ int LZ4_compress_HC_extStateHC_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel) { LZ4HC_CCtx_internal* const ctx = &((LZ4_streamHC_t*)state)->internal_donotuse; +#ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 : + * it reports an aligment of 8-bytes, + * while actually aligning LZ4_streamHC_t on 4 bytes. */ + assert(((size_t)state & (LZ4_streamHC_t_alignment() - 1)) == 0); /* check alignment */ +#endif if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0; /* Error : state is not aligned for pointers (32 or 64 bits) */ LZ4_resetStreamHC_fast((LZ4_streamHC_t*)state, compressionLevel); - LZ4HC_init (ctx, (const BYTE*)src); + LZ4HC_init_internal (ctx, (const BYTE*)src); if (dstCapacity < LZ4_compressBound(srcSize)) return LZ4HC_compress_generic (ctx, src, dst, &srcSize, dstCapacity, compressionLevel, limitedOutput); else @@ -843,8 +860,8 @@ int LZ4_compress_HC_extStateHC_fastReset (void* state, const char* src, char* ds int LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel) { - if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0; /* Error : state is not aligned for pointers (32 or 64 bits) */ - LZ4_initStreamHC (state, compressionLevel); /* full initialization, as there is no guarantee on state's content (could be freshly malloc'ed) */ + LZ4_streamHC_t* const ctx = LZ4_initStreamHC(state, sizeof(*ctx)); + if (ctx==NULL) return 0; /* init failure */ return LZ4_compress_HC_extStateHC_fastReset(state, src, dst, srcSize, dstCapacity, compressionLevel); } @@ -863,12 +880,14 @@ int LZ4_compress_HC(const char* src, char* dst, int srcSize, int dstCapacity, in return cSize; } -int LZ4_compress_HC_destSize(void* LZ4HC_Data, const char* source, char* dest, int* sourceSizePtr, int targetDestSize, int cLevel) +/* state is presumed sized correctly (>= sizeof(LZ4_streamHC_t)) */ +int LZ4_compress_HC_destSize(void* state, const char* source, char* dest, int* sourceSizePtr, int targetDestSize, int cLevel) { - LZ4HC_CCtx_internal* const ctx = &((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse; - LZ4_initStreamHC(LZ4HC_Data, cLevel); /* full initialization, as there is no guarantee on state's content (could be freshly malloc'ed) */ - LZ4HC_init(ctx, (const BYTE*) source); - return LZ4HC_compress_generic(ctx, source, dest, sourceSizePtr, targetDestSize, cLevel, limitedDestSize); + LZ4_streamHC_t* const ctx = LZ4_initStreamHC(state, sizeof(*ctx)); + if (ctx==NULL) return 0; /* init failure */ + LZ4HC_init_internal(&ctx->internal_donotuse, (const BYTE*) source); + LZ4_setCompressionLevel(ctx, cLevel); + return LZ4HC_compress_generic(&ctx->internal_donotuse, source, dest, sourceSizePtr, targetDestSize, cLevel, limitedDestSize); } @@ -881,7 +900,7 @@ LZ4_streamHC_t* LZ4_createStreamHC(void) { LZ4_streamHC_t* const LZ4_streamHCPtr = (LZ4_streamHC_t*)ALLOC(sizeof(LZ4_streamHC_t)); if (LZ4_streamHCPtr==NULL) return NULL; - LZ4_initStreamHC(LZ4_streamHCPtr, LZ4HC_CLEVEL_DEFAULT); /* full initialization, malloc'ed buffer can be full of garbage */ + LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr)); /* full initialization, malloc'ed buffer can be full of garbage */ return LZ4_streamHCPtr; } @@ -894,37 +913,48 @@ int LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr) } -/* initialization */ -void LZ4_initStreamHC (void* state, int compressionLevel) +LZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size) { - LZ4_streamHC_t* const LZ4_streamHCPtr = (LZ4_streamHC_t*)state; - LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal) <= LZ4_STREAMHCSIZE); /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */ + LZ4_streamHC_t* const LZ4_streamHCPtr = (LZ4_streamHC_t*)buffer; + if (buffer == NULL) return NULL; + if (size < sizeof(LZ4_streamHC_t)) return NULL; +#ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 : + * it reports an aligment of 8-bytes, + * while actually aligning LZ4_streamHC_t on 4 bytes. */ + if (((size_t)buffer) & (LZ4_streamHC_t_alignment() - 1)) return NULL; /* alignment check */ +#endif + /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */ + LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal) <= LZ4_STREAMHCSIZE); DEBUGLOG(4, "LZ4_resetStreamHC(%p, %d)", LZ4_streamHCPtr, compressionLevel); + /* end-base will trigger a clearTable on starting compression */ LZ4_streamHCPtr->internal_donotuse.end = (const BYTE *)(ptrdiff_t)-1; LZ4_streamHCPtr->internal_donotuse.base = NULL; LZ4_streamHCPtr->internal_donotuse.dictCtx = NULL; LZ4_streamHCPtr->internal_donotuse.favorDecSpeed = 0; LZ4_streamHCPtr->internal_donotuse.dirty = 0; - LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel); + LZ4_setCompressionLevel(LZ4_streamHCPtr, LZ4HC_CLEVEL_DEFAULT); + return LZ4_streamHCPtr; } /* just a stub */ void LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) { - LZ4_initStreamHC(LZ4_streamHCPtr, compressionLevel); + LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr)); + LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel); } void LZ4_resetStreamHC_fast (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) { DEBUGLOG(4, "LZ4_resetStreamHC_fast(%p, %d)", LZ4_streamHCPtr, compressionLevel); if (LZ4_streamHCPtr->internal_donotuse.dirty) { - LZ4_initStreamHC(LZ4_streamHCPtr, compressionLevel); + LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr)); } else { + /* preserve end - base : can trigger clearTable's threshold */ LZ4_streamHCPtr->internal_donotuse.end -= (uptrval)LZ4_streamHCPtr->internal_donotuse.base; LZ4_streamHCPtr->internal_donotuse.base = NULL; LZ4_streamHCPtr->internal_donotuse.dictCtx = NULL; - LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel); } + LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel); } void LZ4_setCompressionLevel(LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) @@ -939,16 +969,19 @@ void LZ4_favorDecompressionSpeed(LZ4_streamHC_t* LZ4_streamHCPtr, int favor) LZ4_streamHCPtr->internal_donotuse.favorDecSpeed = (favor!=0); } +/* LZ4_loadDictHC() : + * LZ4_streamHCPtr is presumed properly initialized */ int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, const char* dictionary, int dictSize) { LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse; DEBUGLOG(4, "LZ4_loadDictHC(%p, %p, %d)", LZ4_streamHCPtr, dictionary, dictSize); + assert(LZ4_streamHCPtr != NULL); if (dictSize > 64 KB) { dictionary += dictSize - 64 KB; dictSize = 64 KB; } - LZ4_initStreamHC(LZ4_streamHCPtr, ctxPtr->compressionLevel); - LZ4HC_init (ctxPtr, (const BYTE*)dictionary); + LZ4_resetStreamHC_fast(LZ4_streamHCPtr, ctxPtr->compressionLevel); + LZ4HC_init_internal (ctxPtr, (const BYTE*)dictionary); ctxPtr->end = (const BYTE*)dictionary + dictSize; if (dictSize >= 4) LZ4HC_Insert (ctxPtr, ctxPtr->end-3); return dictSize; @@ -982,8 +1015,9 @@ static int LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr, { LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse; DEBUGLOG(4, "LZ4_compressHC_continue_generic(%p, %p, %d)", LZ4_streamHCPtr, src, *srcSizePtr); + assert(ctxPtr != NULL); /* auto-init if forgotten */ - if (ctxPtr->base == NULL) LZ4HC_init (ctxPtr, (const BYTE*) src); + if (ctxPtr->base == NULL) LZ4HC_init_internal (ctxPtr, (const BYTE*) src); /* Check overflow */ if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB) { @@ -1046,11 +1080,13 @@ int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictS } -/*********************************** +/*************************************************** * Deprecated Functions -***********************************/ +***************************************************/ + /* These functions currently generate deprecation warnings */ -/* Deprecated compression functions */ + +/* Wrappers for deprecated compression functions */ int LZ4_compressHC(const char* src, char* dst, int srcSize) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), 0); } int LZ4_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, 0); } int LZ4_compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); } @@ -1066,25 +1102,26 @@ int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* ctx, const char* src, /* Deprecated streaming functions */ int LZ4_sizeofStreamStateHC(void) { return LZ4_STREAMHCSIZE; } +/* state is presumed correctly sized, aka >= sizeof(LZ4_streamHC_t) + * @return : 0 on success, !=0 if error */ int LZ4_resetStreamStateHC(void* state, char* inputBuffer) { - LZ4HC_CCtx_internal *ctx = &((LZ4_streamHC_t*)state)->internal_donotuse; - if ((((size_t)state) & (sizeof(void*)-1)) != 0) return 1; /* Error : pointer is not aligned for pointer (32 or 64 bits) */ - LZ4_initStreamHC((LZ4_streamHC_t*)state, ((LZ4_streamHC_t*)state)->internal_donotuse.compressionLevel); - LZ4HC_init(ctx, (const BYTE*)inputBuffer); + LZ4_streamHC_t* const hc4 = LZ4_initStreamHC(state, sizeof(*hc4)); + if (hc4 == NULL) return 1; /* init failed */ + LZ4HC_init_internal (&hc4->internal_donotuse, (const BYTE*)inputBuffer); return 0; } void* LZ4_createHC (const char* inputBuffer) { - LZ4_streamHC_t* hc4 = (LZ4_streamHC_t*)ALLOC(sizeof(LZ4_streamHC_t)); + LZ4_streamHC_t* const hc4 = LZ4_createStreamHC(); if (hc4 == NULL) return NULL; /* not enough memory */ - LZ4_initStreamHC(hc4, 0 /* compressionLevel */); - LZ4HC_init (&hc4->internal_donotuse, (const BYTE*)inputBuffer); + LZ4HC_init_internal (&hc4->internal_donotuse, (const BYTE*)inputBuffer); return hc4; } -int LZ4_freeHC (void* LZ4HC_Data) { +int LZ4_freeHC (void* LZ4HC_Data) +{ if (!LZ4HC_Data) return 0; /* support free on NULL */ FREEMEM(LZ4HC_Data); return 0; diff --git a/lib/lz4hc.h b/lib/lz4hc.h index fbf4518..445c126 100644 --- a/lib/lz4hc.h +++ b/lib/lz4hc.h @@ -265,7 +265,7 @@ union LZ4_streamHC_u { * Static allocation shall only be used in combination with static linking. */ -LZ4LIB_API void LZ4_initStreamHC (void* streamHCPtr, int compressionLevel); /* v1.9.0+ */ +LZ4LIB_API LZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size); /*-************************************ @@ -299,7 +299,7 @@ LZ4_DEPRECATED("use LZ4_freeStreamHC() instead") LZ4LIB_API int LZ4_freeHC ( LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel); LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel); LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API int LZ4_sizeofStreamStateHC(void); -LZ4_DEPRECATED("use LZ4_resetStreamHC() instead") LZ4LIB_API int LZ4_resetStreamStateHC(void* state, char* inputBuffer); +LZ4_DEPRECATED("use LZ4_initStreamHC() instead") LZ4LIB_API int LZ4_resetStreamStateHC(void* state, char* inputBuffer); /* LZ4_resetStreamHC() is now replaced by LZ4_initStreamHC(). @@ -310,7 +310,7 @@ LZ4_DEPRECATED("use LZ4_resetStreamHC() instead") LZ4LIB_API int LZ4_resetStr * It is recommended to switch to LZ4_initStreamHC(). * LZ4_resetStreamHC() will generate deprecation warnings in a future version. */ -LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel); +//LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel); #if defined (__cplusplus) diff --git a/tests/fullbench.c b/tests/fullbench.c index 34c9b7b..456c916 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -245,7 +245,7 @@ static int local_LZ4_compress_forceDict(const char* in, char* out, int inSize) LZ4_streamHC_t LZ4_streamHC; static void local_LZ4_resetStreamHC(void) { - LZ4_initStreamHC(&LZ4_streamHC, 0); + LZ4_initStreamHC(&LZ4_streamHC, sizeof(LZ4_streamHC)); } static int local_LZ4_saveDictHC(const char* in, char* out, int inSize) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index d899cef..8828c06 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -345,7 +345,8 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c DISPLAY("Not enough memory to start fuzzer tests"); goto _output_error; } - memset(&LZ4dict, 0, sizeof(LZ4dict)); + if ( LZ4_initStream(&LZ4dict, sizeof(LZ4dict)) == NULL) abort(); + if ( LZ4_initStreamHC(&LZ4dictHC, sizeof(LZ4dictHC)) == NULL) abort(); { U32 randState = coreRandState ^ PRIME3; FUZ_fillCompressibleNoiseBuffer(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, compressibility, &randState); } @@ -800,7 +801,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize, dict, dictSize); FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data"); FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size"); - { U32 const crcCheck = XXH32(decodedBuffer, blockSize, 0); + { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe_usingDict corrupted decoded data"); } @@ -829,9 +830,8 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c FUZ_DISPLAYTEST("LZ4_compress_HC_continue with an external dictionary"); dict -= (FUZ_rand(&randState) & 7); /* even bigger separation */ if (dict < (char*)CNBuffer) dict = (char*)CNBuffer; - LZ4_initStreamHC (&LZ4dictHC, compressionLevel); LZ4_loadDictHC(&LZ4dictHC, dict, dictSize); - LZ4_setCompressionLevel(&LZ4dictHC, compressionLevel-1); + LZ4_setCompressionLevel (&LZ4dictHC, compressionLevel); blockContinueCompressedSize = LZ4_compress_HC_continue(&LZ4dictHC, block, compressedBuffer, blockSize, (int)compressedBufferSize); FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_HC_continue failed"); FUZ_CHECKTEST(LZ4dictHC.internal_donotuse.dirty, "Context should be clean"); @@ -863,11 +863,11 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c FUZ_DISPLAYTEST(); { LZ4_streamHC_t LZ4_streamHC; + LZ4_initStreamHC(&LZ4_streamHC, sizeof(LZ4_streamHC)); - LZ4_initStreamHC (&LZ4dictHC, compressionLevel); LZ4_loadDictHC(&LZ4dictHC, dict, dictSize); - LZ4_initStreamHC (&LZ4_streamHC, compressionLevel); LZ4_attach_HC_dictionary(&LZ4_streamHC, &LZ4dictHC); + LZ4_setCompressionLevel (&LZ4_streamHC, compressionLevel); blockContinueCompressedSize = LZ4_compress_HC_continue(&LZ4_streamHC, block, compressedBuffer, blockSize, (int)compressedBufferSize); FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_HC_continue with ExtDictCtx failed"); FUZ_CHECKTEST(LZ4_streamHC.internal_donotuse.dirty, "Context should be clean"); @@ -894,25 +894,25 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_compress_HC_continue using ExtDictCtx and fast reset size is different (%i != %i)", ret, blockContinueCompressedSize); FUZ_CHECKTEST(ret<=0, "LZ4_compress_HC_continue using ExtDictCtx and fast reset should work : enough size available within output buffer"); FUZ_CHECKTEST(LZ4_streamHC.internal_donotuse.dirty, "Context should be clean"); + } - FUZ_DISPLAYTEST(); - decodedBuffer[blockSize] = 0; - ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize, dict, dictSize); - FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data"); - FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size"); - { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); - if (crcCheck!=crcOrig) FUZ_findDiff(block, decodedBuffer); - FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe_usingDict corrupted decoded data"); - } + FUZ_DISPLAYTEST(); + decodedBuffer[blockSize] = 0; + ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize, dict, dictSize); + FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data"); + FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size"); + { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); + if (crcCheck!=crcOrig) FUZ_findDiff(block, decodedBuffer); + FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe_usingDict corrupted decoded data"); } /* Compress HC continue destSize */ FUZ_DISPLAYTEST(); - { int const availableSpace = (FUZ_rand(&randState) % blockSize) + 5; + { int const availableSpace = (int)(FUZ_rand(&randState) % blockSize) + 5; int consumedSize = blockSize; FUZ_DISPLAYTEST(); - LZ4_initStreamHC (&LZ4dictHC, compressionLevel); LZ4_loadDictHC(&LZ4dictHC, dict, dictSize); + LZ4_setCompressionLevel(&LZ4dictHC, compressionLevel); blockContinueCompressedSize = LZ4_compress_HC_continue_destSize(&LZ4dictHC, block, compressedBuffer, &consumedSize, availableSpace); DISPLAYLEVEL(5, " LZ4_compress_HC_continue_destSize : compressed %6i/%6i into %6i/%6i at cLevel=%i\n", consumedSize, blockSize, blockContinueCompressedSize, availableSpace, compressionLevel); FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_HC_continue_destSize failed"); @@ -1067,6 +1067,7 @@ static void FUZ_unitTests(int compressionLevel) { LZ4_streamHC_t sHC; /* statically allocated */ U64 crcOrig; int result; + LZ4_initStreamHC(&sHC, sizeof(sHC)); /* Allocation test */ DISPLAYLEVEL(3, " Basic HC allocation : "); @@ -1079,7 +1080,7 @@ static void FUZ_unitTests(int compressionLevel) /* simple HC compression test */ DISPLAYLEVEL(3, " Simple HC round-trip : "); { U64 const crc64 = XXH64(testInput, testCompressedSize, 0); - LZ4_initStreamHC(&sHC, compressionLevel); + LZ4_setCompressionLevel(&sHC, compressionLevel); result = LZ4_compress_HC_continue(&sHC, testInput, testCompressed, testCompressedSize, testCompressedSize-1); FUZ_CHECKTEST(result==0, "LZ4_compressHC_limitedOutput_continue() compression failed"); FUZ_CHECKTEST(sHC.internal_donotuse.dirty, "Context should be clean"); @@ -1104,7 +1105,7 @@ static void FUZ_unitTests(int compressionLevel) memset(block, 0, blockSize); ((char*)dstBlock)[targetSize] = sentinel; - LZ4_initStreamHC(&sHC, 3); + LZ4_resetStreamHC_fast(&sHC, 3); assert(blockSize < INT_MAX); srcSize = (int)blockSize; assert(targetSize < INT_MAX); -- cgit v0.12 From 887e8a4d012ac7b2034df9a27b1422ae98fee3a9 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 9 Apr 2019 14:00:30 -0700 Subject: re-enable LZ4_resetStreamHC() towards deprecation, but still available and fully supported --- lib/lz4hc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lz4hc.h b/lib/lz4hc.h index 445c126..ea90230 100644 --- a/lib/lz4hc.h +++ b/lib/lz4hc.h @@ -310,7 +310,7 @@ LZ4_DEPRECATED("use LZ4_initStreamHC() instead") LZ4LIB_API int LZ4_resetStre * It is recommended to switch to LZ4_initStreamHC(). * LZ4_resetStreamHC() will generate deprecation warnings in a future version. */ -//LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel); +LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel); #if defined (__cplusplus) -- cgit v0.12 From d8d5f14138109f81d0f5dba60ac179cfe16405c5 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 9 Apr 2019 15:37:59 -0700 Subject: fixed loadDictHC by making a full initialization instead of a fast reset. --- lib/lz4hc.c | 28 ++++++++++++++++++---------- tests/fuzzer.c | 8 ++++---- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/lib/lz4hc.c b/lib/lz4hc.c index 693337a..411b6cc 100644 --- a/lib/lz4hc.c +++ b/lib/lz4hc.c @@ -736,10 +736,10 @@ LZ4_FORCE_INLINE int LZ4HC_compress_generic_internal ( { lz4opt,16384,LZ4_OPT_NUM }, /* 12==LZ4HC_CLEVEL_MAX */ }; - DEBUGLOG(4, "LZ4HC_compress_generic(%p, %p, %d)", ctx, src, *srcSizePtr); + DEBUGLOG(4, "LZ4HC_compress_generic(ctx=%p, src=%p, srcSize=%d)", ctx, src, *srcSizePtr); - if (limit == limitedDestSize && dstCapacity < 1) return 0; /* Impossible to store anything */ - if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size (too large or negative) */ + if (limit == limitedDestSize && dstCapacity < 1) return 0; /* Impossible to store anything */ + if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size (too large or negative) */ ctx->end += *srcSizePtr; if (cLevel < 1) cLevel = LZ4HC_CLEVEL_DEFAULT; /* note : convention is different from lz4frame, maybe something to review */ @@ -756,7 +756,7 @@ LZ4_FORCE_INLINE int LZ4HC_compress_generic_internal ( assert(cParam.strat == lz4opt); result = LZ4HC_compress_optimal(ctx, src, dst, srcSizePtr, dstCapacity, - cParam.nbSearches, cParam.targetLength, limit, + (int)cParam.nbSearches, cParam.targetLength, limit, cLevel == LZ4HC_CLEVEL_MAX, /* ultra mode */ dict, favor); } @@ -925,7 +925,7 @@ LZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size) #endif /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */ LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal) <= LZ4_STREAMHCSIZE); - DEBUGLOG(4, "LZ4_resetStreamHC(%p, %d)", LZ4_streamHCPtr, compressionLevel); + DEBUGLOG(4, "LZ4_initStreamHC(%p, %u)", LZ4_streamHCPtr, (unsigned)size); /* end-base will trigger a clearTable on starting compression */ LZ4_streamHCPtr->internal_donotuse.end = (const BYTE *)(ptrdiff_t)-1; LZ4_streamHCPtr->internal_donotuse.base = NULL; @@ -959,6 +959,7 @@ void LZ4_resetStreamHC_fast (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLev void LZ4_setCompressionLevel(LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) { + DEBUGLOG(5, "LZ4_setCompressionLevel(%p, %d)", LZ4_streamHCPtr, compressionLevel); if (compressionLevel < 1) compressionLevel = LZ4HC_CLEVEL_DEFAULT; if (compressionLevel > LZ4HC_CLEVEL_MAX) compressionLevel = LZ4HC_CLEVEL_MAX; LZ4_streamHCPtr->internal_donotuse.compressionLevel = (short)compressionLevel; @@ -971,7 +972,8 @@ void LZ4_favorDecompressionSpeed(LZ4_streamHC_t* LZ4_streamHCPtr, int favor) /* LZ4_loadDictHC() : * LZ4_streamHCPtr is presumed properly initialized */ -int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, const char* dictionary, int dictSize) +int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, + const char* dictionary, int dictSize) { LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse; DEBUGLOG(4, "LZ4_loadDictHC(%p, %p, %d)", LZ4_streamHCPtr, dictionary, dictSize); @@ -980,7 +982,11 @@ int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, const char* dictionary, int dictionary += dictSize - 64 KB; dictSize = 64 KB; } - LZ4_resetStreamHC_fast(LZ4_streamHCPtr, ctxPtr->compressionLevel); + /* need a full initialization, there are bad side-effects when using resetFast() */ + { int const cLevel = ctxPtr->compressionLevel; + LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr)); + LZ4_setCompressionLevel(LZ4_streamHCPtr, cLevel); + } LZ4HC_init_internal (ctxPtr, (const BYTE*)dictionary); ctxPtr->end = (const BYTE*)dictionary + dictSize; if (dictSize >= 4) LZ4HC_Insert (ctxPtr, ctxPtr->end-3); @@ -1014,7 +1020,8 @@ static int LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr, limitedOutput_directive limit) { LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse; - DEBUGLOG(4, "LZ4_compressHC_continue_generic(%p, %p, %d)", LZ4_streamHCPtr, src, *srcSizePtr); + DEBUGLOG(4, "LZ4_compressHC_continue_generic(ctx=%p, src=%p, srcSize=%d)", + LZ4_streamHCPtr, src, *srcSizePtr); assert(ctxPtr != NULL); /* auto-init if forgotten */ if (ctxPtr->base == NULL) LZ4HC_init_internal (ctxPtr, (const BYTE*) src); @@ -1027,7 +1034,8 @@ static int LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr, } /* Check if blocks follow each other */ - if ((const BYTE*)src != ctxPtr->end) LZ4HC_setExternalDict(ctxPtr, (const BYTE*)src); + if ((const BYTE*)src != ctxPtr->end) + LZ4HC_setExternalDict(ctxPtr, (const BYTE*)src); /* Check overlapping input/dictionary space */ { const BYTE* sourceEnd = (const BYTE*) src + *srcSizePtr; @@ -1237,7 +1245,7 @@ static int LZ4HC_compress_optimal ( LZ4HC_CCtx_internal* ctx, BYTE* oend = op + dstCapacity; /* init */ - DEBUGLOG(5, "LZ4HC_compress_optimal"); + DEBUGLOG(5, "LZ4HC_compress_optimal(dst=%p, dstCapa=%u)", dst, (unsigned)dstCapacity); *srcSizePtr = 0; if (limit == limitedDestSize) oend -= LASTLITERALS; /* Hack for support LZ4 format restriction */ if (sufficient_len >= LZ4_OPT_NUM) sufficient_len = LZ4_OPT_NUM-1; diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 8828c06..27d8d9c 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -836,16 +836,16 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_HC_continue failed"); FUZ_CHECKTEST(LZ4dictHC.internal_donotuse.dirty, "Context should be clean"); - FUZ_DISPLAYTEST(); + FUZ_DISPLAYTEST("LZ4_compress_HC_continue with same external dictionary, but output buffer 1 byte too short"); LZ4_loadDictHC(&LZ4dictHC, dict, dictSize); ret = LZ4_compress_HC_continue(&LZ4dictHC, block, compressedBuffer, blockSize, blockContinueCompressedSize-1); - FUZ_CHECKTEST(ret>0, "LZ4_compress_HC_continue using ExtDict should fail : one missing byte for output buffer (%i != %i)", ret, blockContinueCompressedSize); + FUZ_CHECKTEST(ret>0, "LZ4_compress_HC_continue using ExtDict should fail : one missing byte for output buffer (expected %i, but result=%i)", blockContinueCompressedSize, ret); FUZ_CHECKTEST(!LZ4dictHC.internal_donotuse.dirty, "Context should be dirty"); - FUZ_DISPLAYTEST(); + FUZ_DISPLAYTEST("LZ4_compress_HC_continue with same external dictionary, and output buffer exactly the right size"); LZ4_loadDictHC(&LZ4dictHC, dict, dictSize); ret = LZ4_compress_HC_continue(&LZ4dictHC, block, compressedBuffer, blockSize, blockContinueCompressedSize); - FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_compress_HC_continue size is different (%i != %i)", ret, blockContinueCompressedSize); + FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_compress_HC_continue size is different : ret(%i) != expected(%i)", ret, blockContinueCompressedSize); FUZ_CHECKTEST(ret<=0, "LZ4_compress_HC_continue should work : enough size available within output buffer"); FUZ_CHECKTEST(LZ4dictHC.internal_donotuse.dirty, "Context should be clean"); -- cgit v0.12