zstd-ruby 1.5.2.2 → 1.5.4.0

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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -3
  3. data/ext/zstdruby/common.h +7 -0
  4. data/ext/zstdruby/libzstd/common/bits.h +175 -0
  5. data/ext/zstdruby/libzstd/common/bitstream.h +18 -59
  6. data/ext/zstdruby/libzstd/common/compiler.h +22 -3
  7. data/ext/zstdruby/libzstd/common/cpu.h +1 -1
  8. data/ext/zstdruby/libzstd/common/debug.c +1 -1
  9. data/ext/zstdruby/libzstd/common/debug.h +1 -1
  10. data/ext/zstdruby/libzstd/common/entropy_common.c +12 -40
  11. data/ext/zstdruby/libzstd/common/error_private.c +9 -2
  12. data/ext/zstdruby/libzstd/common/error_private.h +1 -1
  13. data/ext/zstdruby/libzstd/common/fse.h +5 -83
  14. data/ext/zstdruby/libzstd/common/fse_decompress.c +7 -99
  15. data/ext/zstdruby/libzstd/common/huf.h +65 -156
  16. data/ext/zstdruby/libzstd/common/mem.h +39 -46
  17. data/ext/zstdruby/libzstd/common/pool.c +26 -10
  18. data/ext/zstdruby/libzstd/common/pool.h +7 -1
  19. data/ext/zstdruby/libzstd/common/portability_macros.h +22 -3
  20. data/ext/zstdruby/libzstd/common/threading.c +68 -14
  21. data/ext/zstdruby/libzstd/common/threading.h +5 -10
  22. data/ext/zstdruby/libzstd/common/xxhash.c +2 -2
  23. data/ext/zstdruby/libzstd/common/xxhash.h +8 -8
  24. data/ext/zstdruby/libzstd/common/zstd_common.c +1 -1
  25. data/ext/zstdruby/libzstd/common/zstd_deps.h +1 -1
  26. data/ext/zstdruby/libzstd/common/zstd_internal.h +17 -113
  27. data/ext/zstdruby/libzstd/common/zstd_trace.h +3 -3
  28. data/ext/zstdruby/libzstd/compress/clevels.h +1 -1
  29. data/ext/zstdruby/libzstd/compress/fse_compress.c +7 -124
  30. data/ext/zstdruby/libzstd/compress/hist.c +1 -1
  31. data/ext/zstdruby/libzstd/compress/hist.h +1 -1
  32. data/ext/zstdruby/libzstd/compress/huf_compress.c +234 -169
  33. data/ext/zstdruby/libzstd/compress/zstd_compress.c +1055 -455
  34. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +165 -145
  35. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +115 -39
  36. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +16 -8
  37. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +3 -3
  38. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +1 -1
  39. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +25 -21
  40. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +1 -1
  41. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +5 -3
  42. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +95 -33
  43. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +3 -2
  44. data/ext/zstdruby/libzstd/compress/zstd_fast.c +433 -148
  45. data/ext/zstdruby/libzstd/compress/zstd_fast.h +3 -2
  46. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +306 -283
  47. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +4 -2
  48. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +5 -5
  49. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +1 -1
  50. data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +1 -1
  51. data/ext/zstdruby/libzstd/compress/zstd_opt.c +104 -80
  52. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  53. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +12 -5
  54. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +1 -1
  55. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +434 -441
  56. data/ext/zstdruby/libzstd/decompress/huf_decompress_amd64.S +30 -39
  57. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +3 -4
  58. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +1 -1
  59. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +164 -42
  60. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +186 -65
  61. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +1 -1
  62. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +4 -2
  63. data/ext/zstdruby/libzstd/dictBuilder/cover.c +19 -15
  64. data/ext/zstdruby/libzstd/dictBuilder/cover.h +1 -1
  65. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +2 -2
  66. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +9 -87
  67. data/ext/zstdruby/libzstd/zdict.h +53 -31
  68. data/ext/zstdruby/libzstd/zstd.h +489 -90
  69. data/ext/zstdruby/libzstd/zstd_errors.h +27 -8
  70. data/ext/zstdruby/main.c +4 -0
  71. data/ext/zstdruby/streaming_compress.c +1 -7
  72. data/ext/zstdruby/zstdruby.c +110 -26
  73. data/lib/zstd-ruby/version.rb +1 -1
  74. data/lib/zstd-ruby.rb +0 -1
  75. metadata +7 -6
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 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
@@ -30,14 +30,14 @@
30
30
  * TODO: Support Windows calling convention.
