zstd-ruby 1.4.5.0 → 1.4.9.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 (93) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +35 -0
  3. data/README.md +2 -2
  4. data/ext/zstdruby/libzstd/Makefile +237 -138
  5. data/ext/zstdruby/libzstd/README.md +28 -0
  6. data/ext/zstdruby/libzstd/common/bitstream.h +25 -16
  7. data/ext/zstdruby/libzstd/common/compiler.h +118 -4
  8. data/ext/zstdruby/libzstd/common/cpu.h +1 -3
  9. data/ext/zstdruby/libzstd/common/debug.c +1 -1
  10. data/ext/zstdruby/libzstd/common/debug.h +12 -19
  11. data/ext/zstdruby/libzstd/common/entropy_common.c +189 -43
  12. data/ext/zstdruby/libzstd/common/error_private.c +2 -1
  13. data/ext/zstdruby/libzstd/common/error_private.h +2 -2
  14. data/ext/zstdruby/libzstd/common/fse.h +40 -12
  15. data/ext/zstdruby/libzstd/common/fse_decompress.c +124 -17
  16. data/ext/zstdruby/libzstd/common/huf.h +27 -6
  17. data/ext/zstdruby/libzstd/common/mem.h +67 -94
  18. data/ext/zstdruby/libzstd/common/pool.c +23 -17
  19. data/ext/zstdruby/libzstd/common/pool.h +2 -2
  20. data/ext/zstdruby/libzstd/common/threading.c +6 -5
  21. data/ext/zstdruby/libzstd/common/xxhash.c +19 -57
  22. data/ext/zstdruby/libzstd/common/xxhash.h +2 -2
  23. data/ext/zstdruby/libzstd/common/zstd_common.c +10 -10
  24. data/ext/zstdruby/libzstd/common/zstd_deps.h +111 -0
  25. data/ext/zstdruby/libzstd/common/zstd_errors.h +2 -1
  26. data/ext/zstdruby/libzstd/common/zstd_internal.h +90 -59
  27. data/ext/zstdruby/libzstd/common/zstd_trace.c +42 -0
  28. data/ext/zstdruby/libzstd/common/zstd_trace.h +152 -0
  29. data/ext/zstdruby/libzstd/compress/fse_compress.c +31 -24
  30. data/ext/zstdruby/libzstd/compress/hist.c +27 -29
  31. data/ext/zstdruby/libzstd/compress/hist.h +2 -2
  32. data/ext/zstdruby/libzstd/compress/huf_compress.c +217 -101
  33. data/ext/zstdruby/libzstd/compress/zstd_compress.c +1495 -478
  34. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +143 -44
  35. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +7 -7
  36. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +1 -1
  37. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +18 -4
  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 +62 -26
  42. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +23 -23
  43. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +1 -1
  44. data/ext/zstdruby/libzstd/compress/zstd_fast.c +21 -21
  45. data/ext/zstdruby/libzstd/compress/zstd_fast.h +1 -1
  46. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +352 -78
  47. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +21 -1
  48. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +276 -209
  49. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +8 -2
  50. data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +103 -0
  51. data/ext/zstdruby/libzstd/compress/zstd_opt.c +191 -46
  52. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  53. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +79 -410
  54. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +27 -109
  55. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +303 -201
  56. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +9 -9
  57. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +2 -2
  58. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +370 -87
  59. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +153 -45
  60. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +6 -3
  61. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +28 -11
  62. data/ext/zstdruby/libzstd/deprecated/zbuff.h +1 -1
  63. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +1 -1
  64. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -1
  65. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
  66. data/ext/zstdruby/libzstd/dictBuilder/cover.c +40 -31
  67. data/ext/zstdruby/libzstd/dictBuilder/cover.h +2 -2
  68. data/ext/zstdruby/libzstd/dictBuilder/divsufsort.c +1 -1
  69. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +26 -25
  70. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +22 -24
  71. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +5 -4
  72. data/ext/zstdruby/libzstd/dll/example/Makefile +1 -1
  73. data/ext/zstdruby/libzstd/dll/example/README.md +16 -22
  74. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +1 -1
  75. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +6 -2
  76. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +1 -1
  77. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +6 -2
  78. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +1 -1
  79. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +6 -2
  80. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +1 -1
  81. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +7 -3
  82. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +1 -1
  83. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +10 -6
  84. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +1 -1
  85. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +10 -6
  86. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +1 -1
  87. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +10 -6
  88. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +1 -1
  89. data/ext/zstdruby/libzstd/libzstd.pc.in +3 -3
  90. data/ext/zstdruby/libzstd/zstd.h +414 -54
  91. data/lib/zstd-ruby/version.rb +1 -1
  92. metadata +7 -3
  93. data/.travis.yml +0 -14
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2021, Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -50,6 +50,19 @@ static unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) {
50
50
  return maxSymbolValue;
51
51
  }
