zstd-ruby 1.5.2.3 → 1.5.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -5
  3. data/ext/zstdruby/extconf.rb +1 -1
  4. data/ext/zstdruby/libzstd/common/allocations.h +55 -0
  5. data/ext/zstdruby/libzstd/common/bits.h +200 -0
  6. data/ext/zstdruby/libzstd/common/bitstream.h +19 -60
  7. data/ext/zstdruby/libzstd/common/compiler.h +26 -3
  8. data/ext/zstdruby/libzstd/common/cpu.h +1 -1
  9. data/ext/zstdruby/libzstd/common/debug.c +1 -1
  10. data/ext/zstdruby/libzstd/common/debug.h +1 -1
  11. data/ext/zstdruby/libzstd/common/entropy_common.c +12 -40
  12. data/ext/zstdruby/libzstd/common/error_private.c +9 -2
  13. data/ext/zstdruby/libzstd/common/error_private.h +1 -1
  14. data/ext/zstdruby/libzstd/common/fse.h +5 -83
  15. data/ext/zstdruby/libzstd/common/fse_decompress.c +7 -99
  16. data/ext/zstdruby/libzstd/common/huf.h +65 -156
  17. data/ext/zstdruby/libzstd/common/mem.h +39 -46
  18. data/ext/zstdruby/libzstd/common/pool.c +26 -10
  19. data/ext/zstdruby/libzstd/common/pool.h +7 -1
  20. data/ext/zstdruby/libzstd/common/portability_macros.h +22 -3
  21. data/ext/zstdruby/libzstd/common/threading.c +68 -14
  22. data/ext/zstdruby/libzstd/common/threading.h +5 -10
  23. data/ext/zstdruby/libzstd/common/xxhash.c +2 -2
  24. data/ext/zstdruby/libzstd/common/xxhash.h +8 -8
  25. data/ext/zstdruby/libzstd/common/zstd_common.c +1 -36
  26. data/ext/zstdruby/libzstd/common/zstd_deps.h +1 -1
  27. data/ext/zstdruby/libzstd/common/zstd_internal.h +17 -118
  28. data/ext/zstdruby/libzstd/common/zstd_trace.h +3 -3
  29. data/ext/zstdruby/libzstd/compress/clevels.h +1 -1
  30. data/ext/zstdruby/libzstd/compress/fse_compress.c +7 -124
  31. data/ext/zstdruby/libzstd/compress/hist.c +1 -1
  32. data/ext/zstdruby/libzstd/compress/hist.h +1 -1
  33. data/ext/zstdruby/libzstd/compress/huf_compress.c +234 -169
  34. data/ext/zstdruby/libzstd/compress/zstd_compress.c +1243 -538
  35. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +225 -151
  36. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +115 -39
  37. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +16 -8
  38. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +3 -3
  39. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +1 -1
  40. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +25 -21
  41. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +1 -1
  42. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +128 -62
  43. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +95 -33
  44. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +3 -2
  45. data/ext/zstdruby/libzstd/compress/zstd_fast.c +433 -148
  46. data/ext/zstdruby/libzstd/compress/zstd_fast.h +3 -2
  47. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +398 -345
  48. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +4 -2
  49. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +5 -5
  50. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +1 -1
  51. data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +1 -1
  52. data/ext/zstdruby/libzstd/compress/zstd_opt.c +106 -80
  53. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  54. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +17 -9
  55. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +1 -1
  56. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +434 -441
  57. data/ext/zstdruby/libzstd/decompress/huf_decompress_amd64.S +30 -39
  58. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +4 -4
  59. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +1 -1
  60. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +205 -80
  61. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +201 -81
  62. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +6 -1
  63. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +4 -2
  64. data/ext/zstdruby/libzstd/dictBuilder/cover.c +19 -15
  65. data/ext/zstdruby/libzstd/dictBuilder/cover.h +1 -1
  66. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +2 -2
  67. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +11 -89
  68. data/ext/zstdruby/libzstd/zdict.h +53 -31
  69. data/ext/zstdruby/libzstd/zstd.h +580 -135
  70. data/ext/zstdruby/libzstd/zstd_errors.h +27 -8
  71. data/ext/zstdruby/main.c +6 -0
  72. data/ext/zstdruby/skippable_frame.c +63 -0
  73. data/lib/zstd-ruby/version.rb +1 -1
  74. metadata +9 -6
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) Yann Collet, Facebook, Inc.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -55,17 +55,18 @@
55
55
  /*-*******************************************************
56
56
  * Dependencies
57
57
  *********************************************************/
