extlz4 0.2.4.3 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -72,20 +72,24 @@ extern "C" {
72
72
  /*
73
73
  * LZ4_DLL_EXPORT :
74
74
  * Enable exporting of functions when building a Windows DLL
75
- * LZ4LIB_API :
75
+ * LZ4LIB_VISIBILITY :
76
76
  * Control library symbols visibility.
77
77
  */
78
+ #ifndef LZ4LIB_VISIBILITY
79
+ # if defined(__GNUC__) && (__GNUC__ >= 4)
80
+ # define LZ4LIB_VISIBILITY __attribute__ ((visibility ("default")))
81
+ # else
82
+ # define LZ4LIB_VISIBILITY
83
+ # endif
84
+ #endif
78
85
  #if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)
79
- # define LZ4LIB_API __declspec(dllexport)
86
+ # define LZ4LIB_API __declspec(dllexport) LZ4LIB_VISIBILITY
80
87
  #elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)
81
- # define LZ4LIB_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
82
- #elif defined(__GNUC__) && (__GNUC__ >= 4)
83
- # define LZ4LIB_API __attribute__ ((__visibility__ ("default")))
88
+ # define LZ4LIB_API __declspec(dllimport) LZ4LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
84
89
  #else
85
- # define LZ4LIB_API
90
+ # define LZ4LIB_API LZ4LIB_VISIBILITY
86
91
  #endif
87
92
 
88
-
89
93
  /*------ Version ------*/
90
94
  #define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
91
95
  #define LZ4_VERSION_MINOR 8 /* for new (non-breaking) interface capabilities */
@@ -120,30 +124,30 @@ LZ4LIB_API const char* LZ4_versionString (void); /**< library version string;
120
124
  * Simple Functions
121
125
  **************************************/
122
126
  /*! LZ4_compress_default() :
123
- Compresses 'sourceSize' bytes from buffer 'source'
124
- into already allocated 'dest' buffer of size 'maxDestSize'.
125
- Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize).
127
+ Compresses 'srcSize' bytes from buffer 'src'
128
+ into already allocated 'dst' buffer of size 'dstCapacity'.
129
+ Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).
126
130
  It also runs faster, so it's a recommended setting.
127
- If the function cannot compress 'source' into a more limited 'dest' budget,
131
+ If the function cannot compress 'src' into a limited 'dst' budget,
128
132
  compression stops *immediately*, and the function result is zero.
129
- As a consequence, 'dest' content is not valid.
130
- This function never writes outside 'dest' buffer, nor read outside 'source' buffer.
131
- sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE
132
- maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)
133
- return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)
134
- or 0 if compression fails */
135
- LZ4LIB_API int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize);
133
+ As a consequence, 'dst' content is not valid.
134
+ This function never writes outside 'dst' buffer, nor read outside 'source' buffer.
135
+ srcSize : supported max value is LZ4_MAX_INPUT_VALUE
136
+ dstCapacity : full or partial size of buffer 'dst' (which must be already allocated)
137
+ return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)
138
+ or 0 if compression fails */
139
+ LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);
136
140
 
137
141
  /*! LZ4_decompress_safe() :
138
- compressedSize : is the precise full size of the compressed block.
139
- maxDecompressedSize : is the size of destination buffer, which must be already allocated.
140
- return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
141
- If destination buffer is not large enough, decoding will stop and output an error code (<0).
142
+ compressedSize : is the exact complete size of the compressed block.
143
+ dstCapacity : is the size of destination buffer, which must be already allocated.
144
+ return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity)
145
+ If destination buffer is not large enough, decoding will stop and output an error code (negative value).
142
146
  If the source stream is detected malformed, the function will stop decoding and return a negative result.
143
147
  This function is protected against buffer overflow exploits, including malicious data packets.
144
148
  It never writes outside output buffer, nor reads outside input buffer.
145
149
  */
146
- LZ4LIB_API int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
150
+ LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);
147
151
 
148
152
 
