extlz4 0.2.4.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/HISTORY.ja.md +5 -0
- data/README.md +3 -3
- data/contrib/lz4/INSTALL +1 -0
- data/contrib/lz4/NEWS +13 -0
- data/contrib/lz4/README.md +1 -0
- data/contrib/lz4/circle.yml +0 -1
- data/contrib/lz4/lib/README.md +28 -28
- data/contrib/lz4/lib/lz4.c +139 -53
- data/contrib/lz4/lib/lz4.h +85 -69
- data/contrib/lz4/lib/lz4frame.c +63 -57
- data/contrib/lz4/lib/lz4frame_static.h +27 -16
- data/contrib/lz4/lib/lz4hc.c +208 -122
- data/contrib/lz4/lib/lz4hc.h +23 -29
- data/contrib/lz4/lib/lz4opt.h +247 -257
- data/contrib/lz4/lib/xxhash.c +16 -16
- data/lib/extlz4/version.rb +1 -1
- metadata +1 -1
data/contrib/lz4/lib/lz4.h
CHANGED
@@ -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
|
-
*
|
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 '
|
124
|
-
into already allocated '
|
125
|
-
Compression is guaranteed to succeed if '
|
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 '
|
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, '
|
130
|
-
This function never writes outside '
|
131
|
-
|
132
|
-
|
133
|
-
return
|
134
|
-
|
135
|
-
LZ4LIB_API int LZ4_compress_default(const char*
|
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
|
139
|
-
|
140
|
-
return : the number of bytes decompressed into destination buffer (necessarily <=
|
141
|
-
If destination buffer is not large enough, decoding will stop and output an error code (
|
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*
|
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*
|
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*
|
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
|
192
|
-
into already allocated buffer '
|
193
|
-
This function either compresses the entire '
|
194
|
-
or fill '
|
195
|
-
*
|
196
|
-
|
197
|
-
return : Nb bytes written into '
|
198
|
-
|
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*
|
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
|
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
|
209
|
-
note : This function
|
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*
|
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 '
|
219
|
-
into destination buffer '
|
220
|
-
The function
|
221
|
-
|
222
|
-
|
223
|
-
Note : this number can be < 'targetOutputSize' should the compressed block
|
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*
|
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
|
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
|
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
|
-
*
|
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
|
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
|
-
*
|
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
|
-
*
|
289
|
-
*
|
290
|
-
*
|
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
|
296
|
-
*
|
297
|
-
*
|
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
|
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*
|
311
|
-
LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char*
|
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*
|
320
|
-
LZ4LIB_API int LZ4_decompress_fast_usingDict (const char*
|
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
|
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)
|
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))
|
data/contrib/lz4/lib/lz4frame.c
CHANGED
@@ -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
|
508
|
-
if (cctxPtr->lz4CtxLevel <
|
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 =
|
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
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
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
|
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)
|
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)
|
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
|
1303
|
-
|
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:
|
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
|
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
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
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
|
1543
|
-
|
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
|
1616
|
-
|
1617
|
-
|
1618
|
-
&& (dctx->
|
1619
|
-
&& (!decompressOptionsPtr->stableDst)
|
1620
|
-
&& ((unsigned)(dctx->dStage-
|
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
|
-
|
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
|
-
|
1635
|
-
const
|
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
|
-
|
1643
|
+
if (newDictSize > 0)
|
1644
|
+
memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);
|
1639
1645
|
|
1640
1646
|
dctx->dict = dctx->tmpOutBuffer;
|
1641
1647
|
dctx->dictSize = newDictSize;
|