58
+ #include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */
58
59
  #include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
59
60
  #include "../common/mem.h" /* low level memory routines */
60
61
  #define FSE_STATIC_LINKING_ONLY
61
62
  #include "../common/fse.h"
62
- #define HUF_STATIC_LINKING_ONLY
63
63
  #include "../common/huf.h"
64
64
  #include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
65
65
  #include "../common/zstd_internal.h" /* blockProperties_t */
66
66
  #include "zstd_decompress_internal.h" /* ZSTD_DCtx */
67
67
  #include "zstd_ddict.h" /* ZSTD_DDictDictContent */
68
68
  #include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
69
+ #include "../common/bits.h" /* ZSTD_highbit32 */
69
70
 
70
71
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
71
72
  # include "../legacy/zstd_legacy.h"
@@ -78,11 +79,11 @@
78
79
  *************************************/
79
80
 
80
81
  #define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4
81
- #define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.
82
- * Currently, that means a 0.75 load factor.
83
- * So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded
84
- * the load factor of the ddict hash set.
85
- */
82
+ #define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.
83
+ * Currently, that means a 0.75 load factor.
84
+ * So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded
85
+ * the load factor of the ddict hash set.
86
+ */
86
87
 
87
88
  #define DDICT_HASHSET_TABLE_BASE_SIZE 64
88
89
  #define DDICT_HASHSET_RESIZE_FACTOR 2
@@ -243,6 +244,7 @@ static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
243
244
  dctx->outBufferMode = ZSTD_bm_buffered;
244
245
  dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
245
246
  dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
247
+ dctx->disableHufAsm = 0;
246
248
  }
247
249
 
248
250
  static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
@@ -438,16 +440,40 @@ size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
438
440
  * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
439
441
  * @return : 0, `zfhPtr` is correctly filled,
440
442
  * >0, `srcSize` is too small, value is wanted `srcSize` amount,
441
- * or an error code, which can be tested using ZSTD_isError() */
443
+ ** or an error code, which can be tested using ZSTD_isError() */
442
444
  size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
443
445
  {
444
446
  const BYTE* ip = (const BYTE*)src;
445
447
  size_t const minInputSize = ZSTD_startingInputLength(format);
446
448
 
447
- ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
448
- if (srcSize < minInputSize) return minInputSize;
449
- RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
449
+ DEBUGLOG(5, "ZSTD_getFrameHeader_advanced: minInputSize = %zu, srcSize = %zu", minInputSize, srcSize);
450
+
451
+ if (srcSize > 0) {
452
+ /* note : technically could be considered an assert(), since it's an invalid entry */
453
+ RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter : src==NULL, but srcSize>0");
454
+ }
455
+ if (srcSize < minInputSize) {
456
+ if (srcSize > 0 && format != ZSTD_f_zstd1_magicless) {
457
+ /* when receiving less than @minInputSize bytes,
458
+ * control these bytes at least correspond to a supported magic number
459
+ * in order to error out early if they don't.
460
+ **/
461
+ size_t const toCopy = MIN(4, srcSize);
462
+ unsigned char hbuf[4]; MEM_writeLE32(hbuf, ZSTD_MAGICNUMBER);
463
+ assert(src != NULL);
464
+ ZSTD_memcpy(hbuf, src, toCopy);
465
+ if ( MEM_readLE32(hbuf) != ZSTD_MAGICNUMBER ) {
466
+ /* not a zstd frame : let's check if it's a skippable frame */
467
+ MEM_writeLE32(hbuf, ZSTD_MAGIC_SKIPPABLE_START);
468
+ ZSTD_memcpy(hbuf, src, toCopy);
469
+ if ((MEM_readLE32(hbuf) & ZSTD_MAGIC_SKIPPABLE_MASK) != ZSTD_MAGIC_SKIPPABLE_START) {
470
+ RETURN_ERROR(prefix_unknown,
471
+ "first bytes don't correspond to any supported magic number");
472
+ } } }
473
+ return minInputSize;
474
+ }
450
475
 
476
+ ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzers may not understand that zfhPtr will be read only if return value is zero, since they are 2 different signals */
451
477
  if ( (format != ZSTD_f_zstd1_magicless)
452
478
  && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
453
479
  if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
@@ -563,49 +589,52 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
563
589
  sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
564
590
  RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
565
591
  frameParameter_unsupported, "");
566
- {
567
- size_t const skippableSize = skippableHeaderSize + sizeU32;
592
+ { size_t const skippableSize = skippableHeaderSize + sizeU32;
568
593
  RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
569
594
  return skippableSize;
570
595
  }
571
596
  }
572
597
 
573
598
  /*! ZSTD_readSkippableFrame() :
574
- * Retrieves a zstd skippable frame containing data given by src, and writes it to dst buffer.
599
+ * Retrieves content of a skippable frame, and writes it to dst buffer.
575
600
  *
576
601
  * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
577
602
  * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
578
603
  * in the magicVariant.
579
604
  *
580
- * Returns an error if destination buffer is not large enough, or if the frame is not skippable.
605
+ * Returns an error if destination buffer is not large enough, or if this is not a valid skippable frame.
581
606
  *
582
607
  * @return : number of bytes written or a ZSTD error.
583
608
  */
584
- ZSTDLIB_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, unsigned* magicVariant,
585
- const void* src, size_t srcSize)
609
+ size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity,
610
+ unsigned* magicVariant, /* optional, can be NULL */
611
+ const void* src, size_t srcSize)
586
612
  {
587
- U32 const magicNumber = MEM_readLE32(src);
588
- size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);
589
- size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;
590
-
591
- /* check input validity */
592
- RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, "");
593
- RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, "");
594
- RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, "");
613
+ RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
595
614
 