149
153
  /*-************************************
@@ -172,7 +176,7 @@ LZ4_compress_fast() :
172
176
  An acceleration value of "1" is the same as regular LZ4_compress_default()
173
177
  Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1.
174
178
  */
175
- LZ4LIB_API int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration);
179
+ LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
176
180
 
177
181
 
178
182
  /*!
@@ -183,49 +187,49 @@ LZ4_compress_fast_extState() :
183
187
  Then, provide it as 'void* state' to compression function.
184
188
  */
185
189
  LZ4LIB_API int LZ4_sizeofState(void);
186
- LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration);
190
+ LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
187
191
 
188
192
 
189
193
  /*!
190
194
  LZ4_compress_destSize() :
191
- Reverse the logic, by compressing as much data as possible from 'source' buffer
192
- into already allocated buffer 'dest' of size 'targetDestSize'.
193
- This function either compresses the entire 'source' content into 'dest' if it's large enough,
194
- or fill 'dest' buffer completely with as much data as possible from 'source'.
195
- *sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.
196
- New value is necessarily <= old value.
197
- return : Nb bytes written into 'dest' (necessarily <= targetDestSize)
198
- or 0 if compression fails
195
+ Reverse the logic : compresses as much data as possible from 'src' buffer
196
+ into already allocated buffer 'dst' of size 'targetDestSize'.
197
+ This function either compresses the entire 'src' content into 'dst' if it's large enough,
198
+ or fill 'dst' buffer completely with as much data as possible from 'src'.
199
+ *srcSizePtr : will be modified to indicate how many bytes where read from 'src' to fill 'dst'.
200
+ New value is necessarily <= old value.
201
+ return : Nb bytes written into 'dst' (necessarily <= targetDestSize)
202
+ or 0 if compression fails
199
203
  */
200
- LZ4LIB_API int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize);
204
+ LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize);
201
205
 
202
206
 
203
207
  /*!
204
- LZ4_decompress_fast() :
205
- originalSize : is the original and therefore uncompressed size
208
+ LZ4_decompress_fast() : (unsafe!!)
209
+ originalSize : is the original uncompressed size
206
210
  return : the number of bytes read from the source buffer (in other words, the compressed size)
207
211
  If the source stream is detected malformed, the function will stop decoding and return a negative result.
208
- Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes.
209
- note : This function fully respect memory boundaries for properly formed compressed data.
212
+ Destination buffer must be already allocated. Its size must be >= 'originalSize' bytes.
213
+ note : This function respects memory boundaries for *properly formed* compressed data.
210
214
  It is a bit faster than LZ4_decompress_safe().
211
215
  However, it does not provide any protection against intentionally modified data stream (malicious input).
212
216
  Use this function in trusted environment only (data to decode comes from a trusted source).
213
217
  */
214
- LZ4LIB_API int LZ4_decompress_fast (const char* source, char* dest, int originalSize);
218
+ LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize);
215
219
 
216
220
  /*!
217
221
  LZ4_decompress_safe_partial() :
218
- This function decompress a compressed block of size 'compressedSize' at position 'source'
219
- into destination buffer 'dest' of size 'maxDecompressedSize'.
220
- The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached,
221
- reducing decompression time.
222
- return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize)
223
- Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.
222
+ This function decompress a compressed block of size 'srcSize' at position 'src'
223
+ into destination buffer 'dst' of size 'dstCapacity'.
224
+ The function will decompress a minimum of 'targetOutputSize' bytes, and stop after that.
225
+ However, it's not accurate, and may write more than 'targetOutputSize' (but <= dstCapacity).
226
+ @return : the number of bytes decoded in the destination buffer (necessarily <= dstCapacity)
227
+ Note : this number can be < 'targetOutputSize' should the compressed block contain less data.
224
228
  Always control how many bytes were decoded.
225
229
  If the source stream is detected malformed, the function will stop decoding and return a negative result.
226
- This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets
230
+ This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets.
227
231
  */
228
- LZ4LIB_API int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize);
232
+ LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity);
229
233
 
230
234
 