52
52
 
53
+ /**
54
+ * Returns true if we should use ncount=-1 else we should
55
+ * use ncount=1 for low probability symbols instead.
56
+ */
57
+ static unsigned ZSTD_useLowProbCount(size_t const nbSeq)
58
+ {
59
+ /* Heuristic: This should cover most blocks <= 16K and
60
+ * start to fade out after 16K to about 32K depending on
61
+ * comprssibility.
62
+ */
63
+ return nbSeq >= 2048;
64
+ }
65
+
53
66
  /**
54
67
  * Returns the cost in bytes of encoding the normalized count header.
55
68
  * Returns an error if any of the helper functions return an error.
@@ -60,7 +73,7 @@ static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max,
60
73
  BYTE wksp[FSE_NCOUNTBOUND];
61
74
  S16 norm[MaxSeq + 1];
62
75
  const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
63
- FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max), "");
76
+ FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max, ZSTD_useLowProbCount(nbSeq)), "");
64
77
  return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog);
65
78
  }
66
79
 
@@ -239,7 +252,7 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity,
239
252
  *op = codeTable[0];
240
253
  return 1;
241
254
  case set_repeat:
242
- memcpy(nextCTable, prevCTable, prevCTableSize);
255
+ ZSTD_memcpy(nextCTable, prevCTable, prevCTableSize);
243
256
  return 0;
244
257
  case set_basic:
245
258
  FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, entropyWorkspace, entropyWorkspaceSize), ""); /* note : could be pre-calculated */
@@ -253,7 +266,8 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity,
253
266
  nbSeq_1--;
254
267
  }
255
268
  assert(nbSeq_1 > 1);
256
- FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max), "");
269
+ assert(entropyWorkspaceSize >= FSE_BUILD_CTABLE_WORKSPACE_SIZE(MaxSeq, MaxFSELog));
270
+ FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max, ZSTD_useLowProbCount(nbSeq_1)), "");
257
271
  { size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
258
272
  FORWARD_IF_ERROR(NCountSize, "FSE_writeNCount failed");
259
273
  FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, entropyWorkspace, entropyWorkspaceSize), "");
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2021, Yann Collet, Facebook, Inc.
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) 2016-2020, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2021, Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -29,7 +29,7 @@
29
29
  * This metadata is populated in ZSTD_buildSuperBlockEntropy_literal() */
30
30
  typedef struct {
31
31
  symbolEncodingType_e hType;
32
- BYTE hufDesBuffer[500]; /* TODO give name to this value */
32
+ BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE];
33
33
  size_t hufDesSize;
34
34
  } ZSTD_hufCTablesMetadata_t;
35
35
 
@@ -42,7 +42,7 @@ typedef struct {
42
42
  symbolEncodingType_e llType;
43
43
  symbolEncodingType_e ofType;
44
44
  symbolEncodingType_e mlType;
45
- BYTE fseTablesBuffer[500]; /* TODO give name to this value */
45
+ BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE];
46
46
  size_t fseTablesSize;
47
47
  size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_compressSubBlock_sequences() */
48
48
  } ZSTD_fseCTablesMetadata_t;
@@ -79,7 +79,7 @@ static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSiz
79
79
  DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_literal (srcSize=%zu)", srcSize);
80
80
 
81
81
  /* Prepare nextEntropy assuming reusing the existing table */
82
- memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
82
+ ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
83
83
 
84
84
  if (disableLiteralsCompression) {
85
85
  DEBUGLOG(5, "set_basic - disabled");
@@ -118,7 +118,7 @@ static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSiz
118
118
  }
119
119
 
120
120
  /* Build Huffman Tree */
121
- memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable));
121
+ ZSTD_memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable));
122
122
  huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
