multi_compress 0.3.1 → 0.3.3

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 (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -3
  3. data/GET_STARTED.md +3 -3
  4. data/README.md +75 -66
  5. data/THIRD_PARTY_NOTICES.md +24 -0
  6. data/ext/multi_compress/brotli_dec_static_init.c +3 -0
  7. data/ext/multi_compress/brotli_enc_static_init.c +3 -0
  8. data/ext/multi_compress/extconf.rb +22 -1
  9. data/ext/multi_compress/multi_compress.c +152 -72
  10. data/ext/multi_compress/vendor/.vendored +2 -2
  11. data/ext/multi_compress/vendor/brotli/LICENSE +19 -0
  12. data/ext/multi_compress/vendor/brotli/c/common/constants.c +7 -7
  13. data/ext/multi_compress/vendor/brotli/c/common/constants.h +2 -5
  14. data/ext/multi_compress/vendor/brotli/c/common/context.c +2 -2
  15. data/ext/multi_compress/vendor/brotli/c/common/context.h +1 -2
  16. data/ext/multi_compress/vendor/brotli/c/common/dictionary.c +4 -5856
  17. data/ext/multi_compress/vendor/brotli/c/common/dictionary.h +1 -2
  18. data/ext/multi_compress/vendor/brotli/c/common/dictionary_inc.h +5847 -0
  19. data/ext/multi_compress/vendor/brotli/c/common/platform.c +0 -4
  20. data/ext/multi_compress/vendor/brotli/c/common/platform.h +182 -43
  21. data/ext/multi_compress/vendor/brotli/c/common/shared_dictionary.c +3 -7
  22. data/ext/multi_compress/vendor/brotli/c/common/shared_dictionary_internal.h +1 -1
  23. data/ext/multi_compress/vendor/brotli/c/common/static_init.h +56 -0
  24. data/ext/multi_compress/vendor/brotli/c/common/transform.c +6 -4
  25. data/ext/multi_compress/vendor/brotli/c/common/transform.h +1 -2
  26. data/ext/multi_compress/vendor/brotli/c/common/version.h +3 -3
  27. data/ext/multi_compress/vendor/brotli/c/dec/bit_reader.c +2 -3
  28. data/ext/multi_compress/vendor/brotli/c/dec/bit_reader.h +0 -4
  29. data/ext/multi_compress/vendor/brotli/c/dec/decode.c +128 -39
  30. data/ext/multi_compress/vendor/brotli/c/dec/huffman.c +2 -5
  31. data/ext/multi_compress/vendor/brotli/c/dec/huffman.h +0 -2
  32. data/ext/multi_compress/vendor/brotli/c/dec/prefix.c +67 -0
  33. data/ext/multi_compress/vendor/brotli/c/dec/prefix.h +18 -708
  34. data/ext/multi_compress/vendor/brotli/c/dec/prefix_inc.h +707 -0
  35. data/ext/multi_compress/vendor/brotli/c/dec/state.c +18 -15
  36. data/ext/multi_compress/vendor/brotli/c/dec/state.h +2 -6
  37. data/ext/multi_compress/vendor/brotli/c/dec/static_init.c +53 -0
  38. data/ext/multi_compress/vendor/brotli/c/dec/static_init.h +30 -0
  39. data/ext/multi_compress/vendor/brotli/c/enc/backward_references.c +32 -8
  40. data/ext/multi_compress/vendor/brotli/c/enc/backward_references.h +1 -5
  41. data/ext/multi_compress/vendor/brotli/c/enc/backward_references_hq.c +15 -15
  42. data/ext/multi_compress/vendor/brotli/c/enc/backward_references_hq.h +1 -5
  43. data/ext/multi_compress/vendor/brotli/c/enc/bit_cost.c +28 -4
  44. data/ext/multi_compress/vendor/brotli/c/enc/bit_cost.h +8 -40
  45. data/ext/multi_compress/vendor/brotli/c/enc/bit_cost_inc.h +1 -1
  46. data/ext/multi_compress/vendor/brotli/c/enc/block_splitter.c +9 -12
  47. data/ext/multi_compress/vendor/brotli/c/enc/block_splitter.h +0 -3
  48. data/ext/multi_compress/vendor/brotli/c/enc/block_splitter_inc.h +14 -8
  49. data/ext/multi_compress/vendor/brotli/c/enc/brotli_bit_stream.c +10 -9
  50. data/ext/multi_compress/vendor/brotli/c/enc/brotli_bit_stream.h +0 -6
  51. data/ext/multi_compress/vendor/brotli/c/enc/cluster.c +0 -2
  52. data/ext/multi_compress/vendor/brotli/c/enc/cluster.h +0 -2
  53. data/ext/multi_compress/vendor/brotli/c/enc/command.c +1 -1
  54. data/ext/multi_compress/vendor/brotli/c/enc/command.h +8 -10
  55. data/ext/multi_compress/vendor/brotli/c/enc/compound_dictionary.c +3 -5
  56. data/ext/multi_compress/vendor/brotli/c/enc/compound_dictionary.h +1 -4
  57. data/ext/multi_compress/vendor/brotli/c/enc/compress_fragment.c +3 -13
  58. data/ext/multi_compress/vendor/brotli/c/enc/compress_fragment.h +0 -2
  59. data/ext/multi_compress/vendor/brotli/c/enc/compress_fragment_two_pass.c +5 -15
  60. data/ext/multi_compress/vendor/brotli/c/enc/compress_fragment_two_pass.h +0 -2
  61. data/ext/multi_compress/vendor/brotli/c/enc/dictionary_hash.c +127 -1830
  62. data/ext/multi_compress/vendor/brotli/c/enc/dictionary_hash.h +23 -3
  63. data/ext/multi_compress/vendor/brotli/c/enc/dictionary_hash_inc.h +1829 -0
  64. data/ext/multi_compress/vendor/brotli/c/enc/encode.c +77 -52
  65. data/ext/multi_compress/vendor/brotli/c/enc/encoder_dict.c +9 -7
  66. data/ext/multi_compress/vendor/brotli/c/enc/encoder_dict.h +2 -4
  67. data/ext/multi_compress/vendor/brotli/c/enc/entropy_encode.c +3 -6
  68. data/ext/multi_compress/vendor/brotli/c/enc/entropy_encode.h +2 -4
  69. data/ext/multi_compress/vendor/brotli/c/enc/entropy_encode_static.h +18 -12
  70. data/ext/multi_compress/vendor/brotli/c/enc/fast_log.c +1 -1
  71. data/ext/multi_compress/vendor/brotli/c/enc/fast_log.h +2 -3
  72. data/ext/multi_compress/vendor/brotli/c/enc/find_match_length.h +0 -2
  73. data/ext/multi_compress/vendor/brotli/c/enc/hash.h +38 -31
  74. data/ext/multi_compress/vendor/brotli/c/enc/hash_base.h +38 -0
  75. data/ext/multi_compress/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +11 -1
  76. data/ext/multi_compress/vendor/brotli/c/enc/hash_longest_match64_inc.h +24 -7
  77. data/ext/multi_compress/vendor/brotli/c/enc/hash_longest_match64_simd_inc.h +304 -0
  78. data/ext/multi_compress/vendor/brotli/c/enc/hash_longest_match_inc.h +30 -11
  79. data/ext/multi_compress/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +4 -0
  80. data/ext/multi_compress/vendor/brotli/c/enc/hash_longest_match_simd_inc.h +278 -0
  81. data/ext/multi_compress/vendor/brotli/c/enc/histogram.c +1 -0
  82. data/ext/multi_compress/vendor/brotli/c/enc/histogram.h +0 -4
  83. data/ext/multi_compress/vendor/brotli/c/enc/literal_cost.c +4 -6
  84. data/ext/multi_compress/vendor/brotli/c/enc/literal_cost.h +0 -2
  85. data/ext/multi_compress/vendor/brotli/c/enc/matching_tag_mask.h +69 -0
  86. data/ext/multi_compress/vendor/brotli/c/enc/memory.c +0 -5
  87. data/ext/multi_compress/vendor/brotli/c/enc/memory.h +0 -4
  88. data/ext/multi_compress/vendor/brotli/c/enc/metablock.c +7 -9
  89. data/ext/multi_compress/vendor/brotli/c/enc/metablock.h +3 -3
  90. data/ext/multi_compress/vendor/brotli/c/enc/metablock_inc.h +4 -4
  91. data/ext/multi_compress/vendor/brotli/c/enc/params.h +0 -1
  92. data/ext/multi_compress/vendor/brotli/c/enc/prefix.h +0 -2
  93. data/ext/multi_compress/vendor/brotli/c/enc/quality.h +17 -10
  94. data/ext/multi_compress/vendor/brotli/c/enc/ringbuffer.h +1 -4
  95. data/ext/multi_compress/vendor/brotli/c/enc/state.h +2 -2
  96. data/ext/multi_compress/vendor/brotli/c/enc/static_dict.c +5 -11
  97. data/ext/multi_compress/vendor/brotli/c/enc/static_dict.h +1 -3
  98. data/ext/multi_compress/vendor/brotli/c/enc/static_dict_lut.c +224 -0
  99. data/ext/multi_compress/vendor/brotli/c/enc/static_dict_lut.h +20 -5837
  100. data/ext/multi_compress/vendor/brotli/c/enc/static_dict_lut_inc.h +5830 -0
  101. data/ext/multi_compress/vendor/brotli/c/enc/static_init.c +59 -0
  102. data/ext/multi_compress/vendor/brotli/c/enc/static_init.h +30 -0
  103. data/ext/multi_compress/vendor/brotli/c/enc/static_init_lazy.cc +26 -0
  104. data/ext/multi_compress/vendor/brotli/c/enc/utf8_util.c +1 -1
  105. data/ext/multi_compress/vendor/brotli/c/enc/utf8_util.h +0 -2
  106. data/ext/multi_compress/vendor/brotli/c/enc/write_bits.h +0 -2
  107. data/ext/multi_compress/vendor/brotli/c/include/brotli/decode.h +1 -1
  108. data/ext/multi_compress/vendor/brotli/c/include/brotli/encode.h +5 -1
  109. data/ext/multi_compress/vendor/brotli/c/include/brotli/port.h +4 -7
  110. data/ext/multi_compress/vendor/brotli/c/include/brotli/types.h +2 -2
  111. data/ext/multi_compress/vendor/lz4/LICENSE +12 -0
  112. data/ext/multi_compress/vendor/zstd/COPYING +339 -0
  113. data/ext/multi_compress/vendor/zstd/LICENSE +30 -0
  114. data/ext/multi_compress/vendor/zstd/lib/Makefile +67 -35
  115. data/ext/multi_compress/vendor/zstd/lib/README.md +33 -2
  116. data/ext/multi_compress/vendor/zstd/lib/common/allocations.h +55 -0
  117. data/ext/multi_compress/vendor/zstd/lib/common/bits.h +205 -0
  118. data/ext/multi_compress/vendor/zstd/lib/common/bitstream.h +84 -108
  119. data/ext/multi_compress/vendor/zstd/lib/common/compiler.h +170 -41
  120. data/ext/multi_compress/vendor/zstd/lib/common/cpu.h +37 -1
  121. data/ext/multi_compress/vendor/zstd/lib/common/debug.c +7 -1
  122. data/ext/multi_compress/vendor/zstd/lib/common/debug.h +21 -21
  123. data/ext/multi_compress/vendor/zstd/lib/common/entropy_common.c +12 -40
  124. data/ext/multi_compress/vendor/zstd/lib/common/error_private.c +10 -2
  125. data/ext/multi_compress/vendor/zstd/lib/common/error_private.h +46 -47
  126. data/ext/multi_compress/vendor/zstd/lib/common/fse.h +8 -100
  127. data/ext/multi_compress/vendor/zstd/lib/common/fse_decompress.c +28 -116
  128. data/ext/multi_compress/vendor/zstd/lib/common/huf.h +79 -166
  129. data/ext/multi_compress/vendor/zstd/lib/common/mem.h +46 -66
  130. data/ext/multi_compress/vendor/zstd/lib/common/pool.c +27 -11
  131. data/ext/multi_compress/vendor/zstd/lib/common/pool.h +8 -11
  132. data/ext/multi_compress/vendor/zstd/lib/common/portability_macros.h +45 -11
  133. data/ext/multi_compress/vendor/zstd/lib/common/threading.c +74 -14
  134. data/ext/multi_compress/vendor/zstd/lib/common/threading.h +5 -18
  135. data/ext/multi_compress/vendor/zstd/lib/common/xxhash.c +5 -11
  136. data/ext/multi_compress/vendor/zstd/lib/common/xxhash.h +2411 -1003
  137. data/ext/multi_compress/vendor/zstd/lib/common/zstd_common.c +1 -36
  138. data/ext/multi_compress/vendor/zstd/lib/common/zstd_deps.h +13 -1
  139. data/ext/multi_compress/vendor/zstd/lib/common/zstd_internal.h +13 -182
  140. data/ext/multi_compress/vendor/zstd/lib/common/zstd_trace.h +6 -13
  141. data/ext/multi_compress/vendor/zstd/lib/compress/clevels.h +1 -1
  142. data/ext/multi_compress/vendor/zstd/lib/compress/fse_compress.c +15 -131
  143. data/ext/multi_compress/vendor/zstd/lib/compress/hist.c +11 -1
  144. data/ext/multi_compress/vendor/zstd/lib/compress/hist.h +8 -1
  145. data/ext/multi_compress/vendor/zstd/lib/compress/huf_compress.c +283 -189
  146. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_compress.c +2419 -903
  147. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_compress_internal.h +423 -245
  148. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_compress_literals.c +116 -40
  149. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_compress_literals.h +16 -8
  150. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_compress_sequences.c +10 -10
  151. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_compress_sequences.h +8 -7
  152. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_compress_superblock.c +254 -139
  153. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_compress_superblock.h +1 -1
  154. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_cwksp.h +184 -95
  155. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_double_fast.c +163 -81
  156. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_double_fast.h +18 -14
  157. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_fast.c +507 -197
  158. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_fast.h +7 -14
  159. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_lazy.c +579 -484
  160. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_lazy.h +133 -65
  161. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_ldm.c +61 -40
  162. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_ldm.h +7 -15
  163. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_ldm_geartab.h +1 -1
  164. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_opt.c +352 -218
  165. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_opt.h +37 -21
  166. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_preSplit.c +238 -0
  167. data/ext/multi_compress/vendor/zstd/lib/compress/zstd_preSplit.h +33 -0
  168. data/ext/multi_compress/vendor/zstd/lib/compress/zstdmt_compress.c +239 -175
  169. data/ext/multi_compress/vendor/zstd/lib/compress/zstdmt_compress.h +5 -16
  170. data/ext/multi_compress/vendor/zstd/lib/decompress/huf_decompress.c +543 -488
  171. data/ext/multi_compress/vendor/zstd/lib/decompress/huf_decompress_amd64.S +78 -61
  172. data/ext/multi_compress/vendor/zstd/lib/decompress/zstd_ddict.c +4 -4
  173. data/ext/multi_compress/vendor/zstd/lib/decompress/zstd_ddict.h +1 -1
  174. data/ext/multi_compress/vendor/zstd/lib/decompress/zstd_decompress.c +295 -115
  175. data/ext/multi_compress/vendor/zstd/lib/decompress/zstd_decompress_block.c +430 -293
  176. data/ext/multi_compress/vendor/zstd/lib/decompress/zstd_decompress_block.h +7 -2
  177. data/ext/multi_compress/vendor/zstd/lib/decompress/zstd_decompress_internal.h +11 -7
  178. data/ext/multi_compress/vendor/zstd/lib/deprecated/zbuff.h +1 -1
  179. data/ext/multi_compress/vendor/zstd/lib/deprecated/zbuff_common.c +1 -1
  180. data/ext/multi_compress/vendor/zstd/lib/deprecated/zbuff_compress.c +1 -1
  181. data/ext/multi_compress/vendor/zstd/lib/deprecated/zbuff_decompress.c +3 -1
  182. data/ext/multi_compress/vendor/zstd/lib/dictBuilder/cover.c +95 -46
  183. data/ext/multi_compress/vendor/zstd/lib/dictBuilder/cover.h +3 -9
  184. data/ext/multi_compress/vendor/zstd/lib/dictBuilder/divsufsort.h +0 -10
  185. data/ext/multi_compress/vendor/zstd/lib/dictBuilder/fastcover.c +4 -4
  186. data/ext/multi_compress/vendor/zstd/lib/dictBuilder/zdict.c +25 -97
  187. data/ext/multi_compress/vendor/zstd/lib/dll/example/Makefile +1 -1
  188. data/ext/multi_compress/vendor/zstd/lib/dll/example/README.md +1 -1
  189. data/ext/multi_compress/vendor/zstd/lib/legacy/zstd_legacy.h +38 -1
  190. data/ext/multi_compress/vendor/zstd/lib/legacy/zstd_v01.c +19 -50
  191. data/ext/multi_compress/vendor/zstd/lib/legacy/zstd_v01.h +1 -1
  192. data/ext/multi_compress/vendor/zstd/lib/legacy/zstd_v02.c +27 -80
  193. data/ext/multi_compress/vendor/zstd/lib/legacy/zstd_v02.h +1 -1
  194. data/ext/multi_compress/vendor/zstd/lib/legacy/zstd_v03.c +28 -83
  195. data/ext/multi_compress/vendor/zstd/lib/legacy/zstd_v03.h +1 -1
  196. data/ext/multi_compress/vendor/zstd/lib/legacy/zstd_v04.c +25 -74
  197. data/ext/multi_compress/vendor/zstd/lib/legacy/zstd_v04.h +1 -1
  198. data/ext/multi_compress/vendor/zstd/lib/legacy/zstd_v05.c +31 -76
  199. data/ext/multi_compress/vendor/zstd/lib/legacy/zstd_v05.h +1 -1
  200. data/ext/multi_compress/vendor/zstd/lib/legacy/zstd_v06.c +44 -88
  201. data/ext/multi_compress/vendor/zstd/lib/legacy/zstd_v06.h +1 -1
  202. data/ext/multi_compress/vendor/zstd/lib/legacy/zstd_v07.c +33 -84
  203. data/ext/multi_compress/vendor/zstd/lib/legacy/zstd_v07.h +1 -1
  204. data/ext/multi_compress/vendor/zstd/lib/libzstd.mk +65 -33
  205. data/ext/multi_compress/vendor/zstd/lib/libzstd.pc.in +5 -5
  206. data/ext/multi_compress/vendor/zstd/lib/module.modulemap +13 -3
  207. data/ext/multi_compress/vendor/zstd/lib/zdict.h +65 -36
  208. data/ext/multi_compress/vendor/zstd/lib/zstd.h +890 -267
  209. data/ext/multi_compress/vendor/zstd/lib/zstd_errors.h +28 -16
  210. data/lib/multi_compress/version.rb +1 -1
  211. metadata +29 -2
@@ -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
@@ -14,11 +14,10 @@
14
14
  /*-*************************************
15
15
  * Dependencies
16
16
  ***************************************/
17
+ #include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customFree */
17
18
  #include "../common/zstd_internal.h"
18
-
19
- #if defined (__cplusplus)
20
- extern "C" {
21
- #endif
19
+ #include "../common/portability_macros.h"
20
+ #include "../common/compiler.h" /* ZS2_isPower2 */
22
21
 
23
22
  /*-*************************************
24
23
  * Constants
@@ -44,8 +43,9 @@ extern "C" {
44
43
  ***************************************/
45
44
  typedef enum {
46
45
  ZSTD_cwksp_alloc_objects,
47
- ZSTD_cwksp_alloc_buffers,
48
- ZSTD_cwksp_alloc_aligned
46
+ ZSTD_cwksp_alloc_aligned_init_once,
47
+ ZSTD_cwksp_alloc_aligned,
48
+ ZSTD_cwksp_alloc_buffers
49
49
  } ZSTD_cwksp_alloc_phase_e;
50
50
 
51
51
  /**
@@ -98,8 +98,8 @@ typedef enum {
98
98
  *
99
99
  * Workspace Layout:
100
100
  *
101
- * [ ... workspace ... ]
102
- * [objects][tables ... ->] free space [<- ... aligned][<- ... buffers]
101
+ * [ ... workspace ... ]
102
+ * [objects][tables ->] free space [<- buffers][<- aligned][<- init once]
103
103
  *
104
104
  * The various objects that live in the workspace are divided into the
105
105
  * following categories, and are allocated separately:
@@ -123,9 +123,18 @@ typedef enum {
123
123
  * uint32_t arrays, all of whose values are between 0 and (nextSrc - base).
124
124
  * Their sizes depend on the cparams. These tables are 64-byte aligned.
125
125
  *
126
- * - Aligned: these buffers are used for various purposes that require 4 byte
127
- * alignment, but don't require any initialization before they're used. These
128
- * buffers are each aligned to 64 bytes.
126
+ * - Init once: these buffers require to be initialized at least once before
127
+ * use. They should be used when we want to skip memory initialization
128
+ * while not triggering memory checkers (like Valgrind) when reading from
129
+ * from this memory without writing to it first.
130
+ * These buffers should be used carefully as they might contain data
131
+ * from previous compressions.
132
+ * Buffers are aligned to 64 bytes.
133
+ *
134
+ * - Aligned: these buffers don't require any initialization before they're
135
+ * used. The user of the buffer should make sure they write into a buffer
136
+ * location before reading from it.
137
+ * Buffers are aligned to 64 bytes.
129
138
  *
130
139
  * - Buffers: these buffers are used for various purposes that don't require
131
140
  * any alignment or initialization before they're used. This means they can
@@ -137,8 +146,9 @@ typedef enum {
137
146
  * correctly packed into the workspace buffer. That order is:
138
147
  *
139
148
  * 1. Objects
140
- * 2. Buffers
141
- * 3. Aligned/Tables
149
+ * 2. Init once / Tables
150
+ * 3. Aligned / Tables
151
+ * 4. Buffers / Tables
142
152
  *
143
153
  * Attempts to reserve objects of different types out of order will fail.
144
154
  */
@@ -150,6 +160,7 @@ typedef struct {
150
160
  void* tableEnd;
151
161
  void* tableValidEnd;
152
162
  void* allocStart;
163
+ void* initOnceStart;
153
164
 
154
165
  BYTE allocFailed;
155
166
  int workspaceOversizedDuration;
@@ -162,6 +173,7 @@ typedef struct {
162
173
  ***************************************/
163
174
 
164
175
  MEM_STATIC size_t ZSTD_cwksp_available_space(ZSTD_cwksp* ws);
176
+ MEM_STATIC void* ZSTD_cwksp_initialAllocStart(ZSTD_cwksp* ws);
165
177
 
166
178
  MEM_STATIC void ZSTD_cwksp_assert_internal_consistency(ZSTD_cwksp* ws) {
167
179
  (void)ws;
@@ -171,14 +183,29 @@ MEM_STATIC void ZSTD_cwksp_assert_internal_consistency(ZSTD_cwksp* ws) {
171
183
  assert(ws->tableEnd <= ws->allocStart);
172
184
  assert(ws->tableValidEnd <= ws->allocStart);
173
185
  assert(ws->allocStart <= ws->workspaceEnd);
186
+ assert(ws->initOnceStart <= ZSTD_cwksp_initialAllocStart(ws));
187
+ assert(ws->workspace <= ws->initOnceStart);
188
+ #if ZSTD_MEMORY_SANITIZER
189
+ {
190
+ intptr_t const offset = __msan_test_shadow(ws->initOnceStart,
191
+ (U8*)ZSTD_cwksp_initialAllocStart(ws) - (U8*)ws->initOnceStart);
192
+ (void)offset;
193
+ #if defined(ZSTD_MSAN_PRINT)
194
+ if(offset!=-1) {
195
+ __msan_print_shadow((U8*)ws->initOnceStart + offset - 8, 32);
196
+ }
197
+ #endif
198
+ assert(offset==-1);
199
+ };
200
+ #endif
174
201
  }
175
202
 
176
203
  /**
177
204
  * Align must be a power of 2.
178
205
  */
179
- MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t const align) {
206
+ MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t align) {
180
207
  size_t const mask = align - 1;
181
- assert((align & mask) == 0);
208
+ assert(ZSTD_isPower2(align));
182
209
  return (size + mask) & ~mask;
183
210
  }
184
211
 
@@ -192,7 +219,7 @@ MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t const align) {
192
219
  * to figure out how much space you need for the matchState tables. Everything
193
220
  * else is though.
194
221
  *
195
- * Do not use for sizing aligned buffers. Instead, use ZSTD_cwksp_aligned_alloc_size().
222
+ * Do not use for sizing aligned buffers. Instead, use ZSTD_cwksp_aligned64_alloc_size().
196
223
  */
197
224
  MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) {
198
225
  if (size == 0)
@@ -204,12 +231,16 @@ MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) {
204
231
  #endif
205
232
  }
206
233
 
234
+ MEM_STATIC size_t ZSTD_cwksp_aligned_alloc_size(size_t size, size_t alignment) {
235
+ return ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(size, alignment));
236
+ }
237
+
207
238
  /**
208
239
  * Returns an adjusted alloc size that is the nearest larger multiple of 64 bytes.
209
240
  * Used to determine the number of bytes required for a given "aligned".
210
241
  */
211
- MEM_STATIC size_t ZSTD_cwksp_aligned_alloc_size(size_t size) {
212
- return ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(size, ZSTD_CWKSP_ALIGNMENT_BYTES));
242
+ MEM_STATIC size_t ZSTD_cwksp_aligned64_alloc_size(size_t size) {
243
+ return ZSTD_cwksp_aligned_alloc_size(size, ZSTD_CWKSP_ALIGNMENT_BYTES);
213
244
  }
214
245
 
215
246
  /**
@@ -217,14 +248,10 @@ MEM_STATIC size_t ZSTD_cwksp_aligned_alloc_size(size_t size) {
217
248
  * for internal purposes (currently only alignment).
218
249
  */
219
250
  MEM_STATIC size_t ZSTD_cwksp_slack_space_required(void) {
220
- /* For alignment, the wksp will always allocate an additional n_1=[1, 64] bytes
221
- * to align the beginning of tables section, as well as another n_2=[0, 63] bytes
222
- * to align the beginning of the aligned section.
223
- *
224
- * n_1 + n_2 == 64 bytes if the cwksp is freshly allocated, due to tables and
225
- * aligneds being sized in multiples of 64 bytes.
251
+ /* For alignment, the wksp will always allocate an additional 2*ZSTD_CWKSP_ALIGNMENT_BYTES
252
+ * bytes to align the beginning of tables section and end of buffers;
226
253
  */
227
- size_t const slackSpace = ZSTD_CWKSP_ALIGNMENT_BYTES;
254
+ size_t const slackSpace = ZSTD_CWKSP_ALIGNMENT_BYTES * 2;
228
255
  return slackSpace;
229
256
  }
230
257
 
@@ -236,11 +263,23 @@ MEM_STATIC size_t ZSTD_cwksp_slack_space_required(void) {
236
263
  MEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignBytes) {
237
264
  size_t const alignBytesMask = alignBytes - 1;
238
265
  size_t const bytes = (alignBytes - ((size_t)ptr & (alignBytesMask))) & alignBytesMask;
239
- assert((alignBytes & alignBytesMask) == 0);
240
- assert(bytes != ZSTD_CWKSP_ALIGNMENT_BYTES);
266
+ assert(ZSTD_isPower2(alignBytes));
267
+ assert(bytes < alignBytes);
241
268
  return bytes;
242
269
  }
243
270
 
271
+ /**
272
+ * Returns the initial value for allocStart which is used to determine the position from
273
+ * which we can allocate from the end of the workspace.
274
+ */
275
+ MEM_STATIC void* ZSTD_cwksp_initialAllocStart(ZSTD_cwksp* ws)
276
+ {
277
+ char* endPtr = (char*)ws->workspaceEnd;
278
+ assert(ZSTD_isPower2(ZSTD_CWKSP_ALIGNMENT_BYTES));
279
+ endPtr = endPtr - ((size_t)endPtr % ZSTD_CWKSP_ALIGNMENT_BYTES);
280
+ return (void*)endPtr;
281
+ }
282
+
244
283
  /**
245
284
  * Internal function. Do not use directly.
246
285
  * Reserves the given number of bytes within the aligned/buffer segment of the wksp,
@@ -253,7 +292,7 @@ ZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t const bytes)
253
292
  {
254
293
  void* const alloc = (BYTE*)ws->allocStart - bytes;
255
294
  void* const bottom = ws->tableEnd;
256
- DEBUGLOG(5, "cwksp: reserving %p %zd bytes, %zd bytes remaining",
295
+ DEBUGLOG(5, "cwksp: reserving [0x%p]:%zd bytes; %zd bytes remaining",
257
296
  alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes);
258
297
  ZSTD_cwksp_assert_internal_consistency(ws);
259
298
  assert(alloc >= bottom);
@@ -281,27 +320,16 @@ ZSTD_cwksp_internal_advance_phase(ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase
281
320
  {
282
321
  assert(phase >= ws->phase);
283
322
  if (phase > ws->phase) {
284
- /* Going from allocating objects to allocating buffers */
285
- if (ws->phase < ZSTD_cwksp_alloc_buffers &&
286
- phase >= ZSTD_cwksp_alloc_buffers) {
323
+ /* Going from allocating objects to allocating initOnce / tables */
324
+ if (ws->phase < ZSTD_cwksp_alloc_aligned_init_once &&
325
+ phase >= ZSTD_cwksp_alloc_aligned_init_once) {
287
326
  ws->tableValidEnd = ws->objectEnd;
288
- }
327
+ ws->initOnceStart = ZSTD_cwksp_initialAllocStart(ws);
289
328
 
290
- /* Going from allocating buffers to allocating aligneds/tables */
291
- if (ws->phase < ZSTD_cwksp_alloc_aligned &&
292
- phase >= ZSTD_cwksp_alloc_aligned) {
293
- { /* Align the start of the "aligned" to 64 bytes. Use [1, 64] bytes. */
294
- size_t const bytesToAlign =
295
- ZSTD_CWKSP_ALIGNMENT_BYTES - ZSTD_cwksp_bytes_to_align_ptr(ws->allocStart, ZSTD_CWKSP_ALIGNMENT_BYTES);
296
- DEBUGLOG(5, "reserving aligned alignment addtl space: %zu", bytesToAlign);
297
- ZSTD_STATIC_ASSERT((ZSTD_CWKSP_ALIGNMENT_BYTES & (ZSTD_CWKSP_ALIGNMENT_BYTES - 1)) == 0); /* power of 2 */
298
- RETURN_ERROR_IF(!ZSTD_cwksp_reserve_internal_buffer_space(ws, bytesToAlign),
299
- memory_allocation, "aligned phase - alignment initial allocation failed!");
300
- }
301
329
  { /* Align the start of the tables to 64 bytes. Use [0, 63] bytes */
302
- void* const alloc = ws->objectEnd;
330
+ void *const alloc = ws->objectEnd;
303
331
  size_t const bytesToAlign = ZSTD_cwksp_bytes_to_align_ptr(alloc, ZSTD_CWKSP_ALIGNMENT_BYTES);
304
- void* const objectEnd = (BYTE*)alloc + bytesToAlign;
332
+ void *const objectEnd = (BYTE *) alloc + bytesToAlign;
305
333
  DEBUGLOG(5, "reserving table alignment addtl space: %zu", bytesToAlign);
306
334
  RETURN_ERROR_IF(objectEnd > ws->workspaceEnd, memory_allocation,
307
335
  "table phase - alignment initial allocation failed!");
@@ -309,7 +337,9 @@ ZSTD_cwksp_internal_advance_phase(ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase
309
337
  ws->tableEnd = objectEnd; /* table area starts being empty */
310
338
  if (ws->tableValidEnd < ws->tableEnd) {
311
339
  ws->tableValidEnd = ws->tableEnd;
312
- } } }
340
+ }
341
+ }
342
+ }
313
343
  ws->phase = phase;
314
344
  ZSTD_cwksp_assert_internal_consistency(ws);
315
345
  }