31
31
  */
32
32
 
33
- ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop)
34
- ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop)
35
- ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop)
36
- ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop)
37
- .global HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop
38
- .global HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop
39
- .global _HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop
40
- .global _HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop
33
+ ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X1_usingDTable_internal_fast_asm_loop)
34
+ ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X2_usingDTable_internal_fast_asm_loop)
35
+ ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X2_usingDTable_internal_fast_asm_loop)
36
+ ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X1_usingDTable_internal_fast_asm_loop)
37
+ .global HUF_decompress4X1_usingDTable_internal_fast_asm_loop
38
+ .global HUF_decompress4X2_usingDTable_internal_fast_asm_loop
39
+ .global _HUF_decompress4X1_usingDTable_internal_fast_asm_loop
40
+ .global _HUF_decompress4X2_usingDTable_internal_fast_asm_loop
41
41
  .text
42
42
 
43
43
  /* Sets up register mappings for clarity.
@@ -95,8 +95,9 @@ ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop)
95
95
  /* Define both _HUF_* & HUF_* symbols because MacOS
96
96
  * C symbols are prefixed with '_' & Linux symbols aren't.
97
97
  */
98
- _HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop:
99
- HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop:
98
+ _HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
99
+ HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
100
+ ZSTD_CET_ENDBRANCH
100
101
  /* Save all registers - even if they are callee saved for simplicity. */
101
102
  push %rax
102
103
  push %rbx
@@ -350,8 +351,9 @@ HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop:
350
351
  pop %rax
351
352
  ret
352
353
 
353
- _HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop:
354
- HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop:
354
+ _HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
355
+ HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
356
+ ZSTD_CET_ENDBRANCH
355
357
  /* Save all registers - even if they are callee saved for simplicity. */
356
358
  push %rax
357
359
  push %rbx
@@ -427,41 +429,30 @@ HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop:
427
429
  /* r15 = (ip0 - ilimit) / 7 */
428
430
  movq %rdx, %r15
429
431
 
430
- movabsq $-3689348814741910323, %rdx
431
- movq 8(%rsp), %rax /* rax = oend0 */
432
- subq %op0, %rax /* rax = oend0 - op0 */
433
- mulq %rdx
434
- shrq $3, %rdx /* rdx = rax / 10 */
435
-
436
- /* r15 = min(%rdx, %r15) */
437
- cmpq %rdx, %r15
438
- cmova %rdx, %r15
432
+ /* r15 = min(r15, min(oend0 - op0, oend1 - op1, oend2 - op2, oend3 - op3) / 10) */
433
+ movq 8(%rsp), %rax /* rax = oend0 */
434
+ subq %op0, %rax /* rax = oend0 - op0 */
435
+ movq 16(%rsp), %rdx /* rdx = oend1 */
436
+ subq %op1, %rdx /* rdx = oend1 - op1 */
439
437
 
440
- movabsq $-3689348814741910323, %rdx
441
- movq 16(%rsp), %rax /* rax = oend1 */
442
- subq %op1, %rax /* rax = oend1 - op1 */
443
- mulq %rdx
444
- shrq $3, %rdx /* rdx = rax / 10 */
445
-
446
- /* r15 = min(%rdx, %r15) */
447
- cmpq %rdx, %r15
448
- cmova %rdx, %r15
438
+ cmpq %rax, %rdx
439
+ cmova %rax, %rdx /* rdx = min(%rdx, %rax) */
449
440
 
450
- movabsq $-3689348814741910323, %rdx
451
441
  movq 24(%rsp), %rax /* rax = oend2 */
452
442
  subq %op2, %rax /* rax = oend2 - op2 */
453
- mulq %rdx
454
- shrq $3, %rdx /* rdx = rax / 10 */
455
443
 
456
- /* r15 = min(%rdx, %r15) */
457
- cmpq %rdx, %r15
458
- cmova %rdx, %r15
444
+ cmpq %rax, %rdx
445
+ cmova %rax, %rdx /* rdx = min(%rdx, %rax) */
459
446
 