231
235
  /*-*********************************************
@@ -242,24 +246,29 @@ LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);
242
246
 
243
247
  /*! LZ4_resetStream() :
244
248
  * An LZ4_stream_t structure can be allocated once and re-used multiple times.
245
- * Use this function to init an allocated `LZ4_stream_t` structure and start a new compression.
249
+ * Use this function to start compressing a new stream.
246
250
  */
247
251
  LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);
248
252
 
249
253
  /*! LZ4_loadDict() :
250
- * Use this function to load a static dictionary into LZ4_stream.
254
+ * Use this function to load a static dictionary into LZ4_stream_t.
251
255
  * Any previous data will be forgotten, only 'dictionary' will remain in memory.
252
- * Loading a size of 0 is allowed.
253
- * Return : dictionary size, in bytes (necessarily <= 64 KB)
256
+ * Loading a size of 0 is allowed, and is the same as reset.
257
+ * @return : dictionary size, in bytes (necessarily <= 64 KB)
254
258
  */
255
259
  LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
256
260
 
257
261
  /*! LZ4_compress_fast_continue() :
258
- * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio.
259
- * Important : Previous data blocks are assumed to remain present and unmodified !
262
+ * Compress content into 'src' using data from previously compressed blocks, improving compression ratio.
260
263
  * 'dst' buffer must be already allocated.
261
264
  * If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
262
- * If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function @return==0.
265
+ *
266
+ * Important : Up to 64KB of previously compressed data is assumed to remain present and unmodified in memory !
267
+ * Special 1 : If input buffer is a double-buffer, it can have any size, including < 64 KB.
268
+ * Special 2 : If input buffer is a ring-buffer, it can have any size, including < 64 KB.
269
+ *
270
+ * @return : size of compressed block
271
+ * or 0 if there is an error (typically, compressed data cannot fit into 'dst')
263
272
  * After an error, the stream status is invalid, it can only be reset or freed.
264
273
  */
265
274
  LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
@@ -280,35 +289,40 @@ LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dict
280
289
  typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* incomplete type (defined later) */
281
290
 
282
291
  /*! LZ4_createStreamDecode() and LZ4_freeStreamDecode() :
283
- * creation / destruction of streaming decompression tracking structure */
292
+ * creation / destruction of streaming decompression tracking structure.
293
+ * A tracking structure can be re-used multiple times sequentially. */
284
294
  LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);
285
295
  LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
286
296
 
287
297
  /*! LZ4_setStreamDecode() :
288
- * Use this function to instruct where to find the dictionary.
289
- * Setting a size of 0 is allowed (same effect as reset).
290
- * @return : 1 if OK, 0 if error
298
+ * An LZ4_streamDecode_t structure can be allocated once and re-used multiple times.
299
+ * Use this function to start decompression of a new stream of blocks.
300
+ * A dictionary can optionnally be set. Use NULL or size 0 for a simple reset order.
301
+ * @return : 1 if OK, 0 if error
291
302
  */
292
303
  LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
293
304
 
294
305
  /*! LZ4_decompress_*_continue() :
295
- * These decoding functions allow decompression of multiple blocks in "streaming" mode.
296
- * Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)
297
- * In the case of a ring buffers, decoding buffer must be either :
306
+ * These decoding functions allow decompression of consecutive blocks in "streaming" mode.
307
+ * A block is an unsplittable entity, it must be presented entirely to a decompression function.
308
+ * Decompression functions only accept one block at a time.
309
+ * Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB).
310
+ *
311
+ * Special : if application sets a ring buffer for decompression, it must respect one of the following conditions :
298
312
  * - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
299
313
  * In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
300
314
  * - Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
301
- * maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.
315
+ * maxBlockSize is implementation dependent. It's the maximum size of any single block.
302
316
  * In which case, encoding and decoding buffers do not need to be synchronized,
303
317
  * and encoding ring buffer can have any size, including small ones ( < 64 KB).
304
318
  * - _At least_ 64 KB + 8 bytes + maxBlockSize.
305
319
  * In which case, encoding and decoding buffers do not need to be synchronized,
306
320
  * and encoding ring buffer can have any size, including larger than decoding buffer.
307
321
  * Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
308
- * and indicate where it is saved using LZ4_setStreamDecode()
322
+ * and indicate where it is saved using LZ4_setStreamDecode() before decompressing next block.
309
323
  */