123
123
  { size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp,
124
124
  maxSymbolValue, huffLog,
@@ -137,14 +137,14 @@ static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSiz
137
137
  (HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue);
138
138
  if (oldCSize < srcSize && (oldCSize <= hSize + newCSize || hSize + 12 >= srcSize)) {
139
139
  DEBUGLOG(5, "set_repeat - smaller");
140
- memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
140
+ ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
141
141
  hufMetadata->hType = set_repeat;
142
142
  return 0;
143
143
  }
144
144
  }
145
145
  if (newCSize + hSize >= srcSize) {
146
146
  DEBUGLOG(5, "set_basic - no gains");
147
- memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
147
+ ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
148
148
  hufMetadata->hType = set_basic;
149
149
  return 0;
150
150
  }
@@ -188,7 +188,7 @@ static size_t ZSTD_buildSuperBlockEntropy_sequences(seqStore_t* seqStorePtr,
188
188
 
189
189
  assert(cTableWkspSize >= (1 << MaxFSELog) * sizeof(FSE_FUNCTION_TYPE));
190
190
  DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_sequences (nbSeq=%zu)", nbSeq);
191
- memset(workspace, 0, wkspSize);
191
+ ZSTD_memset(workspace, 0, wkspSize);
192
192
 
193
193
  fseMetadata->lastCountSize = 0;
194
194
  /* convert length/distances into codes */
@@ -304,7 +304,7 @@ ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr,
304
304
  * before we know the table size + compressed size, so we have a bound on the
305
305
  * table size. If we guessed incorrectly, we fall back to uncompressed literals.
306
306
  *
307
- * We write the header when writeEntropy=1 and set entropyWrriten=1 when we succeeded
307
+ * We write the header when writeEntropy=1 and set entropyWritten=1 when we succeeded
308
308
  * in writing the header, otherwise it is set to 0.
309
309
  *
310
310
  * hufMetadata->hType has literals block type info.
@@ -348,7 +348,7 @@ static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
348
348
  assert(hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat);
349
349
 
350
350
  if (writeEntropy && hufMetadata->hType == set_compressed) {
351
- memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize);
351
+ ZSTD_memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize);
352
352
  op += hufMetadata->hufDesSize;
353
353
  cLitSize += hufMetadata->hufDesSize;
354
354
  DEBUGLOG(5, "ZSTD_compressSubBlock_literal (hSize=%zu)", hufMetadata->hufDesSize);
@@ -474,7 +474,7 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables
474
474
  const U32 MLtype = fseMetadata->mlType;
475
475
  DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (fseTablesSize=%zu)", fseMetadata->fseTablesSize);
476
476
  *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
477
- memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize);
477
+ ZSTD_memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize);
478
478
  op += fseMetadata->fseTablesSize;
479
479
  } else {
480
480
  const U32 repeat = set_repeat;
@@ -603,7 +603,7 @@ static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type,
603
603
  const BYTE* codeTable, unsigned maxCode,
604
604
  size_t nbSeq, const FSE_CTable* fseCTable,
605
605
  const U32* additionalBits,
606
- short const* defaultNorm, U32 defaultNormLog,
606
+ short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
607
607
  void* workspace, size_t wkspSize)
608
608
  {
609
609
  unsigned* const countWksp = (unsigned*)workspace;
@@ -615,7 +615,11 @@ static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type,
615
615
 
616
616
  HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize); /* can't fail */
617
617
  if (type == set_basic) {
618
- cSymbolTypeSizeEstimateInBits = ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max);
618
+ /* We selected this encoding type, so it must be valid. */
619
+ assert(max <= defaultMax);
620
+ cSymbolTypeSizeEstimateInBits = max <= defaultMax
621
+ ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max)
622
+ : ERROR(GENERIC);
619
623
  } else if (type == set_rle) {
620
624
  cSymbolTypeSizeEstimateInBits = 0;
621
625
  } else if (type == set_compressed || type == set_repeat) {
@@ -643,15 +647,15 @@ static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable,
643
647
  size_t cSeqSizeEstimate = 0;
644
648
  cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff,
645
649
  nbSeq, fseTables->offcodeCTable, NULL,
646
- OF_defaultNorm, OF_defaultNormLog,
650
+ OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
647
651
  workspace, wkspSize);
648
652
  cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->llType, llCodeTable, MaxLL,