460
- movabsq $-3689348814741910323, %rdx
461
447
  movq 32(%rsp), %rax /* rax = oend3 */
462
448
  subq %op3, %rax /* rax = oend3 - op3 */
449
+
450
+ cmpq %rax, %rdx
451
+ cmova %rax, %rdx /* rdx = min(%rdx, %rax) */
452
+
453
+ movabsq $-3689348814741910323, %rax
463
454
  mulq %rdx
464
- shrq $3, %rdx /* rdx = rax / 10 */
455
+ shrq $3, %rdx /* rdx = rdx / 10 */
465
456
 
466
457
  /* r15 = min(%rdx, %r15) */
467
458
  cmpq %rdx, %r15
@@ -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
@@ -19,7 +19,6 @@
19
19
  #include "../common/mem.h" /* low level memory routines */
20
20
  #define FSE_STATIC_LINKING_ONLY
21
21
  #include "../common/fse.h"
22
- #define HUF_STATIC_LINKING_ONLY
23
22
  #include "../common/huf.h"
24
23
  #include "zstd_decompress_internal.h"
25
24
  #include "zstd_ddict.h"
@@ -134,7 +133,7 @@ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,
134
133
  ZSTD_memcpy(internalBuffer, dict, dictSize);
135
134
  }
136
135
  ddict->dictSize = dictSize;
137
- ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
136
+ ddict->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001); /* cover both little and big endian */
138
137
 
139
138
  /* parse dictionary content */
140
139
  FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) , "");
@@ -240,5 +239,5 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
240
239
  unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)
241
240
  {
242
241
  if (ddict==NULL) return 0;
243
- return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize);
242
+ return ddict->dictID;
244
243
  }
@@ -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
@@ -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
@@ -59,13 +59,13 @@
59
59
  #include "../common/mem.h" /* low level memory routines */
60
60
  #define FSE_STATIC_LINKING_ONLY
61
61
  #include "../common/fse.h"
62
- #define HUF_STATIC_LINKING_ONLY
63
62
  #include "../common/huf.h"
64
63
  #include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
65
64
  #include "../common/zstd_internal.h" /* blockProperties_t */
66
65
  #include "zstd_decompress_internal.h" /* ZSTD_DCtx */
67
66
  #include "zstd_ddict.h" /* ZSTD_DDictDictContent */
68
67
  #include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
68
+ #include "../common/bits.h" /* ZSTD_highbit32 */
69
69
 
70
70
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
71
71
  # include "../legacy/zstd_legacy.h"
@@ -78,11 +78,11 @@
78
78
  *************************************/
79
79
 
80
80
  #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
- */
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
+ */
86
86
 
87
87
  #define DDICT_HASHSET_TABLE_BASE_SIZE 64
88
88
  #define DDICT_HASHSET_RESIZE_FACTOR 2
@@ -243,6 +243,7 @@ static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
243
243
  dctx->outBufferMode = ZSTD_bm_buffered;
244
244
  dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
245
245
  dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
246
+ dctx->disableHufAsm = 0;
246
247
  }
247
248
 
248
249
  static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
@@ -438,16 +439,40 @@ size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
438
439
  * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
439
440
  * @return : 0, `zfhPtr` is correctly filled,
440
441
  * >0, `srcSize` is too small, value is wanted `srcSize` amount,
441
- * or an error code, which can be tested using ZSTD_isError() */
442
+ ** or an error code, which can be tested using ZSTD_isError() */
442
443
  size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