596
- /* deliver payload */
597
- if (skippableContentSize > 0 && dst != NULL)
598
- ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);
599
- if (magicVariant != NULL)
600
- *magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;
601
- return skippableContentSize;
615
+ { U32 const magicNumber = MEM_readLE32(src);
616
+ size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);
617
+ size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;
618
+
619
+ /* check input validity */
620
+ RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, "");
621
+ RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, "");
622
+ RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, "");
623
+
624
+ /* deliver payload */
625
+ if (skippableContentSize > 0 && dst != NULL)
626
+ ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);
627
+ if (magicVariant != NULL)
628
+ *magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;
629
+ return skippableContentSize;
630
+ }
602
631
  }
603
632
 
604
633
  /** ZSTD_findDecompressedSize() :
605
- * compatible with legacy mode
606
634
  * `srcSize` must be the exact length of some number of ZSTD compressed and/or
607
635
  * skippable frames
608
- * @return : decompressed size of the frames contained */
636
+ * note: compatible with legacy mode
637
+ * @return : decompressed size of the frames contained */
609
638
  unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
610
639
  {
611
640
  unsigned long long totalDstSize = 0;
@@ -615,9 +644,7 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
615
644
 
616
645
  if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
617
646
  size_t const skippableSize = readSkippableFrameSize(src, srcSize);
618
- if (ZSTD_isError(skippableSize)) {
619
- return ZSTD_CONTENTSIZE_ERROR;
620
- }
647
+ if (ZSTD_isError(skippableSize)) return ZSTD_CONTENTSIZE_ERROR;
621
648
  assert(skippableSize <= srcSize);
622
649
 
623
650
  src = (const BYTE *)src + skippableSize;
@@ -625,17 +652,17 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
625
652
  continue;
626
653
  }
627
654
 
628
- { unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
629
- if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret;
655
+ { unsigned long long const fcs = ZSTD_getFrameContentSize(src, srcSize);
656
+ if (fcs >= ZSTD_CONTENTSIZE_ERROR) return fcs;
630
657
 
631
- /* check for overflow */
632
- if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
633
- totalDstSize += ret;
658
+ if (totalDstSize + fcs < totalDstSize)
659
+ return ZSTD_CONTENTSIZE_ERROR; /* check for overflow */
660
+ totalDstSize += fcs;
634
661
  }
662
+ /* skip to next frame */
635
663
  { size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
636
- if (ZSTD_isError(frameSrcSize)) {
637
- return ZSTD_CONTENTSIZE_ERROR;
638
- }
664
+ if (ZSTD_isError(frameSrcSize)) return ZSTD_CONTENTSIZE_ERROR;
665
+ assert(frameSrcSize <= srcSize);
639
666
 
640
667
  src = (const BYTE *)src + frameSrcSize;
641
668
  srcSize -= frameSrcSize;
@@ -757,10 +784,11 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
757
784
  ip += 4;
758
785
  }
759
786
 
787
+ frameSizeInfo.nbBlocks = nbBlocks;
760
788
  frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
761
789
  frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
762
790
  ? zfh.frameContentSize
763
- : nbBlocks * zfh.blockSizeMax;
791
+ : (unsigned long long)nbBlocks * zfh.blockSizeMax;
764
792
  return frameSizeInfo;
765
793
  }
