extlz4 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -4
  3. data/bin/extlz4 +1 -1
  4. data/contrib/lz4/NEWS +36 -0
  5. data/contrib/lz4/README.md +11 -12
  6. data/contrib/lz4/build/README.md +55 -0
  7. data/contrib/lz4/build/VS2010/datagen/datagen.vcxproj +169 -0
  8. data/contrib/lz4/build/VS2010/frametest/frametest.vcxproj +176 -0
  9. data/contrib/lz4/build/VS2010/fullbench-dll/fullbench-dll.vcxproj +180 -0
  10. data/contrib/lz4/build/VS2010/fullbench/fullbench.vcxproj +176 -0
  11. data/contrib/lz4/build/VS2010/fuzzer/fuzzer.vcxproj +173 -0
  12. data/contrib/lz4/build/VS2010/liblz4-dll/liblz4-dll.rc +51 -0
  13. data/contrib/lz4/build/VS2010/liblz4-dll/liblz4-dll.vcxproj +179 -0
  14. data/contrib/lz4/build/VS2010/liblz4/liblz4.vcxproj +175 -0
  15. data/contrib/lz4/build/VS2010/lz4.sln +98 -0
  16. data/contrib/lz4/build/VS2010/lz4/lz4.rc +51 -0
  17. data/contrib/lz4/build/VS2010/lz4/lz4.vcxproj +189 -0
  18. data/contrib/lz4/build/VS2017/datagen/datagen.vcxproj +173 -0
  19. data/contrib/lz4/build/VS2017/frametest/frametest.vcxproj +180 -0
  20. data/contrib/lz4/build/VS2017/fullbench-dll/fullbench-dll.vcxproj +184 -0
  21. data/contrib/lz4/build/VS2017/fullbench/fullbench.vcxproj +180 -0
  22. data/contrib/lz4/build/VS2017/fuzzer/fuzzer.vcxproj +177 -0
  23. data/contrib/lz4/build/VS2017/liblz4-dll/liblz4-dll.rc +51 -0
  24. data/contrib/lz4/build/VS2017/liblz4-dll/liblz4-dll.vcxproj +183 -0
  25. data/contrib/lz4/build/VS2017/liblz4/liblz4.vcxproj +179 -0
  26. data/contrib/lz4/build/VS2017/lz4.sln +103 -0
  27. data/contrib/lz4/build/VS2017/lz4/lz4.rc +51 -0
  28. data/contrib/lz4/build/VS2017/lz4/lz4.vcxproj +164 -0
  29. data/contrib/lz4/build/cmake/CMakeLists.txt +235 -0
  30. data/contrib/lz4/lib/README.md +27 -10
  31. data/contrib/lz4/lib/lz4.c +327 -230
  32. data/contrib/lz4/lib/lz4.h +80 -70
  33. data/contrib/lz4/lib/lz4frame.c +93 -54
  34. data/contrib/lz4/lib/lz4frame.h +22 -14
  35. data/contrib/lz4/lib/lz4hc.c +192 -115
  36. data/contrib/lz4/lib/lz4hc.h +15 -40
  37. data/contrib/lz4/ossfuzz/Makefile +12 -8
  38. data/contrib/lz4/ossfuzz/compress_frame_fuzzer.c +11 -5
  39. data/contrib/lz4/ossfuzz/compress_fuzzer.c +9 -2
  40. data/contrib/lz4/ossfuzz/compress_hc_fuzzer.c +10 -3
  41. data/contrib/lz4/ossfuzz/decompress_frame_fuzzer.c +11 -3
  42. data/contrib/lz4/ossfuzz/decompress_fuzzer.c +6 -2
  43. data/contrib/lz4/ossfuzz/fuzz_data_producer.c +77 -0
  44. data/contrib/lz4/ossfuzz/fuzz_data_producer.h +36 -0
  45. data/contrib/lz4/ossfuzz/round_trip_frame_fuzzer.c +8 -4
  46. data/contrib/lz4/ossfuzz/round_trip_fuzzer.c +9 -2
  47. data/contrib/lz4/ossfuzz/round_trip_hc_fuzzer.c +7 -2
  48. data/contrib/lz4/ossfuzz/travisoss.sh +6 -1
  49. data/contrib/lz4/tmp +0 -0
  50. data/contrib/lz4/tmpsparse +0 -0
  51. data/ext/extlz4.c +2 -0
  52. data/ext/extlz4.h +5 -0
  53. data/ext/hashargs.c +1 -1
  54. data/ext/hashargs.h +1 -1
  55. data/gemstub.rb +3 -14
  56. data/lib/extlz4.rb +0 -2
  57. data/lib/extlz4/oldstream.rb +1 -1
  58. metadata +40 -25
  59. data/lib/extlz4/version.rb +0 -3