443
444
  {
444
445
  const BYTE* ip = (const BYTE*)src;
445
446
  size_t const minInputSize = ZSTD_startingInputLength(format);
446
447
 
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");
448
+ DEBUGLOG(5, "ZSTD_getFrameHeader_advanced: minInputSize = %zu, srcSize = %zu", minInputSize, srcSize);
450
449
 
450
+ if (srcSize > 0) {
451
+ /* note : technically could be considered an assert(), since it's an invalid entry */
452
+ RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter : src==NULL, but srcSize>0");
453
+ }
454
+ if (srcSize < minInputSize) {
455
+ if (srcSize > 0 && format != ZSTD_f_zstd1_magicless) {
456
+ /* when receiving less than @minInputSize bytes,
457
+ * control these bytes at least correspond to a supported magic number
458
+ * in order to error out early if they don't.
459
+ **/
460
+ size_t const toCopy = MIN(4, srcSize);
461
+ unsigned char hbuf[4]; MEM_writeLE32(hbuf, ZSTD_MAGICNUMBER);
462
+ assert(src != NULL);
463
+ ZSTD_memcpy(hbuf, src, toCopy);
464
+ if ( MEM_readLE32(hbuf) != ZSTD_MAGICNUMBER ) {
465
+ /* not a zstd frame : let's check if it's a skippable frame */
466
+ MEM_writeLE32(hbuf, ZSTD_MAGIC_SKIPPABLE_START);
467
+ ZSTD_memcpy(hbuf, src, toCopy);
468
+ if ((MEM_readLE32(hbuf) & ZSTD_MAGIC_SKIPPABLE_MASK) != ZSTD_MAGIC_SKIPPABLE_START) {
469
+ RETURN_ERROR(prefix_unknown,
470
+ "first bytes don't correspond to any supported magic number");
471
+ } } }
472
+ return minInputSize;
473
+ }
474
+
475
+ 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
476
  if ( (format != ZSTD_f_zstd1_magicless)
452
477
  && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
453
478
  if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
@@ -757,10 +782,11 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
757
782
  ip += 4;
758
783
  }
759
784
 
785
+ frameSizeInfo.nbBlocks = nbBlocks;
760
786
  frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
761
787
  frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
762
788
  ? zfh.frameContentSize
763
- : nbBlocks * zfh.blockSizeMax;
789
+ : (unsigned long long)nbBlocks * zfh.blockSizeMax;
764
790
  return frameSizeInfo;
765
791
  }
766
792
  }
@@ -800,6 +826,48 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
800
826
  return bound;
801
827
  }
802
828
 
829
+ size_t ZSTD_decompressionMargin(void const* src, size_t srcSize)
830
+ {
831
+ size_t margin = 0;
832
+ unsigned maxBlockSize = 0;
833
+
834
+ /* Iterate over each frame */
835
+ while (srcSize > 0) {
836
+ ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
837
+ size_t const compressedSize = frameSizeInfo.compressedSize;
838
+ unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
839
+ ZSTD_frameHeader zfh;
840
+
841
+ FORWARD_IF_ERROR(ZSTD_getFrameHeader(&zfh, src, srcSize), "");
842
+ if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
843
+ return ERROR(corruption_detected);
844
+
845
+ if (zfh.frameType == ZSTD_frame) {
846
+ /* Add the frame header to our margin */
847
+ margin += zfh.headerSize;
848
+ /* Add the checksum to our margin */
849
+ margin += zfh.checksumFlag ? 4 : 0;
850
+ /* Add 3 bytes per block */
851
+ margin += 3 * frameSizeInfo.nbBlocks;
852
+
853
+ /* Compute the max block size */
854
+ maxBlockSize = MAX(maxBlockSize, zfh.blockSizeMax);
855
+ } else {
856
+ assert(zfh.frameType == ZSTD_skippableFrame);
857
+ /* Add the entire skippable frame size to our margin. */
858
+ margin += compressedSize;
859
+ }
860
+
861
+ assert(srcSize >= compressedSize);
862
+ src = (const BYTE*)src + compressedSize;
863
+ srcSize -= compressedSize;
864
+ }
865
+
866
+ /* Add the max block size back to the margin. */
867
+ margin += maxBlockSize;
868
+
869
+ return margin;
870
+ }
803
871
 
804
872
  /*-*************************************************************
805
873
  * Frame decoding
@@ -825,7 +893,7 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
825
893
  if (srcSize == 0) return 0;
826
894
  RETURN_ERROR(dstBuffer_null, "");
827
895
  }
828
- ZSTD_memcpy(dst, src, srcSize);
896
+ ZSTD_memmove(dst, src, srcSize);
829
897
  return srcSize;
830
898
  }
831
899
 
@@ -903,6 +971,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
903
971
 
904
972
  /* Loop on each block */