649
653
  nbSeq, fseTables->litlengthCTable, LL_bits,
650
- LL_defaultNorm, LL_defaultNormLog,
654
+ LL_defaultNorm, LL_defaultNormLog, MaxLL,
651
655
  workspace, wkspSize);
652
656
  cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, MaxML,
653
657
  nbSeq, fseTables->matchlengthCTable, ML_bits,
654
- ML_defaultNorm, ML_defaultNormLog,
658
+ ML_defaultNorm, ML_defaultNormLog, MaxML,
655
659
  workspace, wkspSize);
656
660
  if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize;
657
661
  return cSeqSizeEstimate + sequencesSectionHeaderSize;
@@ -790,7 +794,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
790
794
  } while (!lastSequence);
791
795
  if (writeLitEntropy) {
792
796
  DEBUGLOG(5, "ZSTD_compressSubBlock_multi has literal entropy tables unwritten");
793
- memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf));
797
+ ZSTD_memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf));
794
798
  }
795
799
  if (writeSeqEntropy && ZSTD_needSequenceEntropyTables(&entropyMetadata->fseMetadata)) {
796
800
  /* If we haven't written our entropy tables, then we've violated our contract and
@@ -809,11 +813,11 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
809
813
  if (sp < send) {
810
814
  seqDef const* seq;
811
815
  repcodes_t rep;
812
- memcpy(&rep, prevCBlock->rep, sizeof(rep));
816
+ ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep));
813
817
  for (seq = sstart; seq < sp; ++seq) {
814
818
  rep = ZSTD_updateRep(rep.rep, seq->offset - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);
815
819
  }
816
- memcpy(nextCBlock->rep, &rep, sizeof(rep));
820
+ ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep));
817
821
  }
818
822
  }
819
823
  DEBUGLOG(5, "ZSTD_compressSubBlock_multi compressed");
@@ -831,7 +835,7 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,
831
835
  &zc->blockState.nextCBlock->entropy,
832
836
  &zc->appliedParams,
833
837
  &entropyMetadata,
834
- zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */), "");
838
+ zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */), "");
835
839
 
836
840
  return ZSTD_compressSubBlock_multi(&zc->seqStore,
837
841
  zc->blockState.prevCBlock,
@@ -841,5 +845,5 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,
841
845
  dst, dstCapacity,
842
846
  src, srcSize,
843
847
  zc->bmi2, lastBlock,
844
- zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */);
848
+ zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */);
845
849
  }
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2021, Yann Collet, Facebook, Inc.
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) 2016-2020, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2021, Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -44,6 +44,16 @@ typedef enum {
44
44
  ZSTD_cwksp_alloc_aligned
45
45
  } ZSTD_cwksp_alloc_phase_e;
46
46
 
47
+ /**
48
+ * Used to describe whether the workspace is statically allocated (and will not
49
+ * necessarily ever be freed), or if it's dynamically allocated and we can
50
+ * expect a well-formed caller to free this.
51
+ */
52
+ typedef enum {
53
+ ZSTD_cwksp_dynamic_alloc,
54
+ ZSTD_cwksp_static_alloc
55
+ } ZSTD_cwksp_static_alloc_e;
56
+
47
57
  /**
48
58
  * Zstd fits all its internal datastructures into a single continuous buffer,
49
59
  * so that it only needs to perform a single OS allocation (or so that a buffer
@@ -92,7 +102,7 @@ typedef enum {
92
102
  *
93
103
  * - Static objects: this is optionally the enclosing ZSTD_CCtx or ZSTD_CDict,
94
104
  * so that literally everything fits in a single buffer. Note: if present,
95
- * this must be the first object in the workspace, since ZSTD_free{CCtx,
105
+ * this must be the first object in the workspace, since ZSTD_customFree{CCtx,
96
106
  * CDict}() rely on a pointer comparison to see whether one or two frees are
97
107
  * required.
98
108
  *
@@ -137,9 +147,10 @@ typedef struct {
137
147
  void* tableValidEnd;
138
148
  void* allocStart;
139
149
 
140
- int allocFailed;
150
+ BYTE allocFailed;
141
151
  int workspaceOversizedDuration;
142
152
  ZSTD_cwksp_alloc_phase_e phase;
153
+ ZSTD_cwksp_static_alloc_e isStatic;
143
154
  } ZSTD_cwksp;
144
155
 
145
156
  /*-*************************************
@@ -178,7 +189,9 @@ MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t const align) {
178
189
  * else is though.
179
190
  */
