extlz4 0.3.1 → 0.3.2

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