@@ -100,7 +100,7 @@ extern "C" {
100
100
  /*------ Version ------*/
101
101
  #define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
102
102
  #define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */
103
- #define LZ4_VERSION_RELEASE 2 /* for tweaks, bug-fixes, or development */
103
+ #define LZ4_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */
104
104
 
105
105
  #define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
106
106
 
@@ -186,7 +186,8 @@ LZ4LIB_API int LZ4_compressBound(int inputSize);
186
186
  The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
187
187
  It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
188
188
  An acceleration value of "1" is the same as regular LZ4_compress_default()
189
- Values <= 0 will be replaced by ACCELERATION_DEFAULT (currently == 1, see lz4.c).
189
+ Values <= 0 will be replaced by LZ4_ACCELERATION_DEFAULT (currently == 1, see lz4.c).
190
+ Values > LZ4_ACCELERATION_MAX will be replaced by LZ4_ACCELERATION_MAX (currently == 65537, see lz4.c).
190
191
  */
191
192
  LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
192
193
 
@@ -212,7 +213,18 @@ LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* d
212
213
  * New value is necessarily <= input value.
213
214
  * @return : Nb bytes written into 'dst' (necessarily <= targetDestSize)
214
215
  * or 0 if compression fails.
215
- */
216
+ *
217
+ * Note : from v1.8.2 to v1.9.1, this function had a bug (fixed un v1.9.2+):
218
+ * the produced compressed content could, in specific circumstances,
219
+ * require to be decompressed into a destination buffer larger
220
+ * by at least 1 byte than the content to decompress.
221
+ * If an application uses `LZ4_compress_destSize()`,
222
+ * it's highly recommended to update liblz4 to v1.9.2 or better.
223
+ * If this can't be done or ensured,
224
+ * the receiving decompression function should provide
225
+ * a dstCapacity which is > decompressedSize, by at least 1 byte.
226
+ * See https://github.com/lz4/lz4/issues/859 for details
227
+ */
216
228
  LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize);
217
229
 
218
230
 
@@ -220,25 +232,35 @@ LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePt
220
232
  * Decompress an LZ4 compressed block, of size 'srcSize' at position 'src',
221
233
  * into destination buffer 'dst' of size 'dstCapacity'.
222
234
  * Up to 'targetOutputSize' bytes will be decoded.
223
- * The function stops decoding on reaching this objective,
224
- * which can boost performance when only the beginning of a block is required.
235
+ * The function stops decoding on reaching this objective.
236
+ * This can be useful to boost performance
237
+ * whenever only the beginning of a block is required.
225
238
  *
226
- * @return : the number of bytes decoded in `dst` (necessarily <= dstCapacity)
239
+ * @return : the number of bytes decoded in `dst` (necessarily <= targetOutputSize)
227
240
  * If source stream is detected malformed, function returns a negative result.
228
241
  *
229
- * Note : @return can be < targetOutputSize, if compressed block contains less data.
242
+ * Note 1 : @return can be < targetOutputSize, if compressed block contains less data.
243
+ *
244
+ * Note 2 : targetOutputSize must be <= dstCapacity
230
245
  *
231
- * Note 2 : this function features 2 parameters, targetOutputSize and dstCapacity,
232
- * and expects targetOutputSize <= dstCapacity.
233
- * It effectively stops decoding on reaching targetOutputSize,
246
+ * Note 3 : this function effectively stops decoding on reaching targetOutputSize,
234
247
  * so dstCapacity is kind of redundant.
235
- * This is because in a previous version of this function,
236
- * decoding operation would not "break" a sequence in the middle.
237
- * As a consequence, there was no guarantee that decoding would stop at exactly targetOutputSize,
248
+ * This is because in older versions of this function,
249
+ * decoding operation would still write complete sequences.
250
+ * Therefore, there was no guarantee that it would stop writing at exactly targetOutputSize,
238
251
  * it could write more bytes, though only up to dstCapacity.
239
252
  * Some "margin" used to be required for this operation to work properly.
240
- * This is no longer necessary.
241
- * The function nonetheless keeps its signature, in an effort to not break API.
253
+ * Thankfully, this is no longer necessary.
254
+ * The function nonetheless keeps the same signature, in an effort to preserve API compatibility.
255
+ *
256
+ * Note 4 : If srcSize is the exact size of the block,
257
+ * then targetOutputSize can be any value,
258
+ * including larger than the block's decompressed size.
259
+ * The function will, at most, generate block's decompressed size.
260
+ *
261
+ * Note 5 : If srcSize is _larger_ than block's compressed size,
262
+ * then targetOutputSize **MUST** be <= block's decompressed size.
263
+ * Otherwise, *silent corruption will occur*.
242
264
  */
243
265
  LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity);
244
266
 
@@ -547,74 +569,64 @@ LZ4LIB_STATIC_API void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const
547
569
  #define LZ4_H_98237428734687
548
570
 
549
571
  /*-************************************************************
550
- * PRIVATE DEFINITIONS
572
+ * Private Definitions
551
573
  **************************************************************
552
574
  * Do not use these definitions directly.
553
575
  * They are only exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`.
554
- * Accessing members will expose code to API and/or ABI break in future versions of the library.
576
+ * Accessing members will expose user code to API and/or ABI break in future versions of the library.
555
577
  **************************************************************/
556
578
  #define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)
557
579
  #define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
558
580
  #define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
559
581
 
560
582
  #if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