@@ -321,7 +351,7 @@ ZSTD_cwksp_internal_advance_phase(ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase
321
351
  */
322
352
  MEM_STATIC int ZSTD_cwksp_owns_buffer(const ZSTD_cwksp* ws, const void* ptr)
323
353
  {
324
- return (ptr != NULL) && (ws->workspace <= ptr) && (ptr <= ws->workspaceEnd);
354
+ return (ptr != NULL) && (ws->workspace <= ptr) && (ptr < ws->workspaceEnd);
325
355
  }
326
356
 
327
357
  /**
@@ -348,7 +378,9 @@ ZSTD_cwksp_reserve_internal(ZSTD_cwksp* ws, size_t bytes, ZSTD_cwksp_alloc_phase
348
378
  if (alloc) {
349
379
  alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
350
380
  if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
351
- __asan_unpoison_memory_region(alloc, bytes);
381
+ /* We need to keep the redzone poisoned while unpoisoning the bytes that
382
+ * are actually allocated. */
383
+ __asan_unpoison_memory_region(alloc, bytes - 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE);
352
384
  }
353
385
  }
354
386
  #endif
@@ -366,29 +398,64 @@ MEM_STATIC BYTE* ZSTD_cwksp_reserve_buffer(ZSTD_cwksp* ws, size_t bytes)
366
398
 