905
973
  while (1) {
974
+ BYTE* oBlockEnd = oend;
906
975
  size_t decodedSize;
907
976
  blockProperties_t blockProperties;
908
977
  size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
@@ -912,16 +981,34 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
912
981
  remainingSrcSize -= ZSTD_blockHeaderSize;
913
982
  RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
914
983
 
984
+ if (ip >= op && ip < oBlockEnd) {
985
+ /* We are decompressing in-place. Limit the output pointer so that we
986
+ * don't overwrite the block that we are currently reading. This will
987
+ * fail decompression if the input & output pointers aren't spaced
988
+ * far enough apart.
989
+ *
990
+ * This is important to set, even when the pointers are far enough
991
+ * apart, because ZSTD_decompressBlock_internal() can decide to store
992
+ * literals in the output buffer, after the block it is decompressing.
993
+ * Since we don't want anything to overwrite our input, we have to tell
994
+ * ZSTD_decompressBlock_internal to never write past ip.
995
+ *
996
+ * See ZSTD_allocateLiteralsBuffer() for reference.
997
+ */
998
+ oBlockEnd = op + (ip - op);
999
+ }
1000
+
915
1001
  switch(blockProperties.blockType)
916
1002
  {
917
1003
  case bt_compressed:
918
- decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1, not_streaming);
1004
+ decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, /* frame */ 1, not_streaming);
919
1005
  break;
920
1006
  case bt_raw :
1007
+ /* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */
921
1008
  decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
922
1009
  break;
923
1010
  case bt_rle :
924
- decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize);
1011
+ decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize);
925
1012
  break;
926
1013
  case bt_reserved :
927
1014
  default:
@@ -956,6 +1043,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
956
1043
  }
957
1044
  ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
958
1045
  /* Allow caller to get size read */
1046
+ DEBUGLOG(4, "ZSTD_decompressFrame: decompressed frame of size %zi, consuming %zi bytes of input", op-ostart, ip - (const BYTE*)*srcPtr);
959
1047
  *srcPtr = ip;
960
1048
  *srcSizePtr = remainingSrcSize;
961
1049
  return (size_t)(op-ostart);
@@ -1108,8 +1196,8 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
1108
1196
  size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
1109
1197
 
1110
1198
  /**
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
1199
+ * Similar to ZSTD_nextSrcSizeToDecompress(), but when a block input can be streamed, we
1200
+ * allow taking a partial block as the input. Currently only raw uncompressed blocks can
1113
1201
  * be streamed.
1114
1202
  *
1115
1203
  * For blocks that can be streamed, this allows us to reduce the latency until we produce
@@ -1309,7 +1397,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1309
1397
 
1310
1398
  default:
1311
1399
  assert(0); /* impossible */
1312
- RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
1400
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
1313
1401
  }
1314
1402
  }
1315
1403
 
@@ -1350,11 +1438,11 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1350
1438
  /* in minimal huffman, we always use X1 variants */
1351
1439
  size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
1352
1440
  dictPtr, dictEnd - dictPtr,
1353
- workspace, workspaceSize);
1441
+ workspace, workspaceSize, /* flags */ 0);
1354
1442
  #else
1355
1443
  size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
1356
1444
  dictPtr, (size_t)(dictEnd - dictPtr),
1357
- workspace, workspaceSize);
1445
+ workspace, workspaceSize, /* flags */ 0);
1358
1446
  #endif
1359
1447
  RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
1360
1448
  dictPtr += hSize;
@@ -1453,7 +1541,7 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1453
1541
  dctx->prefixStart = NULL;
1454
1542
  dctx->virtualStart = NULL;
1455
1543
  dctx->dictEnd = NULL;
1456
- dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
1544
+ dctx->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001); /* cover both little and big endian */
1457
1545
  dctx->litEntropy = dctx->fseEntropy = 0;
1458
1546
  dctx->dictID = 0;
1459
1547
  dctx->bType = bt_reserved;
@@ -1515,7 +1603,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
1515
1603
  * This could for one of the following reasons :
1516
1604
  * - The frame does not require a dictionary (most common case).
1517
1605
  * - The frame was built with dictID intentionally removed.
1518
- * Needed dictionary is a hidden information.
1606
+ * Needed dictionary is a hidden piece of information.
1519
1607
  * Note : this use case also happens when using a non-conformant dictionary.
