zstd-ruby 1.5.2.3 → 1.5.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/ext/zstdruby/libzstd/common/bits.h +175 -0
  4. data/ext/zstdruby/libzstd/common/bitstream.h +18 -59
  5. data/ext/zstdruby/libzstd/common/compiler.h +22 -3
  6. data/ext/zstdruby/libzstd/common/cpu.h +1 -1
  7. data/ext/zstdruby/libzstd/common/debug.c +1 -1
  8. data/ext/zstdruby/libzstd/common/debug.h +1 -1
  9. data/ext/zstdruby/libzstd/common/entropy_common.c +12 -40
  10. data/ext/zstdruby/libzstd/common/error_private.c +9 -2
  11. data/ext/zstdruby/libzstd/common/error_private.h +1 -1
  12. data/ext/zstdruby/libzstd/common/fse.h +5 -83
  13. data/ext/zstdruby/libzstd/common/fse_decompress.c +7 -99
  14. data/ext/zstdruby/libzstd/common/huf.h +65 -156
  15. data/ext/zstdruby/libzstd/common/mem.h +39 -46
  16. data/ext/zstdruby/libzstd/common/pool.c +26 -10
  17. data/ext/zstdruby/libzstd/common/pool.h +7 -1
  18. data/ext/zstdruby/libzstd/common/portability_macros.h +22 -3
  19. data/ext/zstdruby/libzstd/common/threading.c +68 -14
  20. data/ext/zstdruby/libzstd/common/threading.h +5 -10
  21. data/ext/zstdruby/libzstd/common/xxhash.c +2 -2
  22. data/ext/zstdruby/libzstd/common/xxhash.h +8 -8
  23. data/ext/zstdruby/libzstd/common/zstd_common.c +1 -1
  24. data/ext/zstdruby/libzstd/common/zstd_deps.h +1 -1
  25. data/ext/zstdruby/libzstd/common/zstd_internal.h +17 -113
  26. data/ext/zstdruby/libzstd/common/zstd_trace.h +3 -3
  27. data/ext/zstdruby/libzstd/compress/clevels.h +1 -1
  28. data/ext/zstdruby/libzstd/compress/fse_compress.c +7 -124
  29. data/ext/zstdruby/libzstd/compress/hist.c +1 -1
  30. data/ext/zstdruby/libzstd/compress/hist.h +1 -1
  31. data/ext/zstdruby/libzstd/compress/huf_compress.c +234 -169
  32. data/ext/zstdruby/libzstd/compress/zstd_compress.c +1055 -455
  33. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +165 -145
  34. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +115 -39
  35. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +16 -8
  36. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +3 -3
  37. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +1 -1
  38. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +25 -21
  39. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +1 -1
  40. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +5 -3
  41. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +95 -33
  42. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +3 -2
  43. data/ext/zstdruby/libzstd/compress/zstd_fast.c +433 -148
  44. data/ext/zstdruby/libzstd/compress/zstd_fast.h +3 -2
  45. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +306 -283
  46. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +4 -2
  47. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +5 -5
  48. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +1 -1
  49. data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +1 -1
  50. data/ext/zstdruby/libzstd/compress/zstd_opt.c +104 -80
  51. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  52. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +12 -5
  53. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +1 -1
  54. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +434 -441
  55. data/ext/zstdruby/libzstd/decompress/huf_decompress_amd64.S +30 -39
  56. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +3 -4
  57. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +1 -1
  58. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +164 -42
  59. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +186 -65
  60. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +1 -1
  61. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +4 -2
  62. data/ext/zstdruby/libzstd/dictBuilder/cover.c +19 -15
  63. data/ext/zstdruby/libzstd/dictBuilder/cover.h +1 -1
  64. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +2 -2
  65. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +9 -87
  66. data/ext/zstdruby/libzstd/zdict.h +53 -31
  67. data/ext/zstdruby/libzstd/zstd.h +489 -90
  68. data/ext/zstdruby/libzstd/zstd_errors.h +27 -8
  69. data/ext/zstdruby/main.c +4 -0
  70. data/lib/zstd-ruby/version.rb +1 -1
  71. 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
  }