180
191
  MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) {
181
- #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
192
+ if (size == 0)
193
+ return 0;
194
+ #if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
182
195
  return size + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
183
196
  #else
184
197
  return size;
@@ -228,7 +241,10 @@ MEM_STATIC void* ZSTD_cwksp_reserve_internal(
228
241
  ZSTD_cwksp_internal_advance_phase(ws, phase);
229
242
  alloc = (BYTE *)ws->allocStart - bytes;
230
243
 
231
- #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
244
+ if (bytes == 0)
245
+ return NULL;
246
+
247
+ #if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
232
248
  /* over-reserve space */
233
249
  alloc = (BYTE *)alloc - 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
234
250
  #endif
@@ -247,11 +263,13 @@ MEM_STATIC void* ZSTD_cwksp_reserve_internal(
247
263
  }
248
264
  ws->allocStart = alloc;
249
265
 
250
- #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
266
+ #if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
251
267
  /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on
252
268
  * either size. */
253
269
  alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
254
- __asan_unpoison_memory_region(alloc, bytes);
270
+ if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
271
+ __asan_unpoison_memory_region(alloc, bytes);
272
+ }
255
273
  #endif
256
274
 
257
275
  return alloc;
@@ -296,8 +314,10 @@ MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) {
296
314
  }
297
315
  ws->tableEnd = end;
298
316
 
299
- #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
300
- __asan_unpoison_memory_region(alloc, bytes);
317
+ #if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
318
+ if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
319
+ __asan_unpoison_memory_region(alloc, bytes);
320
+ }
301
321
  #endif
302
322
 
303
323
  return alloc;
@@ -311,7 +331,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
311
331
  void* alloc = ws->objectEnd;
312
332
  void* end = (BYTE*)alloc + roundedBytes;
313
333
 
314
- #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
334
+ #if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
315
335
  /* over-reserve space */
316
336
  end = (BYTE *)end + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
317
337
  #endif
@@ -332,11 +352,13 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
332
352
  ws->tableEnd = end;
333
353
  ws->tableValidEnd = end;
334
354
 
335
- #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
355
+ #if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
336
356
  /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on
337
357
  * either size. */
338
358
  alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
339
- __asan_unpoison_memory_region(alloc, bytes);
359
+ if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
360
+ __asan_unpoison_memory_region(alloc, bytes);
361
+ }
340
362
  #endif
341
363
 
342
364
  return alloc;
@@ -345,7 +367,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
345
367
  MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws) {
346
368
  DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_dirty");
347
369
 
348
- #if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
370
+ #if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
349
371
  /* To validate that the table re-use logic is sound, and that we don't
350
372
  * access table space that we haven't cleaned, we re-"poison" the table
351
373
  * space every time we mark it dirty. */
@@ -380,7 +402,7 @@ MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) {
380
402
  assert(ws->tableValidEnd >= ws->objectEnd);
381
403
  assert(ws->tableValidEnd <= ws->allocStart);
382
404
  if (ws->tableValidEnd < ws->tableEnd) {
383
- memset(ws->tableValidEnd, 0, (BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd);
405
+ ZSTD_memset(ws->tableValidEnd, 0, (BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd);
384
406
  }
385
407
  ZSTD_cwksp_mark_tables_clean(ws);
386
408
  }
@@ -392,8 +414,12 @@ MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) {
392
414
  MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) {
393
415
  DEBUGLOG(4, "cwksp: clearing tables!");
394
416
 
395
- #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
396
- {
417
+ #if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
418
+ /* We don't do this when the workspace is statically allocated, because
419
+ * when that is the case, we have no capability to hook into the end of the
420
+ * workspace's lifecycle to unpoison the memory.
421
+ */
422
+ if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
397
423
  size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd;
398
424
  __asan_poison_memory_region(ws->objectEnd, size);
399
425
  }
@@ -410,7 +436,7 @@ MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) {
410
436
  MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) {
411
437
  DEBUGLOG(4, "cwksp: clearing!");
412
438
 
413
- #if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
439
+ #if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
414
440
  /* To validate that the context re-use logic is sound, and that we don't
415
441
  * access stuff that this compression hasn't initialized, we re-"poison"
416
442
  * the workspace (or at least the non-static, non-table parts of it)
@@ -421,8 +447,12 @@ MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) {
421
447
  }
422
448
  #endif
423
449
 
424
- #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
425
- {
450
+ #if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
451
+ /* We don't do this when the workspace is statically allocated, because
452
+ * when that is the case, we have no capability to hook into the end of the
453
+ * workspace's lifecycle to unpoison the memory.
454
+ */
455
+ if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
426
456
  size_t size = (BYTE*)ws->workspaceEnd - (BYTE*)ws->objectEnd;
427
457
  __asan_poison_memory_region(ws->objectEnd, size);
428
458
  }
@@ -442,7 +472,7 @@ MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) {
442
472
  * Any existing values in the workspace are ignored (the previously managed
443
473
  * buffer, if present, must be separately freed).
444
474
  */
445
- MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size) {
475
+ MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size, ZSTD_cwksp_static_alloc_e isStatic) {
446
476
  DEBUGLOG(4, "cwksp: init'ing workspace with %zd bytes", size);
447
477
  assert(((size_t)start & (sizeof(void*)-1)) == 0); /* ensure correct alignment */
448
478
  ws->workspace = start;
@@ -450,39 +480,45 @@ MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size) {
450
480
  ws->objectEnd = ws->workspace;
451
481
  ws->tableValidEnd = ws->objectEnd;
452
482
  ws->phase = ZSTD_cwksp_alloc_objects;
483
+ ws->isStatic = isStatic;
453
484
  ZSTD_cwksp_clear(ws);
454
485
  ws->workspaceOversizedDuration = 0;
455
486
  ZSTD_cwksp_assert_internal_consistency(ws);
456
487
  }