561
- #include <stdint.h>
562
-
563
- typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
564
- struct LZ4_stream_t_internal {
565
- uint32_t hashTable[LZ4_HASH_SIZE_U32];
566
- uint32_t currentOffset;
567
- uint16_t dirty;
568
- uint16_t tableType;
569
- const uint8_t* dictionary;
570
- const LZ4_stream_t_internal* dictCtx;
571
- uint32_t dictSize;
572
- };
573
-
574
- typedef struct {
575
- const uint8_t* externalDict;
576
- size_t extDictSize;
577
- const uint8_t* prefixEnd;
578
- size_t prefixSize;
579
- } LZ4_streamDecode_t_internal;
580
-
583
+ # include <stdint.h>
584
+ typedef int8_t LZ4_i8;
585
+ typedef uint8_t LZ4_byte;
586
+ typedef uint16_t LZ4_u16;
587
+ typedef uint32_t LZ4_u32;
581
588
  #else
589
+ typedef signed char LZ4_i8;
590
+ typedef unsigned char LZ4_byte;
591
+ typedef unsigned short LZ4_u16;
592
+ typedef unsigned int LZ4_u32;
593
+ #endif
582
594
 
583
595
  typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
584
596
  struct LZ4_stream_t_internal {
585
- unsigned int hashTable[LZ4_HASH_SIZE_U32];
586
- unsigned int currentOffset;
587
- unsigned short dirty;
588
- unsigned short tableType;
589
- const unsigned char* dictionary;
597
+ LZ4_u32 hashTable[LZ4_HASH_SIZE_U32];
598
+ LZ4_u32 currentOffset;
599
+ LZ4_u32 tableType;
600
+ const LZ4_byte* dictionary;
590
601
  const LZ4_stream_t_internal* dictCtx;
591
- unsigned int dictSize;
602
+ LZ4_u32 dictSize;
592
603
  };
593
604
 
594
605
  typedef struct {
595
- const unsigned char* externalDict;
596
- const unsigned char* prefixEnd;
606
+ const LZ4_byte* externalDict;
597
607
  size_t extDictSize;
608
+ const LZ4_byte* prefixEnd;
598
609
  size_t prefixSize;
599
610
  } LZ4_streamDecode_t_internal;
600
611
 
601
- #endif
602
612
 
603
613
  /*! LZ4_stream_t :
604
- * information structure to track an LZ4 stream.
614
+ * Do not use below internal definitions directly !
615
+ * Declare or allocate an LZ4_stream_t instead.
605
616
  * LZ4_stream_t can also be created using LZ4_createStream(), which is recommended.
606
617
  * The structure definition can be convenient for static allocation
607
618
  * (on stack, or as part of larger structure).
608
619
  * Init this structure with LZ4_initStream() before first use.
609
620
  * note : only use this definition in association with static linking !
610
- * this definition is not API/ABI safe, and may change in a future version.
621
+ * this definition is not API/ABI safe, and may change in future versions.
611
622
  */
612
- #define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4 + ((sizeof(void*)==16) ? 4 : 0) /*AS-400*/ )
613
- #define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(unsigned long long))
623
+ #define LZ4_STREAMSIZE 16416 /* static size, for inter-version compatibility */
624
+ #define LZ4_STREAMSIZE_VOIDP (LZ4_STREAMSIZE / sizeof(void*))
614
625
  union LZ4_stream_u {
615
- unsigned long long table[LZ4_STREAMSIZE_U64];
626
+ void* table[LZ4_STREAMSIZE_VOIDP];
616
627
  LZ4_stream_t_internal internal_donotuse;
617
- } ; /* previously typedef'd to LZ4_stream_t */
628
+ }; /* previously typedef'd to LZ4_stream_t */
629
+
618
630
 
619
631
  /*! LZ4_initStream() : v1.9.0+
620
632
  * An LZ4_stream_t structure must be initialized at least once.
@@ -667,22 +679,21 @@ union LZ4_streamDecode_u {
667
679
  #ifdef LZ4_DISABLE_DEPRECATE_WARNINGS
668
680
  # define LZ4_DEPRECATED(message) /* disable deprecation warnings */
669
681
  #else
670
- # define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
671
682
  # if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
672
683
  # define LZ4_DEPRECATED(message) [[deprecated(message)]]
673
- # elif (LZ4_GCC_VERSION >= 405) || defined(__clang__)
674
- # define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
675
- # elif (LZ4_GCC_VERSION >= 301)
676
- # define LZ4_DEPRECATED(message) __attribute__((deprecated))
677
684
  # elif defined(_MSC_VER)
678
685
  # define LZ4_DEPRECATED(message) __declspec(deprecated(message))
686
+ # elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 45))
687
+ # define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
688
+ # elif defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 31)
689
+ # define LZ4_DEPRECATED(message) __attribute__((deprecated))
679
690
  # else
680
- # pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")
681
- # define LZ4_DEPRECATED(message)
691
+ # pragma message("WARNING: LZ4_DEPRECATED needs custom implementation for this compiler")
692
+ # define LZ4_DEPRECATED(message) /* disabled */
682
693
  # endif
683
694
  #endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */
684
695
 
685
- /* Obsolete compression functions */
696
+ /*! Obsolete compression functions (since v1.7.3) */
686
697
  LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* src, char* dest, int srcSize);
687
698
  LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* src, char* dest, int srcSize, int maxOutputSize);
688
699
  LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
@@ -690,11 +701,12 @@ LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_co
690
701
  LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
691
702
  LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