310
- LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);
311
- LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize);
324
+ LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int srcSize, int dstCapacity);
325
+ LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize);
312
326
 
313
327
 
314
328
  /*! LZ4_decompress_*_usingDict() :
@@ -316,8 +330,8 @@ LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecod
316
330
  * a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue()
317
331
  * They are stand-alone, and don't need an LZ4_streamDecode_t structure.
318
332
  */
319
- LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
320
- LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize);
333
+ LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* src, char* dst, int srcSize, int dstCapcity, const char* dictStart, int dictSize);
334
+ LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize);
321
335
 
322
336
 
323
337
  /*^**********************************************
@@ -419,9 +433,11 @@ union LZ4_streamDecode_u {
419
433
  # define LZ4_DEPRECATED(message) /* disable deprecation warnings */
420
434
  #else
421
435
  # define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
422
- # if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
436
+ # if defined(__clang__) /* clang doesn't handle mixed C++11 and CNU attributes */
437
+ # define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
438
+ # elif defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
423
439
  # define LZ4_DEPRECATED(message) [[deprecated(message)]]
424
- # elif (LZ4_GCC_VERSION >= 405) || defined(__clang__)
440
+ # elif (LZ4_GCC_VERSION >= 405)
425
441
  # define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
426
442
  # elif (LZ4_GCC_VERSION >= 301)
427
443
  # define LZ4_DEPRECATED(message) __attribute__((deprecated))
@@ -322,7 +322,7 @@ size_t LZ4F_compressFrame_usingCDict(void* dstBuffer, size_t dstCapacity,
322
322
  const LZ4F_preferences_t* preferencesPtr)
323
323
  {
324
324
  LZ4F_cctx_t cctxI;
325
- LZ4_stream_t lz4ctx;
325
+ LZ4_stream_t lz4ctx; /* pretty large on stack */
326
326
  LZ4F_preferences_t prefs;
327
327
  LZ4F_compressOptions_t options;
328
328
  BYTE* const dstStart = (BYTE*) dstBuffer;
@@ -504,15 +504,15 @@ size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr,
504
504
  cctxPtr->prefs = *preferencesPtr;
505
505
 
506
506
  /* Ctx Management */
507
- { U32 const tableID = (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) ? 1 : 2; /* 0:nothing ; 1:LZ4 table ; 2:HC tables */
508
- if (cctxPtr->lz4CtxLevel < tableID) {
507
+ { U32 const ctxTypeID = (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) ? 1 : 2; /* 0:nothing ; 1:LZ4 table ; 2:HC tables */
508
+ if (cctxPtr->lz4CtxLevel < ctxTypeID) {
509
509
  FREEMEM(cctxPtr->lz4CtxPtr);
510
510
  if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN)
511
511
  cctxPtr->lz4CtxPtr = (void*)LZ4_createStream();
512
512
  else
513
513
  cctxPtr->lz4CtxPtr = (void*)LZ4_createStreamHC();
514
514
  if (cctxPtr->lz4CtxPtr == NULL) return err0r(LZ4F_ERROR_allocation_failed);
515
- cctxPtr->lz4CtxLevel = tableID;
515
+ cctxPtr->lz4CtxLevel = ctxTypeID;
516
516
  } }
517
517
 
518
518
  /* Buffer Management */
@@ -1253,29 +1253,32 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1253
1253
  memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);
1254
1254
  dctx->tmpInSize += sizeToCopy;
1255
1255
  srcPtr += sizeToCopy;
1256
- if (dctx->tmpInSize < dctx->tmpInTarget) {
1257
- nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize) + BHSize; /* rest of header + nextBlockHeader */
1258
- doAnotherStage = 0; /* not enough src data, ask for some more */
1259
- break;
1260
- }
1261
- { size_t const hSize = LZ4F_decodeHeader(dctx, dctx->header, dctx->tmpInTarget); /* will update dStage appropriately */
1262
- if (LZ4F_isError(hSize)) return hSize;
1263
- }
1256
+ }
1257
+ if (dctx->tmpInSize < dctx->tmpInTarget) {
1258
+ nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize) + BHSize; /* rest of header + nextBlockHeader */
1259
+ doAnotherStage = 0; /* not enough src data, ask for some more */
1264
1260
  break;