457
488
 
458
489
  MEM_STATIC size_t ZSTD_cwksp_create(ZSTD_cwksp* ws, size_t size, ZSTD_customMem customMem) {
459
- void* workspace = ZSTD_malloc(size, customMem);
490
+ void* workspace = ZSTD_customMalloc(size, customMem);
460
491
  DEBUGLOG(4, "cwksp: creating new workspace with %zd bytes", size);
461
492
  RETURN_ERROR_IF(workspace == NULL, memory_allocation, "NULL pointer!");
462
- ZSTD_cwksp_init(ws, workspace, size);
493
+ ZSTD_cwksp_init(ws, workspace, size, ZSTD_cwksp_dynamic_alloc);
463
494
  return 0;
464
495
  }
465
496
 
466
497
  MEM_STATIC void ZSTD_cwksp_free(ZSTD_cwksp* ws, ZSTD_customMem customMem) {
467
498
  void *ptr = ws->workspace;
468
499
  DEBUGLOG(4, "cwksp: freeing workspace");
469
- memset(ws, 0, sizeof(ZSTD_cwksp));
470
- ZSTD_free(ptr, customMem);
500
+ ZSTD_memset(ws, 0, sizeof(ZSTD_cwksp));
501
+ ZSTD_customFree(ptr, customMem);
471
502
  }
472
503
 
473
504
  /**
474
505
  * Moves the management of a workspace from one cwksp to another. The src cwksp
475
- * is left in an invalid state (src must be re-init()'ed before its used again).
506
+ * is left in an invalid state (src must be re-init()'ed before it's used again).
476
507
  */
477
508
  MEM_STATIC void ZSTD_cwksp_move(ZSTD_cwksp* dst, ZSTD_cwksp* src) {
478
509
  *dst = *src;
479
- memset(src, 0, sizeof(ZSTD_cwksp));
510
+ ZSTD_memset(src, 0, sizeof(ZSTD_cwksp));
480
511
  }
481
512
 
482
513
  MEM_STATIC size_t ZSTD_cwksp_sizeof(const ZSTD_cwksp* ws) {
483
514
  return (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->workspace);
484
515
  }
485
516
 
517
+ MEM_STATIC size_t ZSTD_cwksp_used(const ZSTD_cwksp* ws) {
518
+ return (size_t)((BYTE*)ws->tableEnd - (BYTE*)ws->workspace)
519
+ + (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->allocStart);
520
+ }
521
+
486
522
  MEM_STATIC int ZSTD_cwksp_reserve_failed(const ZSTD_cwksp* ws) {
487
523
  return ws->allocFailed;
488
524
  }