766
794
  }
@@ -800,6 +828,48 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
800
828
  return bound;
801
829
  }
802
830
 
831
+ size_t ZSTD_decompressionMargin(void const* src, size_t srcSize)
832
+ {
833
+ size_t margin = 0;
834
+ unsigned maxBlockSize = 0;
835
+
836
+ /* Iterate over each frame */
837
+ while (srcSize > 0) {
838
+ ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
839
+ size_t const compressedSize = frameSizeInfo.compressedSize;
840
+ unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
841
+ ZSTD_frameHeader zfh;
842
+
843
+ FORWARD_IF_ERROR(ZSTD_getFrameHeader(&zfh, src, srcSize), "");
844
+ if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
845
+ return ERROR(corruption_detected);
846
+
847
+ if (zfh.frameType == ZSTD_frame) {
848
+ /* Add the frame header to our margin */
849
+ margin += zfh.headerSize;
850
+ /* Add the checksum to our margin */
851
+ margin += zfh.checksumFlag ? 4 : 0;
852
+ /* Add 3 bytes per block */
853
+ margin += 3 * frameSizeInfo.nbBlocks;
854
+
855
+ /* Compute the max block size */
856
+ maxBlockSize = MAX(maxBlockSize, zfh.blockSizeMax);
857
+ } else {
858
+ assert(zfh.frameType == ZSTD_skippableFrame);
859
+ /* Add the entire skippable frame size to our margin. */
860
+ margin += compressedSize;
861
+ }
862
+
863
+ assert(srcSize >= compressedSize);
864
+ src = (const BYTE*)src + compressedSize;
865
+ srcSize -= compressedSize;
866
+ }
867
+
868
+ /* Add the max block size back to the margin. */
869
+ margin += maxBlockSize;
870
+
871
+ return margin;
872
+ }
803
873
 
804
874
  /*-*************************************************************
805
875
  * Frame decoding
@@ -825,7 +895,7 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
825
895
  if (srcSize == 0) return 0;
826
896
  RETURN_ERROR(dstBuffer_null, "");
827
897
  }
828
- ZSTD_memcpy(dst, src, srcSize);
898
+ ZSTD_memmove(dst, src, srcSize);
829
899
  return srcSize;
830
900
  }
831
901
 
@@ -903,6 +973,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
903
973
 
904
974
  /* Loop on each block */
905
975
  while (1) {
976
+ BYTE* oBlockEnd = oend;
906
977
  size_t decodedSize;
907
978
  blockProperties_t blockProperties;
908
979
  size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
@@ -912,16 +983,34 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
912
983
  remainingSrcSize -= ZSTD_blockHeaderSize;
913
984
  RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
914
985
 
986
+ if (ip >= op && ip < oBlockEnd) {
987
+ /* We are decompressing in-place. Limit the output pointer so that we
988
+ * don't overwrite the block that we are currently reading. This will
989
+ * fail decompression if the input & output pointers aren't spaced
990
+ * far enough apart.
991
+ *
992
+ * This is important to set, even when the pointers are far enough
993
+ * apart, because ZSTD_decompressBlock_internal() can decide to store
994
+ * literals in the output buffer, after the block it is decompressing.
995
+ * Since we don't want anything to overwrite our input, we have to tell
996
+ * ZSTD_decompressBlock_internal to never write past ip.
997
+ *
998
+ * See ZSTD_allocateLiteralsBuffer() for reference.
999
+ */
1000
+ oBlockEnd = op + (ip - op);
1001
+ }
1002
+
915
1003
  switch(blockProperties.blockType)
916
1004
  {
917
1005
  case bt_compressed:
918
- decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1, not_streaming);
1006
+ decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, /* frame */ 1, not_streaming);
919
1007
  break;