1520
1608
  * - `srcSize` is too small, and as a result, frame header could not be decoded.
1521
1609
  * Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
@@ -1524,7 +1612,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
1524
1612
  * ZSTD_getFrameHeader(), which will provide a more precise error code. */
1525
1613
  unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
1526
1614
  {
1527
- ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 };
1615
+ ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0, 0, 0 };
1528
1616
  size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
1529
1617
  if (ZSTD_isError(hError)) return 0;
1530
1618
  return zfp.dictID;
@@ -1631,7 +1719,9 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
1631
1719
  size_t ZSTD_initDStream(ZSTD_DStream* zds)
1632
1720
  {
1633
1721
  DEBUGLOG(4, "ZSTD_initDStream");
1634
- return ZSTD_initDStream_usingDDict(zds, NULL);
1722
+ FORWARD_IF_ERROR(ZSTD_DCtx_reset(zds, ZSTD_reset_session_only), "");
1723
+ FORWARD_IF_ERROR(ZSTD_DCtx_refDDict(zds, NULL), "");
1724
+ return ZSTD_startingInputLength(zds->format);
1635
1725
  }
1636
1726
 
1637
1727
  /* ZSTD_initDStream_usingDDict() :
@@ -1639,6 +1729,7 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
1639
1729
  * this function cannot fail */
1640
1730
  size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1641
1731
  {
1732
+ DEBUGLOG(4, "ZSTD_initDStream_usingDDict");
1642
1733
  FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
1643
1734
  FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
1644
1735
  return ZSTD_startingInputLength(dctx->format);
@@ -1649,6 +1740,7 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1649
1740
  * this function cannot fail */
1650
1741
  size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
1651
1742
  {
1743
+ DEBUGLOG(4, "ZSTD_resetDStream");
1652
1744
  FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
1653
1745
  return ZSTD_startingInputLength(dctx->format);
1654
1746
  }
@@ -1720,6 +1812,11 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
1720
1812
  bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
1721
1813
  bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
1722
1814
  return bounds;
1815
+ case ZSTD_d_disableHuffmanAssembly:
1816
+ bounds.lowerBound = 0;
1817
+ bounds.upperBound = 1;
1818
+ return bounds;
1819
+
1723
1820
  default:;
1724
1821
  }
1725
1822
  bounds.error = ERROR(parameter_unsupported);
@@ -1760,6 +1857,9 @@ size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value
1760
1857
  case ZSTD_d_refMultipleDDicts:
1761
1858
  *value = (int)dctx->refMultipleDDicts;
1762
1859
  return 0;
1860
+ case ZSTD_d_disableHuffmanAssembly:
1861
+ *value = (int)dctx->disableHufAsm;
1862
+ return 0;
1763
1863
  default:;
1764
1864
  }
1765
1865
  RETURN_ERROR(parameter_unsupported, "");
@@ -1793,6 +1893,10 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
1793
1893
  }
1794
1894
  dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
1795
1895
  return 0;
1896
+ case ZSTD_d_disableHuffmanAssembly:
1897
+ CHECK_DBOUNDS(ZSTD_d_disableHuffmanAssembly, value);
1898
+ dctx->disableHufAsm = value != 0;
1899
+ return 0;
1796
1900
  default:;
1797
1901
  }
1798
1902
  RETURN_ERROR(parameter_unsupported, "");
@@ -1980,7 +2084,6 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1980
2084
  if (zds->refMultipleDDicts && zds->ddictSet) {
1981
2085
  ZSTD_DCtx_selectFrameDDict(zds);
1982
2086
  }
1983
- DEBUGLOG(5, "header size : %u", (U32)hSize);
1984
2087
  if (ZSTD_isError(hSize)) {
1985
2088
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1986
2089
  U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
@@ -2012,6 +2115,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2012
2115
  zds->lhSize += remainingInput;
2013
2116
  }
2014
2117
  input->pos = input->size;
2118
+ /* check first few bytes */
2119
+ FORWARD_IF_ERROR(
2120
+ ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format),
2121
+ "First few bytes detected incorrect" );
2122
+ /* return hint input size */
2015
2123
  return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
2016
2124
  }
2017
2125
  assert(ip != NULL);