367
399
  /**
368
400
  * Reserves and returns memory sized on and aligned on ZSTD_CWKSP_ALIGNMENT_BYTES (64 bytes).
401
+ * This memory has been initialized at least once in the past.
402
+ * This doesn't mean it has been initialized this time, and it might contain data from previous
403
+ * operations.
404
+ * The main usage is for algorithms that might need read access into uninitialized memory.
405
+ * The algorithm must maintain safety under these conditions and must make sure it doesn't
406
+ * leak any of the past data (directly or in side channels).
369
407
  */
370
- MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes)
408
+ MEM_STATIC void* ZSTD_cwksp_reserve_aligned_init_once(ZSTD_cwksp* ws, size_t bytes)
371
409
  {
372
- void* ptr = ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES),
373
- ZSTD_cwksp_alloc_aligned);
374
- assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0);
410
+ size_t const alignedBytes = ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES);
411
+ void* ptr = ZSTD_cwksp_reserve_internal(ws, alignedBytes, ZSTD_cwksp_alloc_aligned_init_once);
412
+ assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0);
413
+ if(ptr && ptr < ws->initOnceStart) {
414
+ /* We assume the memory following the current allocation is either:
415
+ * 1. Not usable as initOnce memory (end of workspace)
416
+ * 2. Another initOnce buffer that has been allocated before (and so was previously memset)
417
+ * 3. An ASAN redzone, in which case we don't want to write on it
418
+ * For these reasons it should be fine to not explicitly zero every byte up to ws->initOnceStart.
419
+ * Note that we assume here that MSAN and ASAN cannot run in the same time. */
420
+ ZSTD_memset(ptr, 0, MIN((size_t)((U8*)ws->initOnceStart - (U8*)ptr), alignedBytes));
421
+ ws->initOnceStart = ptr;
422
+ }
423
+ #if ZSTD_MEMORY_SANITIZER
424
+ assert(__msan_test_shadow(ptr, bytes) == -1);
425
+ #endif
426
+ return ptr;
427
+ }
428
+
429
+ /**
430
+ * Reserves and returns memory sized on and aligned on ZSTD_CWKSP_ALIGNMENT_BYTES (64 bytes).
431
+ */
432
+ MEM_STATIC void* ZSTD_cwksp_reserve_aligned64(ZSTD_cwksp* ws, size_t bytes)
433
+ {
434
+ void* const ptr = ZSTD_cwksp_reserve_internal(ws,
435
+ ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES),
436
+ ZSTD_cwksp_alloc_aligned);
437
+ assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0);
375
438
  return ptr;