920
1008
  case bt_raw :
1009
+ /* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */
921
1010
  decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
922
1011
  break;
923
1012
  case bt_rle :
924
- decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize);
1013
+ decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize);
925
1014
  break;
926
1015
  case bt_reserved :
927
1016
  default:
@@ -956,6 +1045,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
956
1045
  }
957
1046
  ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
958
1047
  /* Allow caller to get size read */
1048
+ DEBUGLOG(4, "ZSTD_decompressFrame: decompressed frame of size %zi, consuming %zi bytes of input", op-ostart, ip - (const BYTE*)*srcPtr);
959
1049
  *srcPtr = ip;
960
1050
  *srcSizePtr = remainingSrcSize;
961
1051
  return (size_t)(op-ostart);
@@ -1002,17 +1092,18 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
1002
1092
  }
1003
1093
  #endif
1004
1094
 
1005
- { U32 const magicNumber = MEM_readLE32(src);
1006
- DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
1007
- (unsigned)magicNumber, ZSTD_MAGICNUMBER);
1095
+ if (srcSize >= 4) {
1096
+ U32 const magicNumber = MEM_readLE32(src);
1097
+ DEBUGLOG(5, "reading magic number %08X", (unsigned)magicNumber);
1008
1098
  if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
1099
+ /* skippable frame detected : skip it */
1009
1100
  size_t const skippableSize = readSkippableFrameSize(src, srcSize);
1010
- FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed");
1101
+ FORWARD_IF_ERROR(skippableSize, "invalid skippable frame");
1011
1102
  assert(skippableSize <= srcSize);
1012
1103
 
1013
1104
  src = (const BYTE *)src + skippableSize;
1014
1105
  srcSize -= skippableSize;
1015
- continue;
1106
+ continue; /* check next frame */
1016
1107
  } }
1017
1108
 
1018
1109
  if (ddict) {
@@ -1108,8 +1199,8 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
1108
1199
  size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
1109
1200
 
1110
1201
  /**
1111
- * Similar to ZSTD_nextSrcSizeToDecompress(), but when when a block input can be streamed,
1112
- * we allow taking a partial block as the input. Currently only raw uncompressed blocks can
1202
+ * Similar to ZSTD_nextSrcSizeToDecompress(), but when a block input can be streamed, we
1203
+ * allow taking a partial block as the input. Currently only raw uncompressed blocks can
1113
1204
  * be streamed.
1114
1205
  *
1115
1206
  * For blocks that can be streamed, this allows us to reduce the latency until we produce
@@ -1309,7 +1400,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1309
1400
 
1310
1401
  default:
1311
1402
  assert(0); /* impossible */
1312
- RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
1403
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
1313
1404
  }
1314
1405
  }
1315
1406
 
@@ -1350,11 +1441,11 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1350
1441
  /* in minimal huffman, we always use X1 variants */
1351
1442
  size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
1352
1443
  dictPtr, dictEnd - dictPtr,
1353
- workspace, workspaceSize);
1444
+ workspace, workspaceSize, /* flags */ 0);
1354
1445
  #else
1355
1446
  size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
1356
1447
  dictPtr, (size_t)(dictEnd - dictPtr),
1357
- workspace, workspaceSize);
1448
+ workspace, workspaceSize, /* flags */ 0);
1358
1449
  #endif
1359
1450
  RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
1360
1451
  dictPtr += hSize;
@@ -1453,7 +1544,7 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1453
1544
  dctx->prefixStart = NULL;
1454
1545
  dctx->virtualStart = NULL;
1455
1546
  dctx->dictEnd = NULL;
1456
- dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
1547
+ dctx->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001); /* cover both little and big endian */
1457
1548
  dctx->litEntropy = dctx->fseEntropy = 0;
1458
1549
  dctx->dictID = 0;
1459
1550
  dctx->bType = bt_reserved;
@@ -1515,7 +1606,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
1515
1606
  * This could for one of the following reasons :
1516
1607
  * - The frame does not require a dictionary (most common case).
1517
1608
  * - The frame was built with dictID intentionally removed.
1518
- * Needed dictionary is a hidden information.
1609
+ * Needed dictionary is a hidden piece of information.
1519
1610
  * Note : this use case also happens when using a non-conformant dictionary.
1520
1611
  * - `srcSize` is too small, and as a result, frame header could not be decoded.