692
703
 
693
- /* Obsolete decompression functions */
704
+ /*! Obsolete decompression functions (since v1.8.0) */
694
705
  LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize);
695
706
  LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);
696
707
 
697
- /* Obsolete streaming functions; degraded functionality; do not use!
708
+ /* Obsolete streaming functions (since v1.7.0)
709
+ * degraded functionality; do not use!
698
710
  *
699
711
  * In order to perform streaming compression, these functions depended on data
700
712
  * that is no longer tracked in the state. They have been preserved as well as
@@ -708,23 +720,22 @@ LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API int LZ4_sizeofStre
708
720
  LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer);
709
721
  LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state);
710
722
 
711
- /* Obsolete streaming decoding functions */
723
+ /*! Obsolete streaming decoding functions (since v1.7.0) */
712
724
  LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
713
725
  LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
714
726
 
715
- /*! LZ4_decompress_fast() : **unsafe!**
727
+ /*! Obsolete LZ4_decompress_fast variants (since v1.9.0) :
716
728
  * These functions used to be faster than LZ4_decompress_safe(),
717
- * but it has changed, and they are now slower than LZ4_decompress_safe().
729
+ * but this is no longer the case. They are now slower.
718
730
  * This is because LZ4_decompress_fast() doesn't know the input size,
719
- * and therefore must progress more cautiously in the input buffer to not read beyond the end of block.
731
+ * and therefore must progress more cautiously into the input buffer to not read beyond the end of block.
720
732
  * On top of that `LZ4_decompress_fast()` is not protected vs malformed or malicious inputs, making it a security liability.
721
733
  * As a consequence, LZ4_decompress_fast() is strongly discouraged, and deprecated.
722
734
  *
723
735
  * The last remaining LZ4_decompress_fast() specificity is that
724
736
  * it can decompress a block without knowing its compressed size.
725
- * Such functionality could be achieved in a more secure manner,
726
- * by also providing the maximum size of input buffer,
727
- * but it would require new prototypes, and adaptation of the implementation to this new use case.
737
+ * Such functionality can be achieved in a more secure manner
738
+ * by employing LZ4_decompress_safe_partial().
728
739
  *
729
740
  * Parameters:
730
741
  * originalSize : is the uncompressed size to regenerate.
@@ -739,7 +750,6 @@ LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4
739
750
  * But they may happen if input data is invalid (error or intentional tampering).
740
751
  * As a consequence, use these functions in trusted environments with trusted data **only**.
741
752
  */
742
-
743
753
  LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe() instead")
744
754
  LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize);
745
755
  LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_continue() instead")
@@ -71,8 +71,8 @@
71
71
  * towards another library or solution of their choice
72
72
  * by modifying below section.
73
73
  */
74
- #include <stdlib.h> /* malloc, calloc, free */
75
74
  #ifndef LZ4_SRC_INCLUDED /* avoid redefinition when sources are coalesced */
75
+ # include <stdlib.h> /* malloc, calloc, free */
76
76
  # define ALLOC(s) malloc(s)
77
77
  # define ALLOC_AND_ZERO(s) calloc(1,(s))
78
78
  # define FREEMEM(p) free(p)
@@ -533,7 +533,7 @@ void LZ4F_freeCDict(LZ4F_CDict* cdict)
533
533
  * If the result LZ4F_errorCode_t is not OK_NoError, there was an error during context creation.
534
534
  * Object can release its memory using LZ4F_freeCompressionContext();
535
535
  */
536
- LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* LZ4F_compressionContextPtr, unsigned version)
536
+ LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_cctx** LZ4F_compressionContextPtr, unsigned version)
537
537
  {
538
538
  LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)ALLOC_AND_ZERO(sizeof(LZ4F_cctx_t));
539
539
  if (cctxPtr==NULL) return err0r(LZ4F_ERROR_allocation_failed);
@@ -541,20 +541,18 @@ LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* LZ4F_c
541
541
  cctxPtr->version = version;
542
542
  cctxPtr->cStage = 0; /* Next stage : init stream */
543
543
 
544
- *LZ4F_compressionContextPtr = (LZ4F_compressionContext_t)cctxPtr;
544
+ *LZ4F_compressionContextPtr = cctxPtr;
545
545
 
546
546
  return LZ4F_OK_NoError;
547
547
  }
548
548
 
549
549
 
550
- LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_compressionContext)
550
+ LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_cctx* cctxPtr)
551
551
  {
552
- LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)LZ4F_compressionContext;
553
-
554
552
  if (cctxPtr != NULL) { /* support free on NULL */
555
- FREEMEM(cctxPtr->lz4CtxPtr); /* works because LZ4_streamHC_t and LZ4_stream_t are simple POD types */
553
+ FREEMEM(cctxPtr->lz4CtxPtr); /* note: LZ4_streamHC_t and LZ4_stream_t are simple POD types */
556
554
  FREEMEM(cctxPtr->tmpBuff);
557
- FREEMEM(LZ4F_compressionContext);
555
+ FREEMEM(cctxPtr);
558
556
  }
559
557
 
560
558
  return LZ4F_OK_NoError;
@@ -725,6 +723,9 @@ size_t LZ4F_compressBegin(LZ4F_cctx* cctxPtr,
725
723
  */
726
724
  size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr)