1265
1261
  }
1262
+ { size_t const hSize = LZ4F_decodeHeader(dctx, dctx->header, dctx->tmpInTarget); /* will update dStage appropriately */
1263
+ if (LZ4F_isError(hSize)) return hSize;
1264
+ }
1265
+ break;
1266
1266
 
1267
1267
  case dstage_init:
1268
1268
  if (dctx->frameInfo.contentChecksumFlag) XXH32_reset(&(dctx->xxh), 0);
1269
1269
  /* internal buffers allocation */
1270
- { size_t const bufferNeeded = dctx->maxBlockSize + ((dctx->frameInfo.blockMode==LZ4F_blockLinked) * 128 KB) + 4 /* block checksum */;
1270
+ { size_t const bufferNeeded = dctx->maxBlockSize
1271
+ + ((dctx->frameInfo.blockMode==LZ4F_blockLinked) * 128 KB);
1271
1272
  if (bufferNeeded > dctx->maxBufferSize) { /* tmp buffers too small */
1272
1273
  dctx->maxBufferSize = 0; /* ensure allocation will be re-attempted on next entry*/
1273
1274
  FREEMEM(dctx->tmpIn);
1274
- dctx->tmpIn = (BYTE*)ALLOCATOR(dctx->maxBlockSize);
1275
- if (dctx->tmpIn == NULL) return err0r(LZ4F_ERROR_allocation_failed);
1275
+ dctx->tmpIn = (BYTE*)ALLOCATOR(dctx->maxBlockSize + 4 /* block checksum */);
1276
+ if (dctx->tmpIn == NULL)
1277
+ return err0r(LZ4F_ERROR_allocation_failed);
1276
1278
  FREEMEM(dctx->tmpOutBuffer);
1277
1279
  dctx->tmpOutBuffer= (BYTE*)ALLOCATOR(bufferNeeded);
1278
- if (dctx->tmpOutBuffer== NULL) return err0r(LZ4F_ERROR_allocation_failed);
1280
+ if (dctx->tmpOutBuffer== NULL)
1281
+ return err0r(LZ4F_ERROR_allocation_failed);
1279
1282
  dctx->maxBufferSize = bufferNeeded;
1280
1283
  } }
1281
1284
  dctx->tmpInSize = 0;
@@ -1299,18 +1302,20 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1299
1302
 
1300
1303
  if (dctx->dStage == dstage_storeBlockHeader) /* can be skipped */
1301
1304
  case dstage_storeBlockHeader:
1302
- { size_t sizeToCopy = BHSize - dctx->tmpInSize;
1303
- if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
1305
+ { size_t const remainingInput = (size_t)(srcEnd - srcPtr);
1306
+ size_t const wantedData = BHSize - dctx->tmpInSize;
1307
+ size_t const sizeToCopy = MIN(wantedData, remainingInput);
1304
1308
  memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);
1305
1309
  srcPtr += sizeToCopy;
1306
1310
  dctx->tmpInSize += sizeToCopy;
1311
+
1307
1312
  if (dctx->tmpInSize < BHSize) { /* not enough input for cBlockSize */
1308
1313
  nextSrcSizeHint = BHSize - dctx->tmpInSize;
1309
1314
  doAnotherStage = 0;
1310
1315
  break;
1311
1316
  }
1312
1317
  selectedIn = dctx->tmpIn;
1313
- }
1318
+ } /* if (dctx->dStage == dstage_storeBlockHeader) */
1314
1319
 
1315
1320
  /* decode block header */