376
439
  }
377
440
 
378
441
  /**
379
442
  * Aligned on 64 bytes. These buffers have the special property that
380
- * their values remain constrained, allowing us to re-use them without
443
+ * their values remain constrained, allowing us to reuse them without
381
444
  * memset()-ing them.
382
445
  */
383
446
  MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes)
384
447
  {
385
- const ZSTD_cwksp_alloc_phase_e phase = ZSTD_cwksp_alloc_aligned;
448
+ const ZSTD_cwksp_alloc_phase_e phase = ZSTD_cwksp_alloc_aligned_init_once;
386
449
  void* alloc;
387
450
  void* end;
388
451
  void* top;
389
452
 
390
- if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase))) {
391
- return NULL;
453
+ /* We can only start allocating tables after we are done reserving space for objects at the
454
+ * start of the workspace */
455
+ if(ws->phase < phase) {
456
+ if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase))) {
457
+ return NULL;
458
+ }
392
459
  }
393
460
  alloc = ws->tableEnd;
394
461
  end = (BYTE *)alloc + bytes;
@@ -413,7 +480,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes)
413
480
  #endif
414
481
 
415
482
  assert((bytes & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0);
416
- assert(((size_t)alloc & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0);
483
+ assert(((size_t)alloc & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0);
417
484
  return alloc;
418
485
  }
419
486
 
@@ -459,19 +526,41 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes)
459
526
 
460
527
  return alloc;
461
528
  }