727
725
  {
726
+ if (preferencesPtr && preferencesPtr->autoFlush) {
727
+ return LZ4F_compressBound_internal(srcSize, preferencesPtr, 0);
728
+ }
728
729
  return LZ4F_compressBound_internal(srcSize, preferencesPtr, (size_t)-1);
729
730
  }
730
731
 
@@ -747,6 +748,7 @@ static size_t LZ4F_makeBlock(void* dst,
747
748
  (int)(srcSize), (int)(srcSize-1),
748
749
  level, cdict);
749
750
  if (cSize == 0) { /* compression failed */
751
+ DEBUGLOG(5, "LZ4F_makeBlock: compression failed, creating a raw block (size %u)", (U32)srcSize);
750
752
  cSize = (U32)srcSize;
751
753
  LZ4F_writeLE32(cSizePtr, cSize | LZ4F_BLOCKUNCOMPRESSED_FLAG);
752
754
  memcpy(cSizePtr+BHSize, src, srcSize);
@@ -989,6 +991,7 @@ size_t LZ4F_compressEnd(LZ4F_cctx* cctxPtr,
989
991
  BYTE* dstPtr = dstStart;
990
992
 
991
993
  size_t const flushSize = LZ4F_flush(cctxPtr, dstBuffer, dstCapacity, compressOptionsPtr);
994
+ DEBUGLOG(5,"LZ4F_compressEnd: dstCapacity=%u", (unsigned)dstCapacity);
992
995
  if (LZ4F_isError(flushSize)) return flushSize;
993
996
  dstPtr += flushSize;
994
997
 
@@ -1002,6 +1005,7 @@ size_t LZ4F_compressEnd(LZ4F_cctx* cctxPtr,
1002
1005
  if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled) {
1003
1006
  U32 const xxh = XXH32_digest(&(cctxPtr->xxh));
1004
1007
  if (dstCapacity < 8) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
1008
+ DEBUGLOG(5,"Writing 32-bit content checksum");
1005
1009
  LZ4F_writeLE32(dstPtr, xxh);
1006
1010
  dstPtr+=4; /* content Checksum */
1007
1011
  }
@@ -1112,6 +1116,7 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx* dctx, const void* src, size_t srcSize
1112
1116
  size_t frameHeaderSize;
1113
1117
  const BYTE* srcPtr = (const BYTE*)src;
1114
1118
 
1119
+ DEBUGLOG(5, "LZ4F_decodeHeader");
1115
1120
  /* need to decode header to get frameInfo */
1116
1121
  if (srcSize < minFHSize) return err0r(LZ4F_ERROR_frameHeader_incomplete); /* minimal frame header size */
1117
1122
  MEM_INIT(&(dctx->frameInfo), 0, sizeof(dctx->frameInfo));
@@ -1132,8 +1137,10 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx* dctx, const void* src, size_t srcSize
1132
1137
 
1133
1138
  /* control magic number */
1134
1139
  #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1135
- if (LZ4F_readLE32(srcPtr) != LZ4F_MAGICNUMBER)
1140
+ if (LZ4F_readLE32(srcPtr) != LZ4F_MAGICNUMBER) {
1141
+ DEBUGLOG(4, "frame header error : unknown magic number");
1136
1142
  return err0r(LZ4F_ERROR_frameType_unknown);
1143
+ }
1137
1144
  #endif
1138
1145
  dctx->frameInfo.frameType = LZ4F_frame;
1139
1146
 
@@ -1282,15 +1289,20 @@ LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_dctx* dctx,
1282
1289
 
1283
1290
 
1284
1291
  /* LZ4F_updateDict() :
1285
- * only used for LZ4F_blockLinked mode */
1292
+ * only used for LZ4F_blockLinked mode
1293
+ * Condition : dstPtr != NULL
1294
+ */
1286
1295
  static void LZ4F_updateDict(LZ4F_dctx* dctx,
1287
1296
  const BYTE* dstPtr, size_t dstSize, const BYTE* dstBufferStart,
1288
1297
  unsigned withinTmp)
1289
1298
  {
1290
- if (dctx->dictSize==0)
1291
- dctx->dict = (const BYTE*)dstPtr; /* priority to dictionary continuity */
1299
+ assert(dstPtr != NULL);
1300
+ if (dctx->dictSize==0) {
1301
+ dctx->dict = (const BYTE*)dstPtr; /* priority to prefix mode */
1302
+ }
1303
+ assert(dctx->dict != NULL);
1292
1304
 
1293
- if (dctx->dict + dctx->dictSize == dstPtr) { /* dictionary continuity, directly within dstBuffer */
1305
+ if (dctx->dict + dctx->dictSize == dstPtr) { /* prefix mode, everything within dstBuffer */
1294
1306
  dctx->dictSize += dstSize;
1295
1307
  return;
1296
1308
  }
@@ -1304,9 +1316,10 @@ static void LZ4F_updateDict(LZ4F_dctx* dctx,
1304
1316
 
1305
1317
  assert(dstSize < 64 KB); /* if dstSize >= 64 KB, dictionary would be set into dstBuffer directly */
1306
1318
 
1307
- /* dstBuffer does not contain whole useful history (64 KB), so it must be saved within tmpOut */
1319
+ /* dstBuffer does not contain whole useful history (64 KB), so it must be saved within tmpOutBuffer */
1320
+ assert(dctx->tmpOutBuffer != NULL);
1308
1321
 
1309
- if ((withinTmp) && (dctx->dict == dctx->tmpOutBuffer)) { /* continue history within tmpOutBuffer */
1322
+ if (withinTmp && (dctx->dict == dctx->tmpOutBuffer)) { /* continue history within tmpOutBuffer */
1310
1323
  /* withinTmp expectation : content of [dstPtr,dstSize] is same as [dict+dictSize,dstSize], so we just extend it */
1311
1324
  assert(dctx->dict + dctx->dictSize == dctx->tmpOut + dctx->tmpOutStart);
1312
1325
  dctx->dictSize += dstSize;
@@ -1378,17 +1391,21 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1378
1391
  const BYTE* const srcEnd = srcStart + *srcSizePtr;
1379
1392
  const BYTE* srcPtr = srcStart;
1380
1393
  BYTE* const dstStart = (BYTE*)dstBuffer;
1381
- BYTE* const dstEnd = dstStart + *dstSizePtr;
1394
+ BYTE* const dstEnd = dstStart ? dstStart + *dstSizePtr : NULL;
1382
1395
  BYTE* dstPtr = dstStart;
1383
1396
  const BYTE* selectedIn = NULL;
1384
1397
  unsigned doAnotherStage = 1;
1385
1398
  size_t nextSrcSizeHint = 1;
1386
1399
 
1387
1400
 
1401
+ DEBUGLOG(5, "LZ4F_decompress : %p,%u => %p,%u",
1402
+ srcBuffer, (unsigned)*srcSizePtr, dstBuffer, (unsigned)*dstSizePtr);
1403
+ if (dstBuffer == NULL) assert(*dstSizePtr == 0);
1388
1404
  MEM_INIT(&optionsNull, 0, sizeof(optionsNull));
1389
1405
  if (decompressOptionsPtr==NULL) decompressOptionsPtr = &optionsNull;
1390
1406
  *srcSizePtr = 0;
1391
1407
  *dstSizePtr = 0;
1408
+ assert(dctx != NULL);
1392
1409
 
1393
1410
  /* behaves as a state machine */
1394
1411
 
@@ -1398,6 +1415,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1398
1415
  {
1399
1416
 
1400
1417
  case dstage_getFrameHeader:
1418
+ DEBUGLOG(6, "dstage_getFrameHeader");
1401
1419
  if ((size_t)(srcEnd-srcPtr) >= maxFHSize) { /* enough to decode - shortcut */
1402
1420
  size_t const hSize = LZ4F_decodeHeader(dctx, srcPtr, (size_t)(srcEnd-srcPtr)); /* will update dStage appropriately */
1403
1421
  if (LZ4F_isError(hSize)) return hSize;
@@ -1411,6 +1429,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1411
1429
  /* fall-through */
1412
1430
 
1413
1431
  case dstage_storeFrameHeader:
1432
+ DEBUGLOG(6, "dstage_storeFrameHeader");
1414
1433
  { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize, (size_t)(srcEnd - srcPtr));
1415
1434
  memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);
1416
1435
  dctx->tmpInSize += sizeToCopy;
@@ -1427,6 +1446,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1427
1446
  break;
1428
1447
 
1429
1448
  case dstage_init:
1449
+ DEBUGLOG(6, "dstage_init");
1430
1450
  if (dctx->frameInfo.contentChecksumFlag) (void)XXH32_reset(&(dctx->xxh), 0);
1431
1451
  /* internal buffers allocation */
1432
1452
  { size_t const bufferNeeded = dctx->maxBlockSize
@@ -1480,17 +1500,21 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1480
1500
  } /* if (dctx->dStage == dstage_storeBlockHeader) */
1481
1501
 
1482
1502
  /* decode block header */
1483
- { size_t const nextCBlockSize = LZ4F_readLE32(selectedIn) & 0x7FFFFFFFU;
1503
+ { U32 const blockHeader = LZ4F_readLE32(selectedIn);
1504
+ size_t const nextCBlockSize = blockHeader & 0x7FFFFFFFU;
1484
1505
  size_t const crcSize = dctx->frameInfo.blockChecksumFlag * BFSize;
1485
- if (nextCBlockSize==0) { /* frameEnd signal, no more block */
1506
+ if (blockHeader==0) { /* frameEnd signal, no more block */
1507
+ DEBUGLOG(5, "end of frame");
1486
1508
  dctx->dStage = dstage_getSuffix;
1487
1509
  break;
1488
1510
  }
1489
- if (nextCBlockSize > dctx->maxBlockSize)
1511
+ if (nextCBlockSize > dctx->maxBlockSize) {
1490
1512
  return err0r(LZ4F_ERROR_maxBlockSize_invalid);
1491
- if (LZ4F_readLE32(selectedIn) & LZ4F_BLOCKUNCOMPRESSED_FLAG) {
1513
+ }
1514
+ if (blockHeader & LZ4F_BLOCKUNCOMPRESSED_FLAG) {
1492
1515
  /* next block is uncompressed */
1493
1516
  dctx->tmpInTarget = nextCBlockSize;
1517
+ DEBUGLOG(5, "next block is uncompressed (size %u)", (U32)nextCBlockSize);
1494
1518
  if (dctx->frameInfo.blockChecksumFlag) {
1495
1519
  (void)XXH32_reset(&dctx->blockChecksum, 0);
1496
1520
  }
@@ -1508,20 +1532,26 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1508
1532
  }
1509
1533
 
1510
1534
  case dstage_copyDirect: /* uncompressed block */
1511
- { size_t const minBuffSize = MIN((size_t)(srcEnd-srcPtr), (size_t)(dstEnd-dstPtr));
1512
- size_t const sizeToCopy = MIN(dctx->tmpInTarget, minBuffSize);
1513
- memcpy(dstPtr, srcPtr, sizeToCopy);
1514
- if (dctx->frameInfo.blockChecksumFlag) {
1515
- (void)XXH32_update(&dctx->blockChecksum, srcPtr, sizeToCopy);
1516
- }
1517
- if (dctx->frameInfo.contentChecksumFlag)
1518
- (void)XXH32_update(&dctx->xxh, srcPtr, sizeToCopy);
1519
- if (dctx->frameInfo.contentSize)
1520
- dctx->frameRemainingSize -= sizeToCopy;
1535
+ DEBUGLOG(6, "dstage_copyDirect");
1536
+ { size_t sizeToCopy;
1537
+ if (dstPtr == NULL) {
1538
+ sizeToCopy = 0;
1539
+ } else {
1540
+ size_t const minBuffSize = MIN((size_t)(srcEnd-srcPtr), (size_t)(dstEnd-dstPtr));
1541
+ sizeToCopy = MIN(dctx->tmpInTarget, minBuffSize);
1542
+ memcpy(dstPtr, srcPtr, sizeToCopy);
1543
+ if (dctx->frameInfo.blockChecksumFlag) {
1544
+ (void)XXH32_update(&dctx->blockChecksum, srcPtr, sizeToCopy);
1545
+ }
1546
+ if (dctx->frameInfo.contentChecksumFlag)
1547
+ (void)XXH32_update(&dctx->xxh, srcPtr, sizeToCopy);
1548
+ if (dctx->frameInfo.contentSize)
1549
+ dctx->frameRemainingSize -= sizeToCopy;
1521
1550
 
1522
- /* history management (linked blocks only)*/
1523
- if (dctx->frameInfo.blockMode == LZ4F_blockLinked)
1524
- LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 0);
1551
+ /* history management (linked blocks only)*/
1552
+ if (dctx->frameInfo.blockMode == LZ4F_blockLinked) {
1553
+ LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 0);
1554
+ } }
1525
1555
 
1526
1556
  srcPtr += sizeToCopy;
1527
1557
  dstPtr += sizeToCopy;
@@ -1534,15 +1564,16 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1534
1564
  break;
1535
1565
  }
1536
1566
  dctx->tmpInTarget -= sizeToCopy; /* need to copy more */
1537
- nextSrcSizeHint = dctx->tmpInTarget +
1538
- +(dctx->frameInfo.blockChecksumFlag ? BFSize : 0)
1539
- + BHSize /* next header size */;
1540
- doAnotherStage = 0;
1541
- break;
1542
1567
  }
1568
+ nextSrcSizeHint = dctx->tmpInTarget +
1569
+ +(dctx->frameInfo.blockChecksumFlag ? BFSize : 0)
1570
+ + BHSize /* next header size */;
1571
+ doAnotherStage = 0;
1572
+ break;
1543
1573
 
1544
1574
  /* check block checksum for recently transferred uncompressed block */
1545
1575
  case dstage_getBlockChecksum:
1576
+ DEBUGLOG(6, "dstage_getBlockChecksum");
1546
1577
  { const void* crcSrc;
1547
1578
  if ((srcEnd-srcPtr >= 4) && (dctx->tmpInSize==0)) {
1548
1579
  crcSrc = srcPtr;
@@ -1562,8 +1593,12 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1562
1593
  { U32 const readCRC = LZ4F_readLE32(crcSrc);
1563
1594
  U32 const calcCRC = XXH32_digest(&dctx->blockChecksum);
1564
1595
  #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1565
- if (readCRC != calcCRC)
1596
+ DEBUGLOG(6, "compare block checksum");
1597
+ if (readCRC != calcCRC) {
1598
+ DEBUGLOG(4, "incorrect block checksum: %08X != %08X",
1599
+ readCRC, calcCRC);
1566
1600
  return err0r(LZ4F_ERROR_blockChecksum_invalid);
1601
+ }
1567
1602
  #else
1568
1603
  (void)readCRC;
1569
1604
  (void)calcCRC;
@@ -1573,6 +1608,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1573
1608
  break;
1574
1609
 
1575
1610
  case dstage_getCBlock:
1611
+ DEBUGLOG(6, "dstage_getCBlock");
1576
1612
  if ((size_t)(srcEnd-srcPtr) < dctx->tmpInTarget) {
1577
1613
  dctx->tmpInSize = 0;
1578
1614
  dctx->dStage = dstage_storeCBlock;
@@ -1582,7 +1618,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1582
1618
  selectedIn = srcPtr;
1583
1619
  srcPtr += dctx->tmpInTarget;
1584
1620
 
1585
- if (0) /* jump over next block */
1621
+ if (0) /* always jump over next block */
1586
1622
  case dstage_storeCBlock:
1587
1623
  { size_t const wantedData = dctx->tmpInTarget - dctx->tmpInSize;
1588
1624
  size_t const inputLeft = (size_t)(srcEnd-srcPtr);
@@ -1619,6 +1655,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1619
1655
  const char* dict = (const char*)dctx->dict;
1620
1656
  size_t dictSize = dctx->dictSize;
1621
1657
  int decodedSize;
1658
+ assert(dstPtr != NULL);
1622
1659
  if (dict && dictSize > 1 GB) {
1623
1660
  /* the dictSize param is an int, avoid truncation / sign issues */
1624
1661
  dict += dictSize - 64 KB;
@@ -1636,8 +1673,9 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1636
1673
  dctx->frameRemainingSize -= (size_t)decodedSize;
1637
1674
 
1638
1675
  /* dictionary management */
1639
- if (dctx->frameInfo.blockMode==LZ4F_blockLinked)
1676
+ if (dctx->frameInfo.blockMode==LZ4F_blockLinked) {
1640
1677
  LZ4F_updateDict(dctx, dstPtr, (size_t)decodedSize, dstStart, 0);
1678
+ }
1641
1679
 
1642
1680
  dstPtr += decodedSize;
1643
1681
  dctx->dStage = dstage_getBlockHeader;
@@ -1684,7 +1722,9 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1684
1722
  /* fall-through */
1685
1723
 
1686
1724
  case dstage_flushOut: /* flush decoded data from tmpOut to dstBuffer */
1687
- { size_t const sizeToCopy = MIN(dctx->tmpOutSize - dctx->tmpOutStart, (size_t)(dstEnd-dstPtr));
1725
+ DEBUGLOG(6, "dstage_flushOut");
1726
+ if (dstPtr != NULL) {
1727
+ size_t const sizeToCopy = MIN(dctx->tmpOutSize - dctx->tmpOutStart, (size_t)(dstEnd-dstPtr));
1688
1728
  memcpy(dstPtr, dctx->tmpOut + dctx->tmpOutStart, sizeToCopy);
1689
1729
 
1690
1730
  /* dictionary management */
@@ -1693,16 +1733,15 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1693
1733
 
1694
1734
  dctx->tmpOutStart += sizeToCopy;
1695
1735
  dstPtr += sizeToCopy;
1696
-
1697
- if (dctx->tmpOutStart == dctx->tmpOutSize) { /* all flushed */
1698
- dctx->dStage = dstage_getBlockHeader; /* get next block */
1699
- break;
1700
- }
1701
- /* could not flush everything : stop there, just request a block header */
1702
- doAnotherStage = 0;
1703
- nextSrcSizeHint = BHSize;
1736
+ }
1737
+ if (dctx->tmpOutStart == dctx->tmpOutSize) { /* all flushed */
1738
+ dctx->dStage = dstage_getBlockHeader; /* get next block */
1704
1739
  break;
1705
1740
  }
1741
+ /* could not flush everything : stop there, just request a block header */
1742
+ doAnotherStage = 0;
1743
+ nextSrcSizeHint = BHSize;
1744
+ break;
1706
1745
 
1707
1746
  case dstage_getSuffix:
1708
1747
  if (dctx->frameRemainingSize)
@@ -1806,6 +1845,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1806
1845
  LZ4F_STATIC_ASSERT((unsigned)dstage_init == 2);
1807
1846
  if ( (dctx->frameInfo.blockMode==LZ4F_blockLinked) /* next block will use up to 64KB from previous ones */
1808
1847
  && (dctx->dict != dctx->tmpOutBuffer) /* dictionary is not already within tmp */
1848
+ && (dctx->dict != NULL) /* dictionary exists */
1809
1849
  && (!decompressOptionsPtr->stableDst) /* cannot rely on dst data to remain there for next call */
1810
1850
  && ((unsigned)(dctx->dStage)-2 < (unsigned)(dstage_getSuffix)-2) ) /* valid stages : [init ... getSuffix[ */
1811
1851
  {
@@ -1815,9 +1855,9 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1815
1855
  const BYTE* oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart;
1816
1856
  if (dctx->tmpOutSize > 64 KB) copySize = 0;
1817
1857
  if (copySize > preserveSize) copySize = preserveSize;
1858
+ assert(dctx->tmpOutBuffer != NULL);
1818
1859
 
1819
- if (copySize > 0)
1820
- memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
1860
+ memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
1821
1861
 
1822
1862
  dctx->dict = dctx->tmpOutBuffer;
1823
1863
  dctx->dictSize = preserveSize + dctx->tmpOutStart;
@@ -1825,8 +1865,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
1825
1865
  const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize;
1826
1866
  size_t const newDictSize = MIN(dctx->dictSize, 64 KB);
1827
1867
 
1828
- if (newDictSize > 0)
1829
- memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);
1868
+ memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);
1830
1869
 
1831
1870
  dctx->dict = dctx->tmpOutBuffer;
1832
1871
  dctx->dictSize = newDictSize;