1316
1321
  { size_t const nextCBlockSize = LZ4F_readLE32(selectedIn) & 0x7FFFFFFFU;
@@ -1401,7 +1406,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1401
1406
  dctx->dStage = dstage_getBlockHeader; /* new block */
1402
1407
  break;
1403
1408
 
1404
- case dstage_getCBlock: /* entry from dstage_decodeCBlockSize */
1409
+ case dstage_getCBlock:
1405
1410
  if ((size_t)(srcEnd-srcPtr) < dctx->tmpInTarget) {
1406
1411
  dctx->tmpInSize = 0;
1407
1412
  dctx->dStage = dstage_storeCBlock;
@@ -1414,7 +1419,9 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1414
1419
  break;
1415
1420
 
1416
1421
  case dstage_storeCBlock:
1417
- { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize, (size_t)(srcEnd-srcPtr));
1422
+ { size_t const wantedData = dctx->tmpInTarget - dctx->tmpInSize;
1423
+ size_t const inputLeft = (size_t)(srcEnd-srcPtr);
1424
+ size_t const sizeToCopy = MIN(wantedData, inputLeft);
1418
1425
  memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);
1419
1426
  dctx->tmpInSize += sizeToCopy;
1420
1427
  srcPtr += sizeToCopy;
@@ -1465,7 +1472,6 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1465
1472
 
1466
1473
  case dstage_decodeCBlock_intoTmp:
1467
1474
  /* not enough place into dst : decode into tmpOut */
1468
-
1469
1475
  /* ensure enough place for tmpOut */
1470
1476
  if (dctx->frameInfo.blockMode == LZ4F_blockLinked) {
1471
1477
  if (dctx->dict == dctx->tmpOutBuffer) {
@@ -1518,29 +1524,27 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1518
1524
  }
1519
1525
 
1520
1526
  case dstage_getSuffix:
1521
- { size_t const suffixSize = dctx->frameInfo.contentChecksumFlag * 4;
1522
- if (dctx->frameRemainingSize)
1523
- return err0r(LZ4F_ERROR_frameSize_wrong); /* incorrect frame size decoded */
1524
- if (suffixSize == 0) { /* frame completed */
1525
- nextSrcSizeHint = 0;
1526
- LZ4F_resetDecompressionContext(dctx);
1527
- doAnotherStage = 0;
1528
- break;
1529
- }
1530
- if ((srcEnd - srcPtr) < 4) { /* not enough size for entire CRC */
1531
- dctx->tmpInSize = 0;
1532
- dctx->dStage = dstage_storeSuffix;
1533
- } else {
1534
- selectedIn = srcPtr;
1535
- srcPtr += 4;
1536
- }
1527
+ if (dctx->frameRemainingSize)
1528
+ return err0r(LZ4F_ERROR_frameSize_wrong); /* incorrect frame size decoded */
1529
+ if (!dctx->frameInfo.contentChecksumFlag) { /* no checksum, frame is completed */
1530
+ nextSrcSizeHint = 0;
1531
+ LZ4F_resetDecompressionContext(dctx);
1532
+ doAnotherStage = 0;
1533
+ break;
1534
+ }
1535
+ if ((srcEnd - srcPtr) < 4) { /* not enough size for entire CRC */
1536
+ dctx->tmpInSize = 0;
1537
+ dctx->dStage = dstage_storeSuffix;
1538
+ } else {
1539
+ selectedIn = srcPtr;
1540
+ srcPtr += 4;
1537
1541
  }
1538
1542
 
1539
1543
  if (dctx->dStage == dstage_storeSuffix) /* can be skipped */
1540
1544
  case dstage_storeSuffix:
1541
- {
1542
- size_t sizeToCopy = 4 - dctx->tmpInSize;
1543
- if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
1545
+ { size_t const remainingInput = (size_t)(srcEnd - srcPtr);
1546
+ size_t const wantedData = 4 - dctx->tmpInSize;
1547
+ size_t const sizeToCopy = MIN(wantedData, remainingInput);
1544
1548
  memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);
1545
1549
  srcPtr += sizeToCopy;
1546
1550
  dctx->tmpInSize += sizeToCopy;
@@ -1550,7 +1554,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1550
1554
  break;
1551
1555
  }
1552
1556
  selectedIn = dctx->tmpIn;
1553
- }
1557
+ } /* if (dctx->dStage == dstage_storeSuffix) */
1554
1558
 
1555
1559
  /* case dstage_checkSuffix: */ /* no direct call, avoid scan-build warning */
1556
1560
  { U32 const readCRC = LZ4F_readLE32(selectedIn);
@@ -1589,7 +1593,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1589
1593
  break;
1590
1594
  }
1591
1595
  selectedIn = dctx->header + 4;
1592
- }
1596
+ } /* if (dctx->dStage == dstage_storeSFrameSize) */
1593
1597
 
