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.
- 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;
|