1521
1612
  * Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
@@ -1524,7 +1615,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
1524
1615
  * ZSTD_getFrameHeader(), which will provide a more precise error code. */
1525
1616
  unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
1526
1617
  {
1527
- ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 };
1618
+ ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0, 0, 0 };
1528
1619
  size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
1529
1620
  if (ZSTD_isError(hError)) return 0;
1530
1621
  return zfp.dictID;
@@ -1631,7 +1722,9 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
1631
1722
  size_t ZSTD_initDStream(ZSTD_DStream* zds)
1632
1723
  {
1633
1724
  DEBUGLOG(4, "ZSTD_initDStream");
1634
- return ZSTD_initDStream_usingDDict(zds, NULL);
1725
+ FORWARD_IF_ERROR(ZSTD_DCtx_reset(zds, ZSTD_reset_session_only), "");
1726
+ FORWARD_IF_ERROR(ZSTD_DCtx_refDDict(zds, NULL), "");
1727
+ return ZSTD_startingInputLength(zds->format);
1635
1728
  }
1636
1729
 
1637
1730
  /* ZSTD_initDStream_usingDDict() :
@@ -1639,6 +1732,7 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
1639
1732
  * this function cannot fail */
1640
1733
  size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1641
1734
  {
1735
+ DEBUGLOG(4, "ZSTD_initDStream_usingDDict");
1642
1736
  FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
1643
1737
  FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
1644
1738
  return ZSTD_startingInputLength(dctx->format);
@@ -1649,6 +1743,7 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1649
1743
  * this function cannot fail */
1650
1744
  size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
1651
1745
  {
1746
+ DEBUGLOG(4, "ZSTD_resetDStream");
1652
1747
  FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
1653
1748
  return ZSTD_startingInputLength(dctx->format);
1654
1749
  }
@@ -1720,6 +1815,11 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
1720
1815
  bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
1721
1816
  bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
1722
1817
  return bounds;
1818
+ case ZSTD_d_disableHuffmanAssembly:
1819
+ bounds.lowerBound = 0;
1820
+ bounds.upperBound = 1;
1821
+ return bounds;
1822
+
1723
1823
  default:;
1724
1824
  }
1725
1825
  bounds.error = ERROR(parameter_unsupported);
@@ -1760,6 +1860,9 @@ size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value
1760
1860
  case ZSTD_d_refMultipleDDicts:
1761
1861
  *value = (int)dctx->refMultipleDDicts;
1762
1862
  return 0;
1863
+ case ZSTD_d_disableHuffmanAssembly:
1864
+ *value = (int)dctx->disableHufAsm;
1865
+ return 0;
1763
1866
  default:;
1764
1867
  }
1765
1868
  RETURN_ERROR(parameter_unsupported, "");
@@ -1793,6 +1896,10 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
1793
1896
  }
1794
1897
  dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
1795
1898
  return 0;
1899
+ case ZSTD_d_disableHuffmanAssembly:
1900
+ CHECK_DBOUNDS(ZSTD_d_disableHuffmanAssembly, value);
1901
+ dctx->disableHufAsm = value != 0;
1902
+ return 0;
1796
1903
  default:;
1797
1904
  }
1798
1905
  RETURN_ERROR(parameter_unsupported, "");
@@ -1980,7 +2087,6 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1980
2087
  if (zds->refMultipleDDicts && zds->ddictSet) {
1981
2088
  ZSTD_DCtx_selectFrameDDict(zds);
1982
2089
  }
1983
- DEBUGLOG(5, "header size : %u", (U32)hSize);
1984
2090
  if (ZSTD_isError(hSize)) {
1985
2091
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1986
2092
  U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
@@ -2012,6 +2118,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2012
2118
  zds->lhSize += remainingInput;
2013
2119
  }
2014
2120
  input->pos = input->size;
2121
+ /* check first few bytes */
2122
+ FORWARD_IF_ERROR(
2123
+ ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format),
2124
+ "First few bytes detected incorrect" );
2125
+ /* return hint input size */
2015
2126
  return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
2016
2127
  }
2017
2128
  assert(ip != NULL);
@@ -2029,8 +2140,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2029
2140
  size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
2030
2141
  if (ZSTD_isError(decompressedSize)) return decompressedSize;
2031
2142
  DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