1594
1598
  /* case dstage_decodeSFrameSize: */ /* no direct access */
1595
1599
  { size_t const SFrameSize = LZ4F_readLE32(selectedIn);
@@ -1606,36 +1610,38 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1606
1610
  doAnotherStage = 0;
1607
1611
  nextSrcSizeHint = dctx->tmpInTarget;
1608
1612
  if (nextSrcSizeHint) break; /* still more to skip */
1613
+ /* frame fully skipped : prepare context for a new frame */
1609
1614
  LZ4F_resetDecompressionContext(dctx);
1610
1615
  break;
1611
1616
  }
1612
1617
  }
1613
- }
1614
-
1615
- /* preserve history within tmp if necessary */
1616
- if ( (dctx->frameInfo.blockMode==LZ4F_blockLinked)
1617
- && (dctx->dict != dctx->tmpOutBuffer)
1618
- && (dctx->dStage != dstage_getFrameHeader)
1619
- && (!decompressOptionsPtr->stableDst)
1620
- && ((unsigned)(dctx->dStage-1) < (unsigned)(dstage_getSuffix-1)) )
1618
+ } /* while (doAnotherStage) */
1619
+
1620
+ /* preserve history within tmp whenever necessary */
1621
+ LZ4F_STATIC_ASSERT((unsigned)dstage_init == 2);
1622
+ if ( (dctx->frameInfo.blockMode==LZ4F_blockLinked) /* next block will use up to 64KB from previous ones */
1623
+ && (dctx->dict != dctx->tmpOutBuffer) /* dictionary is not already within tmp */
1624
+ && (!decompressOptionsPtr->stableDst) /* cannot rely on dst data to remain there for next call */
1625
+ && ((unsigned)(dctx->dStage)-2 < (unsigned)(dstage_getSuffix)-2) ) /* valid stages : [init ... getSuffix[ */
1621
1626
  {
1622
1627
  if (dctx->dStage == dstage_flushOut) {
1623
- size_t preserveSize = dctx->tmpOut - dctx->tmpOutBuffer;
1628
+ size_t const preserveSize = dctx->tmpOut - dctx->tmpOutBuffer;
1624
1629
  size_t copySize = 64 KB - dctx->tmpOutSize;
1625
1630
  const BYTE* oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart;
1626
1631
  if (dctx->tmpOutSize > 64 KB) copySize = 0;
1627
1632
  if (copySize > preserveSize) copySize = preserveSize;
1628
1633
 
1629
- memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
1634
+ if (copySize > 0)
1635
+ memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
1630
1636
 
1631
1637
  dctx->dict = dctx->tmpOutBuffer;
1632
1638
  dctx->dictSize = preserveSize + dctx->tmpOutStart;
1633
1639
  } else {
1634
- size_t newDictSize = dctx->dictSize;
1635
- const BYTE* oldDictEnd = dctx->dict + dctx->dictSize;
1636
- if ((newDictSize) > 64 KB) newDictSize = 64 KB;
1640
+ const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize;
1641
+ size_t const newDictSize = MIN(dctx->dictSize, 64 KB);
1637
1642
 
1638
- memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);
1643
+ if (newDictSize > 0)
1644
+ memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);
1639
1645
 
1640
1646
  dctx->dict = dctx->tmpOutBuffer;
1641
1647
  dctx->dictSize = newDictSize;