529
+ /**
530
+ * with alignment control
531
+ * Note : should happen only once, at workspace first initialization
532
+ */
533
+ MEM_STATIC void* ZSTD_cwksp_reserve_object_aligned(ZSTD_cwksp* ws, size_t byteSize, size_t alignment)
534
+ {
535
+ size_t const mask = alignment - 1;
536
+ size_t const surplus = (alignment > sizeof(void*)) ? alignment - sizeof(void*) : 0;
537
+ void* const start = ZSTD_cwksp_reserve_object(ws, byteSize + surplus);
538
+ if (start == NULL) return NULL;
539
+ if (surplus == 0) return start;
540
+ assert(ZSTD_isPower2(alignment));
541
+ return (void*)(((size_t)start + surplus) & ~mask);
542
+ }
462
543
 
463
544
  MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws)
464
545
  {
465
546
  DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_dirty");
466
547
 
467
548
  #if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
468
- /* To validate that the table re-use logic is sound, and that we don't
549
+ /* To validate that the table reuse logic is sound, and that we don't
469
550
  * access table space that we haven't cleaned, we re-"poison" the table
470
- * space every time we mark it dirty. */
551
+ * space every time we mark it dirty.
552
+ * Since tableValidEnd space and initOnce space may overlap we don't poison
553
+ * the initOnce portion as it break its promise. This means that this poisoning
554
+ * check isn't always applied fully. */
471
555
  {
472
556
  size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd;
473
557
  assert(__msan_test_shadow(ws->objectEnd, size) == -1);
474
- __msan_poison(ws->objectEnd, size);
558
+ if((BYTE*)ws->tableValidEnd < (BYTE*)ws->initOnceStart) {
559
+ __msan_poison(ws->objectEnd, size);
560
+ } else {
561
+ assert(ws->initOnceStart >= ws->objectEnd);
562
+ __msan_poison(ws->objectEnd, (BYTE*)ws->initOnceStart - (BYTE*)ws->objectEnd);
563
+ }
475
564
  }
476
565
  #endif
477
566
 
@@ -499,7 +588,7 @@ MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) {
499
588
  assert(ws->tableValidEnd >= ws->objectEnd);
500
589
  assert(ws->tableValidEnd <= ws->allocStart);
501
590
  if (ws->tableValidEnd < ws->tableEnd) {
502
- ZSTD_memset(ws->tableValidEnd, 0, (BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd);
591
+ ZSTD_memset(ws->tableValidEnd, 0, (size_t)((BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd));
503
592
  }
504
593
  ZSTD_cwksp_mark_tables_clean(ws);
505
594
  }
@@ -508,7 +597,8 @@ MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) {
508
597
  * Invalidates table allocations.
509
598
  * All other allocations remain valid.
510
599
  */
511
- MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) {
600
+ MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws)
601
+ {
512
602
  DEBUGLOG(4, "cwksp: clearing tables!");
513
603
 
514
604
  #if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
@@ -534,13 +624,16 @@ MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) {
534
624
  DEBUGLOG(4, "cwksp: clearing!");
535
625
 
536
626
  #if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
537
- /* To validate that the context re-use logic is sound, and that we don't
627
+ /* To validate that the context reuse logic is sound, and that we don't
538
628
  * access stuff that this compression hasn't initialized, we re-"poison"
539
- * the workspace (or at least the non-static, non-table parts of it)
540
- * every time we start a new compression. */
629
+ * the workspace except for the areas in which we expect memory reuse
630
+ * without initialization (objects, valid tables area and init once
631
+ * memory). */
541
632
  {
542
- size_t size = (BYTE*)ws->workspaceEnd - (BYTE*)ws->tableValidEnd;
543
- __msan_poison(ws->tableValidEnd, size);
633
+ if((BYTE*)ws->tableValidEnd < (BYTE*)ws->initOnceStart) {
634
+ size_t size = (BYTE*)ws->initOnceStart - (BYTE*)ws->tableValidEnd;
635
+ __msan_poison(ws->tableValidEnd, size);
636
+ }
544
637
  }
545
638
  #endif
546
639
 
@@ -556,14 +649,23 @@ MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) {
556
649
  #endif
557
650
 
558
651
  ws->tableEnd = ws->objectEnd;
559
- ws->allocStart = ws->workspaceEnd;
652
+ ws->allocStart = ZSTD_cwksp_initialAllocStart(ws);
560
653
  ws->allocFailed = 0;
561
- if (ws->phase > ZSTD_cwksp_alloc_buffers) {
562
- ws->phase = ZSTD_cwksp_alloc_buffers;
654
+ if (ws->phase > ZSTD_cwksp_alloc_aligned_init_once) {
655
+ ws->phase = ZSTD_cwksp_alloc_aligned_init_once;
563
656
  }
564
657
  ZSTD_cwksp_assert_internal_consistency(ws);
565
658
  }
566
659
 
660
+ MEM_STATIC size_t ZSTD_cwksp_sizeof(const ZSTD_cwksp* ws) {
661
+ return (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->workspace);
662
+ }
663
+
664
+ MEM_STATIC size_t ZSTD_cwksp_used(const ZSTD_cwksp* ws) {
665
+ return (size_t)((BYTE*)ws->tableEnd - (BYTE*)ws->workspace)
666
+ + (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->allocStart);
667
+ }
668
+
567
669
  /**
568
670
  * The provided workspace takes ownership of the buffer [start, start+size).
569
671
  * Any existing values in the workspace are ignored (the previously managed
@@ -576,6 +678,7 @@ MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size, ZSTD_c
576
678
  ws->workspaceEnd = (BYTE*)start + size;
577
679
  ws->objectEnd = ws->workspace;
578
680
  ws->tableValidEnd = ws->objectEnd;
681
+ ws->initOnceStart = ZSTD_cwksp_initialAllocStart(ws);
579
682
  ws->phase = ZSTD_cwksp_alloc_objects;
580
683
  ws->isStatic = isStatic;
581
684
  ZSTD_cwksp_clear(ws);
@@ -594,6 +697,11 @@ MEM_STATIC size_t ZSTD_cwksp_create(ZSTD_cwksp* ws, size_t size, ZSTD_customMem
594
697
  MEM_STATIC void ZSTD_cwksp_free(ZSTD_cwksp* ws, ZSTD_customMem customMem) {
595
698
  void *ptr = ws->workspace;
596
699
  DEBUGLOG(4, "cwksp: freeing workspace");
700
+ #if ZSTD_MEMORY_SANITIZER && !defined(ZSTD_MSAN_DONT_POISON_WORKSPACE)
701
+ if (ptr != NULL && customMem.customFree != NULL) {
702
+ __msan_unpoison(ptr, ZSTD_cwksp_sizeof(ws));
703
+ }
704
+ #endif
597
705
  ZSTD_memset(ws, 0, sizeof(ZSTD_cwksp));
598
706
  ZSTD_customFree(ptr, customMem);
599
707
  }
@@ -607,15 +715,6 @@ MEM_STATIC void ZSTD_cwksp_move(ZSTD_cwksp* dst, ZSTD_cwksp* src) {
607
715
  ZSTD_memset(src, 0, sizeof(ZSTD_cwksp));
608
716
  }
609
717
 
610
- MEM_STATIC size_t ZSTD_cwksp_sizeof(const ZSTD_cwksp* ws) {
611
- return (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->workspace);
612
- }
613
-
614
- MEM_STATIC size_t ZSTD_cwksp_used(const ZSTD_cwksp* ws) {
615
- return (size_t)((BYTE*)ws->tableEnd - (BYTE*)ws->workspace)
616
- + (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->allocStart);
617
- }
618
-
619
718
  MEM_STATIC int ZSTD_cwksp_reserve_failed(const ZSTD_cwksp* ws) {
620
719
  return ws->allocFailed;
621
720
  }
@@ -628,17 +727,11 @@ MEM_STATIC int ZSTD_cwksp_reserve_failed(const ZSTD_cwksp* ws) {
628
727
  * Returns if the estimated space needed for a wksp is within an acceptable limit of the
629
728
  * actual amount of space used.
630
729
  */
631
- MEM_STATIC int ZSTD_cwksp_estimated_space_within_bounds(const ZSTD_cwksp* const ws,
632
- size_t const estimatedSpace, int resizedWorkspace) {
633
- if (resizedWorkspace) {
634
- /* Resized/newly allocated wksp should have exact bounds */
635
- return ZSTD_cwksp_used(ws) == estimatedSpace;
636
- } else {
637
- /* Due to alignment, when reusing a workspace, we can actually consume 63 fewer or more bytes
638
- * than estimatedSpace. See the comments in zstd_cwksp.h for details.
639
- */
640
- return (ZSTD_cwksp_used(ws) >= estimatedSpace - 63) && (ZSTD_cwksp_used(ws) <= estimatedSpace + 63);
641
- }
730
+ MEM_STATIC int ZSTD_cwksp_estimated_space_within_bounds(const ZSTD_cwksp *const ws, size_t const estimatedSpace) {
731
+ /* We have an alignment space between objects and tables between tables and buffers, so we can have up to twice
732
+ * the alignment bytes difference between estimation and actual usage */
733
+ return (estimatedSpace - ZSTD_cwksp_slack_space_required()) <= ZSTD_cwksp_used(ws) &&
734
+ ZSTD_cwksp_used(ws) <= estimatedSpace;
642
735
  }
643
736
 
644
737
 
@@ -669,8 +762,4 @@ MEM_STATIC void ZSTD_cwksp_bump_oversized_duration(
669
762
  }
670
763
  }
671
764
 
672
- #if defined (__cplusplus)
673
- }
674
- #endif
675
-
676
765
  #endif /* ZSTD_CWKSP_H */