@@ -2029,8 +2137,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2029
2137
  size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
2030
2138
  if (ZSTD_isError(decompressedSize)) return decompressedSize;
2031
2139
  DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
2140
+ assert(istart != NULL);
2032
2141
  ip = istart + cSize;
2033
- op += decompressedSize;
2142
+ op = op ? op + decompressedSize : op; /* can occur if frameContentSize = 0 (empty frame) */
2034
2143
  zds->expected = 0;
2035
2144
  zds->streamStage = zdss_init;
2036
2145
  someMoreWork = 0;
@@ -2114,6 +2223,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2114
2223
  }
2115
2224
  if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
2116
2225
  FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
2226
+ assert(ip != NULL);
2117
2227
  ip += neededInSize;
2118
2228
  /* Function modifies the stage so we must break */
2119
2229
  break;
@@ -2128,7 +2238,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2128
2238
  int const isSkipFrame = ZSTD_isSkipFrame(zds);
2129
2239
  size_t loadedSize;
2130
2240
  /* At this point we shouldn't be decompressing a block that we can stream. */
2131
- assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
2241
+ assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)));
2132
2242
  if (isSkipFrame) {
2133
2243
  loadedSize = MIN(toLoad, (size_t)(iend-ip));
2134
2244
  } else {
@@ -2137,8 +2247,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2137
2247
  "should never happen");
2138
2248
  loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
2139
2249
  }
2140
- ip += loadedSize;
2141
- zds->inPos += loadedSize;
2250
+ if (loadedSize != 0) {
2251
+ /* ip may be NULL */
2252
+ ip += loadedSize;
2253
+ zds->inPos += loadedSize;
2254
+ }
2142
2255
  if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
2143
2256
 
2144
2257
  /* decode loaded input */
@@ -2148,14 +2261,17 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2148
2261
  break;
2149
2262
  }
2150
2263
  case zdss_flush:
2151
- { size_t const toFlushSize = zds->outEnd - zds->outStart;
2264
+ {
2265
+ size_t const toFlushSize = zds->outEnd - zds->outStart;
2152
2266
  size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
2153
- op += flushedSize;
2267
+
2268
+ op = op ? op + flushedSize : op;
2269
+
2154
2270
  zds->outStart += flushedSize;
2155
2271
  if (flushedSize == toFlushSize) { /* flush completed */
2156
2272
  zds->streamStage = zdss_read;
2157
2273
  if ( (zds->outBuffSize < zds->fParams.frameContentSize)
2158
- && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
2274
+ && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
2159
2275
  DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
2160
2276
  (int)(zds->outBuffSize - zds->outStart),
2161
2277
  (U32)zds->fParams.blockSizeMax);
@@ -2169,7 +2285,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2169
2285
 
2170
2286
  default:
2171
2287
  assert(0); /* impossible */
2172
- RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
2288
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
2173
2289
  } }
2174
2290
 
2175
2291
  /* result */
@@ -2182,8 +2298,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2182
2298
  if ((ip==istart) && (op==ostart)) { /* no forward progress */
2183
2299
  zds->noForwardProgress ++;
2184
2300
  if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
2185
- RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
2186
- RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
2301
+ RETURN_ERROR_IF(op==oend, noForwardProgress_destFull, "");
2302
+ RETURN_ERROR_IF(ip==iend, noForwardProgress_inputEmpty, "");
2187
2303
  assert(0);
2188
2304
  }
2189
2305
  } else {
@@ -2220,11 +2336,17 @@ size_t ZSTD_decompressStream_simpleArgs (
2220
2336
  void* dst, size_t dstCapacity, size_t* dstPos,
2221
2337
  const void* src, size_t srcSize, size_t* srcPos)
2222
2338
  {
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;
2339
+ ZSTD_outBuffer output;
2340
+ ZSTD_inBuffer input;
2341
+ output.dst = dst;
2342
+ output.size = dstCapacity;
2343
+ output.pos = *dstPos;
2344
+ input.src = src;
2345
+ input.size = srcSize;
2346
+ input.pos = *srcPos;
2347
+ { size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
2348
+ *dstPos = output.pos;
2349
+ *srcPos = input.pos;
2350
+ return cErr;
2351
+ }
2230
2352
  }