zstd-ruby 1.4.5.0 → 1.4.9.0

Sign up to get free protection for your applications and to get access to all the features.
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
  }