2143
+ assert(istart != NULL);
2032
2144
  ip = istart + cSize;
2033
- op += decompressedSize;
2145
+ op = op ? op + decompressedSize : op; /* can occur if frameContentSize = 0 (empty frame) */
2034
2146
  zds->expected = 0;
2035
2147
  zds->streamStage = zdss_init;
2036
2148
  someMoreWork = 0;
@@ -2114,6 +2226,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2114
2226
  }
2115
2227
  if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
2116
2228
  FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
2229
+ assert(ip != NULL);
2117
2230
  ip += neededInSize;
2118
2231
  /* Function modifies the stage so we must break */
2119
2232
  break;
@@ -2128,7 +2241,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2128
2241
  int const isSkipFrame = ZSTD_isSkipFrame(zds);
2129
2242
  size_t loadedSize;
2130
2243
  /* At this point we shouldn't be decompressing a block that we can stream. */
2131
- assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
2244
+ assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)));
2132
2245
  if (isSkipFrame) {
2133
2246
  loadedSize = MIN(toLoad, (size_t)(iend-ip));
2134
2247
  } else {
@@ -2137,8 +2250,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2137
2250
  "should never happen");
2138
2251
  loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
2139
2252
  }
2140
- ip += loadedSize;
2141
- zds->inPos += loadedSize;
2253
+ if (loadedSize != 0) {
2254
+ /* ip may be NULL */
2255
+ ip += loadedSize;
2256
+ zds->inPos += loadedSize;
2257
+ }
2142
2258
  if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
2143
2259
 
2144
2260
  /* decode loaded input */
@@ -2148,14 +2264,17 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2148
2264
  break;
2149
2265
  }
2150
2266
  case zdss_flush:
2151
- { size_t const toFlushSize = zds->outEnd - zds->outStart;
2267
+ {
2268
+ size_t const toFlushSize = zds->outEnd - zds->outStart;
2152
2269
  size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
2153
- op += flushedSize;
2270
+
2271
+ op = op ? op + flushedSize : op;
2272
+
2154
2273
  zds->outStart += flushedSize;
2155
2274
  if (flushedSize == toFlushSize) { /* flush completed */
2156
2275
  zds->streamStage = zdss_read;
2157
2276
  if ( (zds->outBuffSize < zds->fParams.frameContentSize)
2158
- && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
2277
+ && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
2159
2278
  DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
2160
2279
  (int)(zds->outBuffSize - zds->outStart),
2161
2280
  (U32)zds->fParams.blockSizeMax);
@@ -2169,7 +2288,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2169
2288
 
2170
2289
  default:
2171
2290
  assert(0); /* impossible */
2172
- RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
2291
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
2173
2292
  } }
2174
2293
 
2175
2294
  /* result */
@@ -2182,8 +2301,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2182
2301
  if ((ip==istart) && (op==ostart)) { /* no forward progress */
2183
2302
  zds->noForwardProgress ++;
2184
2303
  if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
2185
- RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
2186
- RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
2304
+ RETURN_ERROR_IF(op==oend, noForwardProgress_destFull, "");
2305
+ RETURN_ERROR_IF(ip==iend, noForwardProgress_inputEmpty, "");
2187
2306
  assert(0);
2188
2307
  }
2189
2308
  } else {
@@ -2220,11 +2339,17 @@ size_t ZSTD_decompressStream_simpleArgs (
2220
2339
  void* dst, size_t dstCapacity, size_t* dstPos,
2221
2340
  const void* src, size_t srcSize, size_t* srcPos)
2222
2341
  {
2223
- ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
2224
- ZSTD_inBuffer input = { src, srcSize, *srcPos };
2225
- /* ZSTD_compress_generic() will check validity of dstPos and srcPos */
2226
- size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
2227
- *dstPos = output.pos;
2228
- *srcPos = input.pos;
2229
- return cErr;
2342
+ ZSTD_outBuffer output;
2343
+ ZSTD_inBuffer input;
2344
+ output.dst = dst;
2345
+ output.size = dstCapacity;
2346
+ output.pos = *dstPos;
2347
+ input.src = src;
2348
+ input.size = srcSize;
2349
+ input.pos = *srcPos;
2350
+ { size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
2351
+ *dstPos = output.pos;
2352
+ *srcPos = input.pos;
2353
+ return cErr;
2354
+ }
2230
2355
  }