zstd-ruby 1.3.8.0 → 1.4.5.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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -5
  3. data/README.md +1 -1
  4. data/ext/zstdruby/libzstd/Makefile +133 -61
  5. data/ext/zstdruby/libzstd/README.md +51 -18
  6. data/ext/zstdruby/libzstd/common/bitstream.h +38 -39
  7. data/ext/zstdruby/libzstd/common/compiler.h +41 -6
  8. data/ext/zstdruby/libzstd/common/cpu.h +1 -1
  9. data/ext/zstdruby/libzstd/common/debug.c +11 -31
  10. data/ext/zstdruby/libzstd/common/debug.h +11 -31
  11. data/ext/zstdruby/libzstd/common/entropy_common.c +13 -33
  12. data/ext/zstdruby/libzstd/common/error_private.c +2 -1
  13. data/ext/zstdruby/libzstd/common/error_private.h +6 -2
  14. data/ext/zstdruby/libzstd/common/fse.h +13 -33
  15. data/ext/zstdruby/libzstd/common/fse_decompress.c +12 -35
  16. data/ext/zstdruby/libzstd/common/huf.h +15 -33
  17. data/ext/zstdruby/libzstd/common/mem.h +75 -2
  18. data/ext/zstdruby/libzstd/common/pool.c +8 -4
  19. data/ext/zstdruby/libzstd/common/pool.h +2 -2
  20. data/ext/zstdruby/libzstd/common/threading.c +52 -6
  21. data/ext/zstdruby/libzstd/common/threading.h +36 -4
  22. data/ext/zstdruby/libzstd/common/xxhash.c +25 -37
  23. data/ext/zstdruby/libzstd/common/xxhash.h +11 -31
  24. data/ext/zstdruby/libzstd/common/zstd_common.c +1 -1
  25. data/ext/zstdruby/libzstd/common/zstd_errors.h +2 -1
  26. data/ext/zstdruby/libzstd/common/zstd_internal.h +203 -22
  27. data/ext/zstdruby/libzstd/compress/fse_compress.c +19 -42
  28. data/ext/zstdruby/libzstd/compress/hist.c +15 -35
  29. data/ext/zstdruby/libzstd/compress/hist.h +12 -32
  30. data/ext/zstdruby/libzstd/compress/huf_compress.c +92 -92
  31. data/ext/zstdruby/libzstd/compress/zstd_compress.c +1460 -1472
  32. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +330 -65
  33. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +158 -0
  34. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +29 -0
  35. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +419 -0
  36. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +54 -0
  37. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +845 -0
  38. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
  39. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +525 -0
  40. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +65 -43
  41. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +2 -2
  42. data/ext/zstdruby/libzstd/compress/zstd_fast.c +264 -159
  43. data/ext/zstdruby/libzstd/compress/zstd_fast.h +2 -2
  44. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +74 -42
  45. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +2 -2
  46. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +33 -11
  47. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +7 -2
  48. data/ext/zstdruby/libzstd/compress/zstd_opt.c +108 -125
  49. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  50. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +129 -93
  51. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +46 -28
  52. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +76 -60
  53. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +14 -10
  54. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +2 -2
  55. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +471 -258
  56. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +471 -346
  57. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +3 -3
  58. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +25 -4
  59. data/ext/zstdruby/libzstd/deprecated/zbuff.h +9 -8
  60. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +2 -2
  61. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -1
  62. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
  63. data/ext/zstdruby/libzstd/dictBuilder/cover.c +220 -65
  64. data/ext/zstdruby/libzstd/dictBuilder/cover.h +81 -7
  65. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +85 -56
  66. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +43 -19
  67. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +73 -35
  68. data/ext/zstdruby/libzstd/dll/example/Makefile +2 -1
  69. data/ext/zstdruby/libzstd/dll/example/build_package.bat +3 -2
  70. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +49 -15
  71. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +142 -117
  72. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +13 -8
  73. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +54 -25
  74. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +13 -8
  75. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +55 -25
  76. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +13 -8
  77. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +62 -29
  78. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +13 -8
  79. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +145 -109
  80. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +14 -9
  81. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +56 -26
  82. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +11 -6
  83. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +65 -28
  84. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +11 -6
  85. data/ext/zstdruby/libzstd/libzstd.pc.in +3 -2
  86. data/ext/zstdruby/libzstd/zstd.h +921 -597
  87. data/lib/zstd-ruby/version.rb +1 -1
  88. data/zstd-ruby.gemspec +2 -2
  89. metadata +19 -14
  90. data/ext/zstdruby/libzstd/dll/libzstd.def +0 -87
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2020, 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
@@ -17,15 +17,30 @@
17
17
 
18
18
 
19
19
  /* Note : This is an internal API.
20
- * Some methods are still exposed (ZSTDLIB_API),
20
+ * These APIs used to be exposed with ZSTDLIB_API,
21
21
  * because it used to be the only way to invoke MT compression.
22
- * Now, it's recommended to use ZSTD_compress_generic() instead.
23
- * These methods will stop being exposed in a future version */
22
+ * Now, it's recommended to use ZSTD_compress2 and ZSTD_compressStream2()
23
+ * instead.
24
+ *
25
+ * If you depend on these APIs and can't switch, then define
26
+ * ZSTD_LEGACY_MULTITHREADED_API when making the dynamic library.
27
+ * However, we may completely remove these functions in a future
28
+ * release, so please switch soon.
29
+ *
30
+ * This API requires ZSTD_MULTITHREAD to be defined during compilation,
31
+ * otherwise ZSTDMT_createCCtx*() will fail.
32
+ */
33
+
34
+ #ifdef ZSTD_LEGACY_MULTITHREADED_API
35
+ # define ZSTDMT_API ZSTDLIB_API
36
+ #else
37
+ # define ZSTDMT_API
38
+ #endif
24
39
 
25
40
  /* === Dependencies === */
26
41
  #include <stddef.h> /* size_t */
27
42
  #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters */
28
- #include "zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */
43
+ #include "../zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */
29
44
 
30
45
 
31
46
  /* === Constants === */
@@ -35,22 +50,25 @@
35
50
  #ifndef ZSTDMT_JOBSIZE_MIN
36
51
  # define ZSTDMT_JOBSIZE_MIN (1 MB)
37
52
  #endif
53
+ #define ZSTDMT_JOBLOG_MAX (MEM_32bits() ? 29 : 30)
38
54
  #define ZSTDMT_JOBSIZE_MAX (MEM_32bits() ? (512 MB) : (1024 MB))
39
55
 
40
56
 
41
57
  /* === Memory management === */
42
58
  typedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx;
43
- ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers);
44
- ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers,
59
+ /* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */
60
+ ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers);
61
+ /* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */
62
+ ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers,
45
63
  ZSTD_customMem cMem);
46
- ZSTDLIB_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);
64
+ ZSTDMT_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);
47
65
 
48
- ZSTDLIB_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);
66
+ ZSTDMT_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);
49
67
 
50
68
 
51
69
  /* === Simple one-pass compression function === */
52
70
 
53
- ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
71
+ ZSTDMT_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
54
72
  void* dst, size_t dstCapacity,
55
73
  const void* src, size_t srcSize,
56
74
  int compressionLevel);
@@ -59,31 +77,31 @@ ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
59
77
 
60
78
  /* === Streaming functions === */
61
79
 
62
- ZSTDLIB_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel);
63
- ZSTDLIB_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it will change in the future to mean "empty" */
80
+ ZSTDMT_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel);
81
+ ZSTDMT_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it will change in the future to mean "empty" */
64
82
 
65
- ZSTDLIB_API size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx);
66
- ZSTDLIB_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
83
+ ZSTDMT_API size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx);
84
+ ZSTDMT_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
67
85
 
68
- ZSTDLIB_API size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
69
- ZSTDLIB_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
86
+ ZSTDMT_API size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
87
+ ZSTDMT_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
70
88
 
71
89
 
72
90
  /* === Advanced functions and parameters === */
73
91
 
74
- ZSTDLIB_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
75
- void* dst, size_t dstCapacity,
76
- const void* src, size_t srcSize,
77
- const ZSTD_CDict* cdict,
78
- ZSTD_parameters params,
79
- int overlapLog);
92
+ ZSTDMT_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
93
+ void* dst, size_t dstCapacity,
94
+ const void* src, size_t srcSize,
95
+ const ZSTD_CDict* cdict,
96
+ ZSTD_parameters params,
97
+ int overlapLog);
80
98
 
81
- ZSTDLIB_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
99
+ ZSTDMT_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
82
100
  const void* dict, size_t dictSize, /* dict can be released after init, a local copy is preserved within zcs */
83
101
  ZSTD_parameters params,
84
102
  unsigned long long pledgedSrcSize); /* pledgedSrcSize is optional and can be zero == unknown */
85
103
 
86
- ZSTDLIB_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
104
+ ZSTDMT_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
87
105
  const ZSTD_CDict* cdict,
88
106
  ZSTD_frameParameters fparams,
89
107
  unsigned long long pledgedSrcSize); /* note : zero means empty */
@@ -92,7 +110,7 @@ ZSTDLIB_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
92
110
  * List of parameters that can be set using ZSTDMT_setMTCtxParameter() */
93
111
  typedef enum {
94
112
  ZSTDMT_p_jobSize, /* Each job is compressed in parallel. By default, this value is dynamically determined depending on compression parameters. Can be set explicitly here. */
95
- ZSTDMT_p_overlapLog, /* Each job may reload a part of previous job to enhance compressionr ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window. This is a "sticky" parameter : its value will be re-used on next compression job */
113
+ ZSTDMT_p_overlapLog, /* Each job may reload a part of previous job to enhance compression ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window. This is a "sticky" parameter : its value will be re-used on next compression job */
96
114
  ZSTDMT_p_rsyncable /* Enables rsyncable mode. */
97
115
  } ZSTDMT_parameter;
98
116
 
@@ -101,12 +119,12 @@ typedef enum {
101
119
  * The function must be called typically after ZSTD_createCCtx() but __before ZSTDMT_init*() !__
102
120
  * Parameters not explicitly reset by ZSTDMT_init*() remain the same in consecutive compression sessions.
103
121
  * @return : 0, or an error code (which can be tested using ZSTD_isError()) */
104
- ZSTDLIB_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value);
122
+ ZSTDMT_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value);
105
123
 
106
124
  /* ZSTDMT_getMTCtxParameter() :
107
125
  * Query the ZSTDMT_CCtx for a parameter value.
108
126
  * @return : 0, or an error code (which can be tested using ZSTD_isError()) */
109
- ZSTDLIB_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value);
127
+ ZSTDMT_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value);
110
128
 
111
129
 
112
130
  /*! ZSTDMT_compressStream_generic() :
@@ -116,7 +134,7 @@ ZSTDLIB_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter
116
134
  * 0 if fully flushed
117
135
  * or an error code
118
136
  * note : needs to be init using any ZSTD_initCStream*() variant */
119
- ZSTDLIB_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
137
+ ZSTDMT_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
120
138
  ZSTD_outBuffer* output,
121
139
  ZSTD_inBuffer* input,
122
140
  ZSTD_EndDirective endOp);
@@ -1,47 +1,27 @@
1
1
  /* ******************************************************************
2
- huff0 huffman decoder,
3
- part of Finite State Entropy library
4
- Copyright (C) 2013-present, Yann Collet.
5
-
6
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
7
-
8
- Redistribution and use in source and binary forms, with or without
9
- modification, are permitted provided that the following conditions are
10
- met:
11
-
12
- * Redistributions of source code must retain the above copyright
13
- notice, this list of conditions and the following disclaimer.
14
- * Redistributions in binary form must reproduce the above
15
- copyright notice, this list of conditions and the following disclaimer
16
- in the documentation and/or other materials provided with the
17
- distribution.
18
-
19
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
-
31
- You can contact the author at :
32
- - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
2
+ * huff0 huffman decoder,
3
+ * part of Finite State Entropy library
4
+ * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
5
+ *
6
+ * You can contact the author at :
7
+ * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
8
+ *
9
+ * This source code is licensed under both the BSD-style license (found in the
10
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
11
+ * in the COPYING file in the root directory of this source tree).
12
+ * You may select, at your option, one of the above-listed licenses.
33
13
  ****************************************************************** */
34
14
 
35
15
  /* **************************************************************
36
16
  * Dependencies
37
17
  ****************************************************************/
38
18
  #include <string.h> /* memcpy, memset */
39
- #include "compiler.h"
40
- #include "bitstream.h" /* BIT_* */
41
- #include "fse.h" /* to compress headers */
19
+ #include "../common/compiler.h"
20
+ #include "../common/bitstream.h" /* BIT_* */
21
+ #include "../common/fse.h" /* to compress headers */
42
22
  #define HUF_STATIC_LINKING_ONLY
43
- #include "huf.h"
44
- #include "error_private.h"
23
+ #include "../common/huf.h"
24
+ #include "../common/error_private.h"
45
25
 
46
26
  /* **************************************************************
47
27
  * Macros
@@ -61,7 +41,6 @@
61
41
  * Error Management
62
42
  ****************************************************************/
63
43
  #define HUF_isError ERR_isError
64
- #define CHECK_F(f) { size_t const err_ = (f); if (HUF_isError(err_)) return err_; }
65
44
 
66
45
 
67
46
  /* **************************************************************
@@ -179,17 +158,29 @@ size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize
179
158
 
180
159
  /* fill DTable */
181
160
  { U32 n;
182
- for (n=0; n<nbSymbols; n++) {
183
- U32 const w = huffWeight[n];
184
- U32 const length = (1 << w) >> 1;
185
- U32 u;
161
+ size_t const nEnd = nbSymbols;
162
+ for (n=0; n<nEnd; n++) {
163
+ size_t const w = huffWeight[n];
164
+ size_t const length = (1 << w) >> 1;
165
+ size_t const uStart = rankVal[w];
166
+ size_t const uEnd = uStart + length;
167
+ size_t u;
186
168
  HUF_DEltX1 D;
187
- D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);
188
- for (u = rankVal[w]; u < rankVal[w] + length; u++)
189
- dt[u] = D;
190
- rankVal[w] += length;
191
- } }
192
-
169
+ D.byte = (BYTE)n;
170
+ D.nbBits = (BYTE)(tableLog + 1 - w);
171
+ rankVal[w] = (U32)uEnd;
172
+ if (length < 4) {
173
+ /* Use length in the loop bound so the compiler knows it is short. */
174
+ for (u = 0; u < length; ++u)
175
+ dt[uStart + u] = D;
176
+ } else {
177
+ /* Unroll the loop 4 times, we know it is a power of 2. */
178
+ for (u = uStart; u < uEnd; u += 4) {
179
+ dt[u + 0] = D;
180
+ dt[u + 1] = D;
181
+ dt[u + 2] = D;
182
+ dt[u + 3] = D;
183
+ } } } }
193
184
  return iSize;
194
185
  }
195
186
 
@@ -280,6 +271,7 @@ HUF_decompress4X1_usingDTable_internal_body(
280
271
  { const BYTE* const istart = (const BYTE*) cSrc;
281
272
  BYTE* const ostart = (BYTE*) dst;
282
273
  BYTE* const oend = ostart + dstSize;
274
+ BYTE* const olimit = oend - 3;
283
275
  const void* const dtPtr = DTable + 1;
284
276
  const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
285
277
 
@@ -304,9 +296,9 @@ HUF_decompress4X1_usingDTable_internal_body(
304
296
  BYTE* op2 = opStart2;
305
297
  BYTE* op3 = opStart3;
306
298
  BYTE* op4 = opStart4;
307
- U32 endSignal = BIT_DStream_unfinished;
308
299
  DTableDesc const dtd = HUF_getDTableDesc(DTable);
309
300
  U32 const dtLog = dtd.tableLog;
301
+ U32 endSignal = 1;
310
302
 
311
303
  if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
312
304
  CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
@@ -315,8 +307,7 @@ HUF_decompress4X1_usingDTable_internal_body(
315
307
  CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
316
308
 
317
309
  /* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */
318
- endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
319
- while ( (endSignal==BIT_DStream_unfinished) && (op4<(oend-3)) ) {
310
+ for ( ; (endSignal) & (op4 < olimit) ; ) {
320
311
  HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
321
312
  HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
322
313
  HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
@@ -333,10 +324,10 @@ HUF_decompress4X1_usingDTable_internal_body(
333
324
  HUF_DECODE_SYMBOLX1_0(op2, &bitD2);
334
325
  HUF_DECODE_SYMBOLX1_0(op3, &bitD3);
335
326
  HUF_DECODE_SYMBOLX1_0(op4, &bitD4);
336
- BIT_reloadDStream(&bitD1);
337
- BIT_reloadDStream(&bitD2);
338
- BIT_reloadDStream(&bitD3);
339
- BIT_reloadDStream(&bitD4);
327
+ endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
328
+ endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
329
+ endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
330
+ endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;
340
331
  }
341
332
 
342
333
  /* check corruption */
@@ -755,7 +746,6 @@ HUF_decompress1X2_usingDTable_internal_body(
755
746
  return dstSize;
756
747
  }
757
748
 
758
-
759
749
  FORCE_INLINE_TEMPLATE size_t
760
750
  HUF_decompress4X2_usingDTable_internal_body(
761
751
  void* dst, size_t dstSize,
@@ -767,6 +757,7 @@ HUF_decompress4X2_usingDTable_internal_body(
767
757
  { const BYTE* const istart = (const BYTE*) cSrc;
768
758
  BYTE* const ostart = (BYTE*) dst;
769
759
  BYTE* const oend = ostart + dstSize;
760
+ BYTE* const olimit = oend - (sizeof(size_t)-1);
770
761
  const void* const dtPtr = DTable+1;
771
762
  const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
772
763
 
@@ -791,7 +782,7 @@ HUF_decompress4X2_usingDTable_internal_body(
791
782
  BYTE* op2 = opStart2;
792
783
  BYTE* op3 = opStart3;
793
784
  BYTE* op4 = opStart4;
794
- U32 endSignal;
785
+ U32 endSignal = 1;
795
786
  DTableDesc const dtd = HUF_getDTableDesc(DTable);
796
787
  U32 const dtLog = dtd.tableLog;
797
788
 
@@ -802,8 +793,29 @@ HUF_decompress4X2_usingDTable_internal_body(
802
793
  CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
803
794
 
804
795
  /* 16-32 symbols per loop (4-8 symbols per stream) */
805
- endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
806
- for ( ; (endSignal==BIT_DStream_unfinished) & (op4<(oend-(sizeof(bitD4.bitContainer)-1))) ; ) {
796
+ for ( ; (endSignal) & (op4 < olimit); ) {
797
+ #if defined(__clang__) && (defined(__x86_64__) || defined(__i386__))
798
+ HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
799
+ HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
800
+ HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
801
+ HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
802
+ HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
803
+ HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
804
+ HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
805
+ HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
806
+ endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
807
+ endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
808
+ HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
809
+ HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
810
+ HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
811
+ HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
812
+ HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
813
+ HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
814
+ HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
815
+ HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
816
+ endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
817
+ endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;
818
+ #else
807
819
  HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
808
820
  HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
809
821
  HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
@@ -820,8 +832,12 @@ HUF_decompress4X2_usingDTable_internal_body(
820
832
  HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
821
833
  HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
822
834
  HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
823
-
824
- endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
835
+ endSignal = (U32)LIKELY(
836
+ (BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished)
837
+ & (BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished)
838
+ & (BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished)
839
+ & (BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished));
840
+ #endif
825
841
  }
826
842
 
827
843
  /* check corruption */
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2020, 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
@@ -15,17 +15,17 @@
15
15
  * Dependencies
16
16
  *********************************************************/
17
17
  #include <string.h> /* memcpy, memmove, memset */
18
- #include "cpu.h" /* bmi2 */
19
- #include "mem.h" /* low level memory routines */
18
+ #include "../common/cpu.h" /* bmi2 */
19
+ #include "../common/mem.h" /* low level memory routines */
20
20
  #define FSE_STATIC_LINKING_ONLY
21
- #include "fse.h"
21
+ #include "../common/fse.h"
22
22
  #define HUF_STATIC_LINKING_ONLY
23
- #include "huf.h"
23
+ #include "../common/huf.h"
24
24
  #include "zstd_decompress_internal.h"
25
25
  #include "zstd_ddict.h"
26
26
 
27
27
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
28
- # include "zstd_legacy.h"
28
+ # include "../legacy/zstd_legacy.h"
29
29
  #endif
30
30
 
31
31
 
@@ -65,6 +65,10 @@ void ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
65
65
  dctx->virtualStart = ddict->dictContent;
66
66
  dctx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize;
67
67
  dctx->previousDstEnd = dctx->dictEnd;
68
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
69
+ dctx->dictContentBeginForFuzzing = dctx->prefixStart;
70
+ dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
71
+ #endif
68
72
  if (ddict->entropyPresent) {
69
73
  dctx->litEntropy = 1;
70
74
  dctx->fseEntropy = 1;
@@ -105,9 +109,9 @@ ZSTD_loadEntropy_intoDDict(ZSTD_DDict* ddict,
105
109
  ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_FRAMEIDSIZE);
106
110
 
107
111
  /* load entropy tables */
108
- CHECK_E( ZSTD_loadDEntropy(&ddict->entropy,
109
- ddict->dictContent, ddict->dictSize),
110
- dictionary_corrupted );
112
+ RETURN_ERROR_IF(ZSTD_isError(ZSTD_loadDEntropy(
113
+ &ddict->entropy, ddict->dictContent, ddict->dictSize)),
114
+ dictionary_corrupted, "");
111
115
  ddict->entropyPresent = 1;
112
116
  return 0;
113
117
  }
@@ -133,7 +137,7 @@ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,
133
137
  ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
134
138
 
135
139
  /* parse dictionary content */
136
- CHECK_F( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) );
140
+ FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) , "");
137
141
 
138
142
  return 0;
139
143
  }
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2020, 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
@@ -16,7 +16,7 @@
16
16
  * Dependencies
17
17
  *********************************************************/
18
18
  #include <stddef.h> /* size_t */
19
- #include "zstd.h" /* ZSTD_DDict, and several public functions */
19
+ #include "../zstd.h" /* ZSTD_DDict, and several public functions */
20
20
 
21
21
 
22
22
  /*-*******************************************************
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2020, 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
@@ -56,19 +56,19 @@
56
56
  * Dependencies
57
57
  *********************************************************/
58
58
  #include <string.h> /* memcpy, memmove, memset */
59
- #include "cpu.h" /* bmi2 */
60
- #include "mem.h" /* low level memory routines */
59
+ #include "../common/cpu.h" /* bmi2 */
60
+ #include "../common/mem.h" /* low level memory routines */
61
61
  #define FSE_STATIC_LINKING_ONLY
62
- #include "fse.h"
62
+ #include "../common/fse.h"
63
63
  #define HUF_STATIC_LINKING_ONLY
64
- #include "huf.h"
65
- #include "zstd_internal.h" /* blockProperties_t */
64
+ #include "../common/huf.h"
65
+ #include "../common/zstd_internal.h" /* blockProperties_t */
66
66
  #include "zstd_decompress_internal.h" /* ZSTD_DCtx */
67
67
  #include "zstd_ddict.h" /* ZSTD_DDictDictContent */
68
68
  #include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
69
69
 
70
70
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
71
- # include "zstd_legacy.h"
71
+ # include "../legacy/zstd_legacy.h"
72
72
  #endif
73
73
 
74
74
 
@@ -88,10 +88,7 @@ size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
88
88
 
89
89
  static size_t ZSTD_startingInputLength(ZSTD_format_e format)
90
90
  {
91
- size_t const startingInputLength = (format==ZSTD_f_zstd1_magicless) ?
92
- ZSTD_FRAMEHEADERSIZE_PREFIX - ZSTD_FRAMEIDSIZE :
93
- ZSTD_FRAMEHEADERSIZE_PREFIX;
94
- ZSTD_STATIC_ASSERT(ZSTD_FRAMEHEADERSIZE_PREFIX >= ZSTD_FRAMEIDSIZE);
91
+ size_t const startingInputLength = ZSTD_FRAMEHEADERSIZE_PREFIX(format);
95
92
  /* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */
96
93
  assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) );
97
94
  return startingInputLength;
@@ -106,6 +103,7 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
106
103
  dctx->ddictLocal = NULL;
107
104
  dctx->dictEnd = NULL;
108
105
  dctx->ddictIsCold = 0;
106
+ dctx->dictUses = ZSTD_dont_use;
109
107
  dctx->inBuff = NULL;
110
108
  dctx->inBuffSize = 0;
111
109
  dctx->outBuffSize = 0;
@@ -113,7 +111,12 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
113
111
  dctx->legacyContext = NULL;
114
112
  dctx->previousLegacyVersion = 0;
115
113
  dctx->noForwardProgress = 0;
114
+ dctx->oversizedDuration = 0;
116
115
  dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
116
+ dctx->outBufferMode = ZSTD_obm_buffered;
117
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
118
+ dctx->dictContentEndForFuzzing = NULL;
119
+ #endif
117
120
  }
118
121
 
119
122
  ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
@@ -147,13 +150,20 @@ ZSTD_DCtx* ZSTD_createDCtx(void)
147
150
  return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
148
151
  }
149
152
 
153
+ static void ZSTD_clearDict(ZSTD_DCtx* dctx)
154
+ {
155
+ ZSTD_freeDDict(dctx->ddictLocal);
156
+ dctx->ddictLocal = NULL;
157
+ dctx->ddict = NULL;
158
+ dctx->dictUses = ZSTD_dont_use;
159
+ }
160
+
150
161
  size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
151
162
  {
152
163
  if (dctx==NULL) return 0; /* support free on NULL */
153
- if (dctx->staticSize) return ERROR(memory_allocation); /* not compatible with static DCtx */
164
+ RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
154
165
  { ZSTD_customMem const cMem = dctx->customMem;
155
- ZSTD_freeDDict(dctx->ddictLocal);
156
- dctx->ddictLocal = NULL;
166
+ ZSTD_clearDict(dctx);
157
167
  ZSTD_free(dctx->inBuff, cMem);
158
168
  dctx->inBuff = NULL;
159
169
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
@@ -203,7 +213,7 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
203
213
  static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
204
214
  {
205
215
  size_t const minInputSize = ZSTD_startingInputLength(format);
206
- if (srcSize < minInputSize) return ERROR(srcSize_wrong);
216
+ RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, "");
207
217
 
208
218
  { BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
209
219
  U32 const dictID= fhd & 3;
@@ -238,7 +248,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
238
248
 
239
249
  memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
240
250
  if (srcSize < minInputSize) return minInputSize;
241
- if (src==NULL) return ERROR(GENERIC); /* invalid parameter */
251
+ RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
242
252
 
243
253
  if ( (format != ZSTD_f_zstd1_magicless)
244
254
  && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
@@ -251,7 +261,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
251
261
  zfhPtr->frameType = ZSTD_skippableFrame;
252
262
  return 0;
253
263
  }
254
- return ERROR(prefix_unknown);
264
+ RETURN_ERROR(prefix_unknown, "");
255
265
  }
256
266
 
257
267
  /* ensure there is enough `srcSize` to fully read/decode frame header */
@@ -269,14 +279,13 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
269
279
  U64 windowSize = 0;
270
280
  U32 dictID = 0;
271
281
  U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
272
- if ((fhdByte & 0x08) != 0)
273
- return ERROR(frameParameter_unsupported); /* reserved bits, must be zero */
282
+ RETURN_ERROR_IF((fhdByte & 0x08) != 0, frameParameter_unsupported,
283
+ "reserved bits, must be zero");
274
284
 
275
285
  if (!singleSegment) {
276
286
  BYTE const wlByte = ip[pos++];
277
287
  U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
278
- if (windowLog > ZSTD_WINDOWLOG_MAX)
279
- return ERROR(frameParameter_windowTooLarge);
288
+ RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge, "");
280
289
  windowSize = (1ULL << windowLog);
281
290
  windowSize += (windowSize >> 3) * (wlByte&7);
282
291
  }
@@ -348,14 +357,16 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
348
357
  size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
349
358
  U32 sizeU32;
350
359
 
351
- if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
352
- return ERROR(srcSize_wrong);
360
+ RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
353
361
 
354
362
  sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
355
- if ((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32)
356
- return ERROR(frameParameter_unsupported);
357
-
358
- return skippableHeaderSize + sizeU32;
363
+ RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
364
+ frameParameter_unsupported, "");
365
+ {
366
+ size_t const skippableSize = skippableHeaderSize + sizeU32;
367
+ RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
368
+ return skippableSize;
369
+ }
359
370
  }
360
371
 
361
372
  /** ZSTD_findDecompressedSize() :
@@ -367,16 +378,15 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
367
378
  {
368
379
  unsigned long long totalDstSize = 0;
369
380
 
370
- while (srcSize >= ZSTD_FRAMEHEADERSIZE_PREFIX) {
381
+ while (srcSize >= ZSTD_startingInputLength(ZSTD_f_zstd1)) {
371
382
  U32 const magicNumber = MEM_readLE32(src);
372
383
 
373
384
  if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
374
385
  size_t const skippableSize = readSkippableFrameSize(src, srcSize);
375
- if (ZSTD_isError(skippableSize))
376
- return skippableSize;
377
- if (srcSize < skippableSize) {
386
+ if (ZSTD_isError(skippableSize)) {
378
387
  return ZSTD_CONTENTSIZE_ERROR;
379
388
  }
389
+ assert(skippableSize <= srcSize);
380
390
 
381
391
  src = (const BYTE *)src + skippableSize;
382
392
  srcSize -= skippableSize;
@@ -428,88 +438,137 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
428
438
  {
429
439
  size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
430
440
  if (ZSTD_isError(result)) return result; /* invalid header */
431
- if (result>0) return ERROR(srcSize_wrong); /* headerSize too small */
432
- if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID))
433
- return ERROR(dictionary_wrong);
441
+ RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
442
+ #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
443
+ /* Skip the dictID check in fuzzing mode, because it makes the search
444
+ * harder.
445
+ */
446
+ RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
447
+ dictionary_wrong, "");
448
+ #endif
434
449
  if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
435
450
  return 0;
436
451
  }
437
452
 
453
+ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
454
+ {
455
+ ZSTD_frameSizeInfo frameSizeInfo;
456
+ frameSizeInfo.compressedSize = ret;
457
+ frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
458
+ return frameSizeInfo;
459
+ }
438
460
 
439
- /** ZSTD_findFrameCompressedSize() :
440
- * compatible with legacy mode
441
- * `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
442
- * `srcSize` must be at least as large as the frame contained
443
- * @return : the compressed size of the frame starting at `src` */
444
- size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
461
+ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
445
462
  {
463
+ ZSTD_frameSizeInfo frameSizeInfo;
464
+ memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
465
+
446
466
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
447
467
  if (ZSTD_isLegacy(src, srcSize))
448
- return ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
468
+ return ZSTD_findFrameSizeInfoLegacy(src, srcSize);
449
469
  #endif
450
- if ( (srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
451
- && (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START ) {
452
- return readSkippableFrameSize(src, srcSize);
470
+
471
+ if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
472
+ && (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
473
+ frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
474
+ assert(ZSTD_isError(frameSizeInfo.compressedSize) ||
475
+ frameSizeInfo.compressedSize <= srcSize);
476
+ return frameSizeInfo;
453
477
  } else {
454
478
  const BYTE* ip = (const BYTE*)src;
455
479
  const BYTE* const ipstart = ip;
456
480
  size_t remainingSize = srcSize;
481
+ size_t nbBlocks = 0;
457
482
  ZSTD_frameHeader zfh;
458
483
 
459
484
  /* Extract Frame Header */
460
485
  { size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
461
- if (ZSTD_isError(ret)) return ret;
462
- if (ret > 0) return ERROR(srcSize_wrong);
486
+ if (ZSTD_isError(ret))
487
+ return ZSTD_errorFrameSizeInfo(ret);
488
+ if (ret > 0)
489
+ return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
463
490
  }
464
491
 
465
492
  ip += zfh.headerSize;
466
493
  remainingSize -= zfh.headerSize;
467
494
 
468
- /* Loop on each block */
495
+ /* Iterate over each block */
469
496
  while (1) {
470
497
  blockProperties_t blockProperties;
471
498
  size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
472
- if (ZSTD_isError(cBlockSize)) return cBlockSize;
499
+ if (ZSTD_isError(cBlockSize))
500
+ return ZSTD_errorFrameSizeInfo(cBlockSize);
473
501
 
474
502
  if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
475
- return ERROR(srcSize_wrong);
503
+ return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
476
504
 
477
505
  ip += ZSTD_blockHeaderSize + cBlockSize;
478
506
  remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
507
+ nbBlocks++;
479
508
 
480
509
  if (blockProperties.lastBlock) break;
481
510
  }
482
511
 
483
- if (zfh.checksumFlag) { /* Final frame content checksum */
484
- if (remainingSize < 4) return ERROR(srcSize_wrong);
512
+ /* Final frame content checksum */
513
+ if (zfh.checksumFlag) {
514
+ if (remainingSize < 4)
515
+ return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
485
516
  ip += 4;
486
517
  }
487
518
 
488
- return ip - ipstart;
519
+ frameSizeInfo.compressedSize = ip - ipstart;
520
+ frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
521
+ ? zfh.frameContentSize
522
+ : nbBlocks * zfh.blockSizeMax;
523
+ return frameSizeInfo;
489
524
  }
490
525
  }
491
526
 
527
+ /** ZSTD_findFrameCompressedSize() :
528
+ * compatible with legacy mode
529
+ * `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
530
+ * `srcSize` must be at least as large as the frame contained
531
+ * @return : the compressed size of the frame starting at `src` */
532
+ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
533
+ {
534
+ ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
535
+ return frameSizeInfo.compressedSize;
536
+ }
537
+
538
+ /** ZSTD_decompressBound() :
539
+ * compatible with legacy mode
540
+ * `src` must point to the start of a ZSTD frame or a skippeable frame
541
+ * `srcSize` must be at least as large as the frame contained
542
+ * @return : the maximum decompressed size of the compressed source
543
+ */
544
+ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
545
+ {
546
+ unsigned long long bound = 0;
547
+ /* Iterate over each frame */
548
+ while (srcSize > 0) {
549
+ ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
550
+ size_t const compressedSize = frameSizeInfo.compressedSize;
551
+ unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
552
+ if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
553
+ return ZSTD_CONTENTSIZE_ERROR;
554
+ assert(srcSize >= compressedSize);
555
+ src = (const BYTE*)src + compressedSize;
556
+ srcSize -= compressedSize;
557
+ bound += decompressedBound;
558
+ }
559
+ return bound;
560
+ }
492
561
 
493
562
 
494
563
  /*-*************************************************************
495
564
  * Frame decoding
496
565
  ***************************************************************/
497
566
 
498
-
499
- void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
500
- {
501
- if (dst != dctx->previousDstEnd) { /* not contiguous */
502
- dctx->dictEnd = dctx->previousDstEnd;
503
- dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
504
- dctx->prefixStart = dst;
505
- dctx->previousDstEnd = dst;
506
- }
507
- }
508
-
509
567
  /** ZSTD_insertBlock() :
510
- insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
568
+ * insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
511
569
  size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
512
570
  {
571
+ DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
513
572
  ZSTD_checkContinuity(dctx, blockStart);
514
573
  dctx->previousDstEnd = (const char*)blockStart + blockSize;
515
574
  return blockSize;
@@ -522,9 +581,9 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
522
581
  DEBUGLOG(5, "ZSTD_copyRawBlock");
523
582
  if (dst == NULL) {
524
583
  if (srcSize == 0) return 0;
525
- return ERROR(dstBuffer_null);
584
+ RETURN_ERROR(dstBuffer_null, "");
526
585
  }
527
- if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);
586
+ RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
528
587
  memcpy(dst, src, srcSize);
529
588
  return srcSize;
530
589
  }
@@ -535,9 +594,9 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
535
594
  {
536
595
  if (dst == NULL) {
537
596
  if (regenSize == 0) return 0;
538
- return ERROR(dstBuffer_null);
597
+ RETURN_ERROR(dstBuffer_null, "");
539
598
  }
540
- if (regenSize > dstCapacity) return ERROR(dstSize_tooSmall);
599
+ RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
541
600
  memset(dst, b, regenSize);
542
601
  return regenSize;
543
602
  }
@@ -553,22 +612,24 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
553
612
  {
554
613
  const BYTE* ip = (const BYTE*)(*srcPtr);
555
614
  BYTE* const ostart = (BYTE* const)dst;
556
- BYTE* const oend = ostart + dstCapacity;
615
+ BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
557
616
  BYTE* op = ostart;
558
617
  size_t remainingSrcSize = *srcSizePtr;
559
618
 
560
619
  DEBUGLOG(4, "ZSTD_decompressFrame (srcSize:%i)", (int)*srcSizePtr);
561
620
 
562
621
  /* check */
563
- if (remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN+ZSTD_blockHeaderSize)
564
- return ERROR(srcSize_wrong);
622
+ RETURN_ERROR_IF(
623
+ remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize,
624
+ srcSize_wrong, "");
565
625
 
566
626
  /* Frame Header */
567
- { size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_FRAMEHEADERSIZE_PREFIX);
627
+ { size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal(
628
+ ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format);
568
629
  if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
569
- if (remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize)
570
- return ERROR(srcSize_wrong);
571
- CHECK_F( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
630
+ RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
631
+ srcSize_wrong, "");
632
+ FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , "");
572
633
  ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
573
634
  }
574
635
 
@@ -581,7 +642,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
581
642
 
582
643
  ip += ZSTD_blockHeaderSize;
583
644
  remainingSrcSize -= ZSTD_blockHeaderSize;
584
- if (cBlockSize > remainingSrcSize) return ERROR(srcSize_wrong);
645
+ RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
585
646
 
586
647
  switch(blockProperties.blockType)
587
648
  {
@@ -596,28 +657,30 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
596
657
  break;
597
658
  case bt_reserved :
598
659
  default:
599
- return ERROR(corruption_detected);
660
+ RETURN_ERROR(corruption_detected, "invalid block type");
600
661
  }
601
662
 
602
663
  if (ZSTD_isError(decodedSize)) return decodedSize;
603
664
  if (dctx->fParams.checksumFlag)
604
665
  XXH64_update(&dctx->xxhState, op, decodedSize);
605
- op += decodedSize;
666
+ if (decodedSize != 0)
667
+ op += decodedSize;
668
+ assert(ip != NULL);
606
669
  ip += cBlockSize;
607
670
  remainingSrcSize -= cBlockSize;
608
671
  if (blockProperties.lastBlock) break;
609
672
  }
610
673
 
611
674
  if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
612
- if ((U64)(op-ostart) != dctx->fParams.frameContentSize) {
613
- return ERROR(corruption_detected);
614
- } }
675
+ RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
676
+ corruption_detected, "");
677
+ }
615
678
  if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
616
679
  U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
617
680
  U32 checkRead;
618
- if (remainingSrcSize<4) return ERROR(checksum_wrong);
681
+ RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
619
682
  checkRead = MEM_readLE32(ip);
620
- if (checkRead != checkCalc) return ERROR(checksum_wrong);
683
+ RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
621
684
  ip += 4;
622
685
  remainingSrcSize -= 4;
623
686
  }
@@ -645,15 +708,15 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
645
708
  dictSize = ZSTD_DDict_dictSize(ddict);
646
709
  }
647
710
 
648
- while (srcSize >= ZSTD_FRAMEHEADERSIZE_PREFIX) {
711
+ while (srcSize >= ZSTD_startingInputLength(dctx->format)) {
649
712
 
650
713
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
651
714
  if (ZSTD_isLegacy(src, srcSize)) {
652
715
  size_t decodedSize;
653
716
  size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
654
717
  if (ZSTD_isError(frameSize)) return frameSize;
655
- /* legacy support is not compatible with static dctx */
656
- if (dctx->staticSize) return ERROR(memory_allocation);
718
+ RETURN_ERROR_IF(dctx->staticSize, memory_allocation,
719
+ "legacy support is not compatible with static dctx");
657
720
 
658
721
  decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
659
722
  if (ZSTD_isError(decodedSize)) return decodedSize;
@@ -674,9 +737,8 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
674
737
  (unsigned)magicNumber, ZSTD_MAGICNUMBER);
675
738
  if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
676
739
  size_t const skippableSize = readSkippableFrameSize(src, srcSize);
677
- if (ZSTD_isError(skippableSize))
678
- return skippableSize;
679
- if (srcSize < skippableSize) return ERROR(srcSize_wrong);
740
+ FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed");
741
+ assert(skippableSize <= srcSize);
680
742
 
681
743
  src = (const BYTE *)src + skippableSize;
682
744
  srcSize -= skippableSize;
@@ -685,38 +747,39 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
685
747
 
686
748
  if (ddict) {
687
749
  /* we were called from ZSTD_decompress_usingDDict */
688
- CHECK_F(ZSTD_decompressBegin_usingDDict(dctx, ddict));
750
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict), "");
689
751
  } else {
690
752
  /* this will initialize correctly with no dict if dict == NULL, so
691
753
  * use this in all cases but ddict */
692
- CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
754
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
693
755
  }
694
756
  ZSTD_checkContinuity(dctx, dst);
695
757
 
696
758
  { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
697
759
  &src, &srcSize);
698
- if ( (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
699
- && (moreThan1Frame==1) ) {
700
- /* at least one frame successfully completed,
701
- * but following bytes are garbage :
702
- * it's more likely to be a srcSize error,
703
- * specifying more bytes than compressed size of frame(s).
704
- * This error message replaces ERROR(prefix_unknown),
705
- * which would be confusing, as the first header is actually correct.
706
- * Note that one could be unlucky, it might be a corruption error instead,
707
- * happening right at the place where we expect zstd magic bytes.
708
- * But this is _much_ less likely than a srcSize field error. */
709
- return ERROR(srcSize_wrong);
710
- }
760
+ RETURN_ERROR_IF(
761
+ (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
762
+ && (moreThan1Frame==1),
763
+ srcSize_wrong,
764
+ "at least one frame successfully completed, but following "
765
+ "bytes are garbage: it's more likely to be a srcSize error, "
766
+ "specifying more bytes than compressed size of frame(s). This "
767
+ "error message replaces ERROR(prefix_unknown), which would be "
768
+ "confusing, as the first header is actually correct. Note that "
769
+ "one could be unlucky, it might be a corruption error instead, "
770
+ "happening right at the place where we expect zstd magic "
771
+ "bytes. But this is _much_ less likely than a srcSize field "
772
+ "error.");
711
773
  if (ZSTD_isError(res)) return res;
712
774
  assert(res <= dstCapacity);
713
- dst = (BYTE*)dst + res;
775
+ if (res != 0)
776
+ dst = (BYTE*)dst + res;
714
777
  dstCapacity -= res;
715
778
  }
716
779
  moreThan1Frame = 1;
717
780
  } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
718
781
 
719
- if (srcSize) return ERROR(srcSize_wrong); /* input not entirely consumed */
782
+ RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
720
783
 
721
784
  return (BYTE*)dst - (BYTE*)dststart;
722
785
  }
@@ -730,9 +793,26 @@ size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
730
793
  }
731
794
 
732
795
 
796
+ static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
797
+ {
798
+ switch (dctx->dictUses) {
799
+ default:
800
+ assert(0 /* Impossible */);
801
+ /* fall-through */
802
+ case ZSTD_dont_use:
803
+ ZSTD_clearDict(dctx);
804
+ return NULL;
805
+ case ZSTD_use_indefinitely:
806
+ return dctx->ddict;
807
+ case ZSTD_use_once:
808
+ dctx->dictUses = ZSTD_dont_use;
809
+ return dctx->ddict;
810
+ }
811
+ }
812
+
733
813
  size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
734
814
  {
735
- return ZSTD_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);
815
+ return ZSTD_decompress_usingDDict(dctx, dst, dstCapacity, src, srcSize, ZSTD_getDDict(dctx));
736
816
  }
737
817
 
738
818
 
@@ -741,7 +821,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
741
821
  #if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
742
822
  size_t regenSize;
743
823
  ZSTD_DCtx* const dctx = ZSTD_createDCtx();
744
- if (dctx==NULL) return ERROR(memory_allocation);
824
+ RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
745
825
  regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
746
826
  ZSTD_freeDCtx(dctx);
747
827
  return regenSize;
@@ -759,6 +839,24 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
759
839
  ****************************************/
760
840
  size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
761
841
 
842
+ /**
843
+ * Similar to ZSTD_nextSrcSizeToDecompress(), but when when a block input can be streamed,
844
+ * we allow taking a partial block as the input. Currently only raw uncompressed blocks can
845
+ * be streamed.
846
+ *
847
+ * For blocks that can be streamed, this allows us to reduce the latency until we produce
848
+ * output, and avoid copying the input.
849
+ *
850
+ * @param inputSize - The total amount of input that the caller currently has.
851
+ */
852
+ static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) {
853
+ if (!(dctx->stage == ZSTDds_decompressBlock || dctx->stage == ZSTDds_decompressLastBlock))
854
+ return dctx->expected;
855
+ if (dctx->bType != bt_raw)
856
+ return dctx->expected;
857
+ return MIN(MAX(inputSize, 1), dctx->expected);
858
+ }
859
+
762
860
  ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
763
861
  switch(dctx->stage)
764
862
  {
@@ -791,8 +889,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
791
889
  {
792
890
  DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
793
891
  /* Sanity check */
794
- if (srcSize != dctx->expected)
795
- return ERROR(srcSize_wrong); /* not allowed */
892
+ RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
796
893
  if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
797
894
 
798
895
  switch (dctx->stage)
@@ -817,7 +914,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
817
914
  case ZSTDds_decodeFrameHeader:
818
915
  assert(src != NULL);
819
916
  memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
820
- CHECK_F(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
917
+ FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), "");
821
918
  dctx->expected = ZSTD_blockHeaderSize;
822
919
  dctx->stage = ZSTDds_decodeBlockHeader;
823
920
  return 0;
@@ -826,6 +923,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
826
923
  { blockProperties_t bp;
827
924
  size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
828
925
  if (ZSTD_isError(cBlockSize)) return cBlockSize;
926
+ RETURN_ERROR_IF(cBlockSize > dctx->fParams.blockSizeMax, corruption_detected, "Block Size Exceeds Maximum");
829
927
  dctx->expected = cBlockSize;
830
928
  dctx->bType = bp.blockType;
831
929
  dctx->rleSize = bp.origSize;
@@ -858,28 +956,41 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
858
956
  case bt_compressed:
859
957
  DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
860
958
  rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
959
+ dctx->expected = 0; /* Streaming not supported */
861
960
  break;
862
961
  case bt_raw :
962
+ assert(srcSize <= dctx->expected);
863
963
  rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
964
+ FORWARD_IF_ERROR(rSize, "ZSTD_copyRawBlock failed");
965
+ assert(rSize == srcSize);
966
+ dctx->expected -= rSize;
864
967
  break;
865
968
  case bt_rle :
866
969
  rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
970
+ dctx->expected = 0; /* Streaming not supported */
867
971
  break;
868
972
  case bt_reserved : /* should never happen */
869
973
  default:
870
- return ERROR(corruption_detected);
974
+ RETURN_ERROR(corruption_detected, "invalid block type");
871
975
  }
872
- if (ZSTD_isError(rSize)) return rSize;
976
+ FORWARD_IF_ERROR(rSize, "");
977
+ RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
873
978
  DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
874
979
  dctx->decodedSize += rSize;
875
980
  if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
981
+ dctx->previousDstEnd = (char*)dst + rSize;
982
+
983
+ /* Stay on the same stage until we are finished streaming the block. */
984
+ if (dctx->expected > 0) {
985
+ return rSize;
986
+ }
876
987
 
877
988
  if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
878
989
  DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
879
- if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
880
- if (dctx->decodedSize != dctx->fParams.frameContentSize) {
881
- return ERROR(corruption_detected);
882
- } }
990
+ RETURN_ERROR_IF(
991
+ dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
992
+ && dctx->decodedSize != dctx->fParams.frameContentSize,
993
+ corruption_detected, "");
883
994
  if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
884
995
  dctx->expected = 4;
885
996
  dctx->stage = ZSTDds_checkChecksum;
@@ -890,7 +1001,6 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
890
1001
  } else {
891
1002
  dctx->stage = ZSTDds_decodeBlockHeader;
892
1003
  dctx->expected = ZSTD_blockHeaderSize;
893
- dctx->previousDstEnd = (char*)dst + rSize;
894
1004
  }
895
1005
  return rSize;
896
1006
  }
@@ -900,7 +1010,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
900
1010
  { U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
901
1011
  U32 const check32 = MEM_readLE32(src);
902
1012
  DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
903
- if (check32 != h32) return ERROR(checksum_wrong);
1013
+ RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
904
1014
  dctx->expected = 0;
905
1015
  dctx->stage = ZSTDds_getFrameHeaderSize;
906
1016
  return 0;
@@ -921,7 +1031,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
921
1031
 
922
1032
  default:
923
1033
  assert(0); /* impossible */
924
- return ERROR(GENERIC); /* some compiler require default to do something */
1034
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
925
1035
  }
926
1036
  }
927
1037
 
@@ -932,6 +1042,10 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict
932
1042
  dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
933
1043
  dctx->prefixStart = dict;
934
1044
  dctx->previousDstEnd = (const char*)dict + dictSize;
1045
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1046
+ dctx->dictContentBeginForFuzzing = dctx->prefixStart;
1047
+ dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
1048
+ #endif
935
1049
  return 0;
936
1050
  }
937
1051
 
@@ -945,7 +1059,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
945
1059
  const BYTE* dictPtr = (const BYTE*)dict;
946
1060
  const BYTE* const dictEnd = dictPtr + dictSize;
947
1061
 
948
- if (dictSize <= 8) return ERROR(dictionary_corrupted);
1062
+ RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, "dict is too small");
949
1063
  assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
950
1064
  dictPtr += 8; /* skip header = magic + dictID */
951
1065
 
@@ -964,16 +1078,16 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
964
1078
  dictPtr, dictEnd - dictPtr,
965
1079
  workspace, workspaceSize);
966
1080
  #endif
967
- if (HUF_isError(hSize)) return ERROR(dictionary_corrupted);
1081
+ RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
968
1082
  dictPtr += hSize;
969
1083
  }
970
1084
 
971
1085
  { short offcodeNCount[MaxOff+1];
972
1086
  unsigned offcodeMaxValue = MaxOff, offcodeLog;
973
1087
  size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
974
- if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
975
- if (offcodeMaxValue > MaxOff) return ERROR(dictionary_corrupted);
976
- if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
1088
+ RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
1089
+ RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, "");
1090
+ RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
977
1091
  ZSTD_buildFSETable( entropy->OFTable,
978
1092
  offcodeNCount, offcodeMaxValue,
979
1093
  OF_base, OF_bits,
@@ -984,9 +1098,9 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
984
1098
  { short matchlengthNCount[MaxML+1];
985
1099
  unsigned matchlengthMaxValue = MaxML, matchlengthLog;
986
1100
  size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
987
- if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
988
- if (matchlengthMaxValue > MaxML) return ERROR(dictionary_corrupted);
989
- if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
1101
+ RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
1102
+ RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, "");
1103
+ RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
990
1104
  ZSTD_buildFSETable( entropy->MLTable,
991
1105
  matchlengthNCount, matchlengthMaxValue,
992
1106
  ML_base, ML_bits,
@@ -997,9 +1111,9 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
997
1111
  { short litlengthNCount[MaxLL+1];
998
1112
  unsigned litlengthMaxValue = MaxLL, litlengthLog;
999
1113
  size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
1000
- if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
1001
- if (litlengthMaxValue > MaxLL) return ERROR(dictionary_corrupted);
1002
- if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
1114
+ RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
1115
+ RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, "");
1116
+ RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
1003
1117
  ZSTD_buildFSETable( entropy->LLTable,
1004
1118
  litlengthNCount, litlengthMaxValue,
1005
1119
  LL_base, LL_bits,
@@ -1007,12 +1121,13 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1007
1121
  dictPtr += litlengthHeaderSize;
1008
1122
  }
1009
1123
 
1010
- if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
1124
+ RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
1011
1125
  { int i;
1012
1126
  size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
1013
1127
  for (i=0; i<3; i++) {
1014
1128
  U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
1015
- if (rep==0 || rep >= dictContentSize) return ERROR(dictionary_corrupted);
1129
+ RETURN_ERROR_IF(rep==0 || rep > dictContentSize,
1130
+ dictionary_corrupted, "");
1016
1131
  entropy->rep[i] = rep;
1017
1132
  } }
1018
1133
 
@@ -1030,7 +1145,7 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
1030
1145
 
1031
1146
  /* load entropy tables */
1032
1147
  { size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
1033
- if (ZSTD_isError(eSize)) return ERROR(dictionary_corrupted);
1148
+ RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, "");
1034
1149
  dict = (const char*)dict + eSize;
1035
1150
  dictSize -= eSize;
1036
1151
  }
@@ -1053,6 +1168,7 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1053
1168
  dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
1054
1169
  dctx->litEntropy = dctx->fseEntropy = 0;
1055
1170
  dctx->dictID = 0;
1171
+ dctx->bType = bt_reserved;
1056
1172
  ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
1057
1173
  memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
1058
1174
  dctx->LLTptr = dctx->entropy.LLTable;
@@ -1064,9 +1180,11 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1064
1180
 
1065
1181
  size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1066
1182
  {
1067
- CHECK_F( ZSTD_decompressBegin(dctx) );
1183
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
1068
1184
  if (dict && dictSize)
1069
- CHECK_E(ZSTD_decompress_insertDictionary(dctx, dict, dictSize), dictionary_corrupted);
1185
+ RETURN_ERROR_IF(
1186
+ ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
1187
+ dictionary_corrupted, "");
1070
1188
  return 0;
1071
1189
  }
1072
1190
 
@@ -1085,7 +1203,7 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1085
1203
  DEBUGLOG(4, "DDict is %s",
1086
1204
  dctx->ddictIsCold ? "~cold~" : "hot!");
1087
1205
  }
1088
- CHECK_F( ZSTD_decompressBegin(dctx) );
1206
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
1089
1207
  if (ddict) { /* NULL ddict is equivalent to no dictionary */
1090
1208
  ZSTD_copyDDictParameters(dctx, ddict);
1091
1209
  }
@@ -1104,7 +1222,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
1104
1222
  }
1105
1223
 
1106
1224
  /*! ZSTD_getDictID_fromFrame() :
1107
- * Provides the dictID required to decompresse frame stored within `src`.
1225
+ * Provides the dictID required to decompress frame stored within `src`.
1108
1226
  * If @return == 0, the dictID could not be decoded.
1109
1227
  * This could for one of the following reasons :
1110
1228
  * - The frame does not require a dictionary (most common case).
@@ -1176,15 +1294,14 @@ size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
1176
1294
  ZSTD_dictLoadMethod_e dictLoadMethod,
1177
1295
  ZSTD_dictContentType_e dictContentType)
1178
1296
  {
1179
- if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
1180
- ZSTD_freeDDict(dctx->ddictLocal);
1181
- if (dict && dictSize >= 8) {
1297
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1298
+ ZSTD_clearDict(dctx);
1299
+ if (dict && dictSize != 0) {
1182
1300
  dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
1183
- if (dctx->ddictLocal == NULL) return ERROR(memory_allocation);
1184
- } else {
1185
- dctx->ddictLocal = NULL;
1301
+ RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, "NULL pointer!");
1302
+ dctx->ddict = dctx->ddictLocal;
1303
+ dctx->dictUses = ZSTD_use_indefinitely;
1186
1304
  }
1187
- dctx->ddict = dctx->ddictLocal;
1188
1305
  return 0;
1189
1306
  }
1190
1307
 
@@ -1200,7 +1317,9 @@ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
1200
1317
 
1201
1318
  size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
1202
1319
  {
1203
- return ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType);
1320
+ FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), "");
1321
+ dctx->dictUses = ZSTD_use_once;
1322
+ return 0;
1204
1323
  }
1205
1324
 
1206
1325
  size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)
@@ -1210,22 +1329,21 @@ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSiz
1210
1329
 
1211
1330
 
1212
1331
  /* ZSTD_initDStream_usingDict() :
1213
- * return : expected size, aka ZSTD_FRAMEHEADERSIZE_PREFIX.
1332
+ * return : expected size, aka ZSTD_startingInputLength().
1214
1333
  * this function cannot fail */
1215
1334
  size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
1216
1335
  {
1217
1336
  DEBUGLOG(4, "ZSTD_initDStream_usingDict");
1218
- zds->streamStage = zdss_init;
1219
- zds->noForwardProgress = 0;
1220
- CHECK_F( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
1221
- return ZSTD_FRAMEHEADERSIZE_PREFIX;
1337
+ FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) , "");
1338
+ FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , "");
1339
+ return ZSTD_startingInputLength(zds->format);
1222
1340
  }
1223
1341
 
1224
1342
  /* note : this variant can't fail */
1225
1343
  size_t ZSTD_initDStream(ZSTD_DStream* zds)
1226
1344
  {
1227
1345
  DEBUGLOG(4, "ZSTD_initDStream");
1228
- return ZSTD_initDStream_usingDict(zds, NULL, 0);
1346
+ return ZSTD_initDStream_usingDDict(zds, NULL);
1229
1347
  }
1230
1348
 
1231
1349
  /* ZSTD_initDStream_usingDDict() :
@@ -1233,29 +1351,29 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
1233
1351
  * this function cannot fail */
1234
1352
  size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1235
1353
  {
1236
- size_t const initResult = ZSTD_initDStream(dctx);
1237
- dctx->ddict = ddict;
1238
- return initResult;
1354
+ FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
1355
+ FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
1356
+ return ZSTD_startingInputLength(dctx->format);
1239
1357
  }
1240
1358
 
1241
1359
  /* ZSTD_resetDStream() :
1242
- * return : expected size, aka ZSTD_FRAMEHEADERSIZE_PREFIX.
1360
+ * return : expected size, aka ZSTD_startingInputLength().
1243
1361
  * this function cannot fail */
1244
1362
  size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
1245
1363
  {
1246
- DEBUGLOG(4, "ZSTD_resetDStream");
1247
- dctx->streamStage = zdss_loadHeader;
1248
- dctx->lhSize = dctx->inPos = dctx->outStart = dctx->outEnd = 0;
1249
- dctx->legacyVersion = 0;
1250
- dctx->hostageByte = 0;
1251
- return ZSTD_FRAMEHEADERSIZE_PREFIX;
1364
+ FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
1365
+ return ZSTD_startingInputLength(dctx->format);
1252
1366
  }
1253
1367
 
1254
1368
 
1255
1369
  size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1256
1370
  {
1257
- if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
1258
- dctx->ddict = ddict;
1371
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1372
+ ZSTD_clearDict(dctx);
1373
+ if (ddict) {
1374
+ dctx->ddict = ddict;
1375
+ dctx->dictUses = ZSTD_use_indefinitely;
1376
+ }
1259
1377
  return 0;
1260
1378
  }
1261
1379
 
@@ -1267,9 +1385,9 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
1267
1385
  ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
1268
1386
  size_t const min = (size_t)1 << bounds.lowerBound;
1269
1387
  size_t const max = (size_t)1 << bounds.upperBound;
1270
- if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
1271
- if (maxWindowSize < min) return ERROR(parameter_outOfBound);
1272
- if (maxWindowSize > max) return ERROR(parameter_outOfBound);
1388
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1389
+ RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound, "");
1390
+ RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound, "");
1273
1391
  dctx->maxWindowSize = maxWindowSize;
1274
1392
  return 0;
1275
1393
  }
@@ -1292,6 +1410,10 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
1292
1410
  bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
1293
1411
  ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
1294
1412
  return bounds;
1413
+ case ZSTD_d_stableOutBuffer:
1414
+ bounds.lowerBound = (int)ZSTD_obm_buffered;
1415
+ bounds.upperBound = (int)ZSTD_obm_stable;
1416
+ return bounds;
1295
1417
  default:;
1296
1418
  }
1297
1419
  bounds.error = ERROR(parameter_unsupported);
@@ -1311,15 +1433,15 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
1311
1433
  }
1312
1434
 
1313
1435
  #define CHECK_DBOUNDS(p,v) { \
1314
- if (!ZSTD_dParam_withinBounds(p, v)) \
1315
- return ERROR(parameter_outOfBound); \
1436
+ RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
1316
1437
  }
1317
1438
 
1318
1439
  size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
1319
1440
  {
1320
- if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
1441
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1321
1442
  switch(dParam) {
1322
1443
  case ZSTD_d_windowLogMax:
1444
+ if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
1323
1445
  CHECK_DBOUNDS(ZSTD_d_windowLogMax, value);
1324
1446
  dctx->maxWindowSize = ((size_t)1) << value;
1325
1447
  return 0;
@@ -1327,21 +1449,26 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
1327
1449
  CHECK_DBOUNDS(ZSTD_d_format, value);
1328
1450
  dctx->format = (ZSTD_format_e)value;
1329
1451
  return 0;
1452
+ case ZSTD_d_stableOutBuffer:
1453
+ CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
1454
+ dctx->outBufferMode = (ZSTD_outBufferMode_e)value;
1455
+ return 0;
1330
1456
  default:;
1331
1457
  }
1332
- return ERROR(parameter_unsupported);
1458
+ RETURN_ERROR(parameter_unsupported, "");
1333
1459
  }
1334
1460
 
1335
1461
  size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
1336
1462
  {
1337
1463
  if ( (reset == ZSTD_reset_session_only)
1338
1464
  || (reset == ZSTD_reset_session_and_parameters) ) {
1339
- (void)ZSTD_initDStream(dctx);
1465
+ dctx->streamStage = zdss_init;
1466
+ dctx->noForwardProgress = 0;
1340
1467
  }
1341
1468
  if ( (reset == ZSTD_reset_parameters)
1342
1469
  || (reset == ZSTD_reset_session_and_parameters) ) {
1343
- if (dctx->streamStage != zdss_init)
1344
- return ERROR(stage_wrong);
1470
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1471
+ ZSTD_clearDict(dctx);
1345
1472
  dctx->format = ZSTD_f_zstd1;
1346
1473
  dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
1347
1474
  }
@@ -1360,7 +1487,8 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
1360
1487
  unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
1361
1488
  unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
1362
1489
  size_t const minRBSize = (size_t) neededSize;
1363
- if ((unsigned long long)minRBSize != neededSize) return ERROR(frameParameter_windowTooLarge);
1490
+ RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
1491
+ frameParameter_windowTooLarge, "");
1364
1492
  return minRBSize;
1365
1493
  }
1366
1494
 
@@ -1378,60 +1506,129 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
1378
1506
  ZSTD_frameHeader zfh;
1379
1507
  size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
1380
1508
  if (ZSTD_isError(err)) return err;
1381
- if (err>0) return ERROR(srcSize_wrong);
1382
- if (zfh.windowSize > windowSizeMax)
1383
- return ERROR(frameParameter_windowTooLarge);
1509
+ RETURN_ERROR_IF(err>0, srcSize_wrong, "");
1510
+ RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
1511
+ frameParameter_windowTooLarge, "");
1384
1512
  return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
1385
1513
  }
1386
1514
 
1387
1515
 
1388
1516
  /* ***** Decompression ***** */
1389
1517
 
1390
- MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1518
+ static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
1391
1519
  {
1392
- size_t const length = MIN(dstCapacity, srcSize);
1393
- memcpy(dst, src, length);
1394
- return length;
1520
+ return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;
1521
+ }
1522
+
1523
+ static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
1524
+ {
1525
+ if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
1526
+ zds->oversizedDuration++;
1527
+ else
1528
+ zds->oversizedDuration = 0;
1529
+ }
1530
+
1531
+ static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)
1532
+ {
1533
+ return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;
1534
+ }
1535
+
1536
+ /* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */
1537
+ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)
1538
+ {
1539
+ ZSTD_outBuffer const expect = zds->expectedOutBuffer;
1540
+ /* No requirement when ZSTD_obm_stable is not enabled. */
1541
+ if (zds->outBufferMode != ZSTD_obm_stable)
1542
+ return 0;
1543
+ /* Any buffer is allowed in zdss_init, this must be the same for every other call until
1544
+ * the context is reset.
1545
+ */
1546
+ if (zds->streamStage == zdss_init)
1547
+ return 0;
1548
+ /* The buffer must match our expectation exactly. */
1549
+ if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
1550
+ return 0;
1551
+ RETURN_ERROR(dstBuffer_wrong, "ZSTD_obm_stable enabled but output differs!");
1395
1552
  }
1396
1553
 
1554
+ /* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
1555
+ * and updates the stage and the output buffer state. This call is extracted so it can be
1556
+ * used both when reading directly from the ZSTD_inBuffer, and in buffered input mode.
1557
+ * NOTE: You must break after calling this function since the streamStage is modified.
1558
+ */
1559
+ static size_t ZSTD_decompressContinueStream(
1560
+ ZSTD_DStream* zds, char** op, char* oend,
1561
+ void const* src, size_t srcSize) {
1562
+ int const isSkipFrame = ZSTD_isSkipFrame(zds);
1563
+ if (zds->outBufferMode == ZSTD_obm_buffered) {
1564
+ size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
1565
+ size_t const decodedSize = ZSTD_decompressContinue(zds,
1566
+ zds->outBuff + zds->outStart, dstSize, src, srcSize);
1567
+ FORWARD_IF_ERROR(decodedSize, "");
1568
+ if (!decodedSize && !isSkipFrame) {
1569
+ zds->streamStage = zdss_read;
1570
+ } else {
1571
+ zds->outEnd = zds->outStart + decodedSize;
1572
+ zds->streamStage = zdss_flush;
1573
+ }
1574
+ } else {
1575
+ /* Write directly into the output buffer */
1576
+ size_t const dstSize = isSkipFrame ? 0 : oend - *op;
1577
+ size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
1578
+ FORWARD_IF_ERROR(decodedSize, "");
1579
+ *op += decodedSize;
1580
+ /* Flushing is not needed. */
1581
+ zds->streamStage = zdss_read;
1582
+ assert(*op <= oend);
1583
+ assert(zds->outBufferMode == ZSTD_obm_stable);
1584
+ }
1585
+ return 0;
1586
+ }
1397
1587
 
1398
1588
  size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
1399
1589
  {
1400
- const char* const istart = (const char*)(input->src) + input->pos;
1401
- const char* const iend = (const char*)(input->src) + input->size;
1590
+ const char* const src = (const char*)input->src;
1591
+ const char* const istart = input->pos != 0 ? src + input->pos : src;
1592
+ const char* const iend = input->size != 0 ? src + input->size : src;
1402
1593
  const char* ip = istart;
1403
- char* const ostart = (char*)(output->dst) + output->pos;
1404
- char* const oend = (char*)(output->dst) + output->size;
1594
+ char* const dst = (char*)output->dst;
1595
+ char* const ostart = output->pos != 0 ? dst + output->pos : dst;
1596
+ char* const oend = output->size != 0 ? dst + output->size : dst;
1405
1597
  char* op = ostart;
1406
1598
  U32 someMoreWork = 1;
1407
1599
 
1408
1600
  DEBUGLOG(5, "ZSTD_decompressStream");
1409
- if (input->pos > input->size) { /* forbidden */
1410
- DEBUGLOG(5, "in: pos: %u vs size: %u",
1411
- (U32)input->pos, (U32)input->size);
1412
- return ERROR(srcSize_wrong);
1413
- }
1414
- if (output->pos > output->size) { /* forbidden */
1415
- DEBUGLOG(5, "out: pos: %u vs size: %u",
1416
- (U32)output->pos, (U32)output->size);
1417
- return ERROR(dstSize_tooSmall);
1418
- }
1601
+ RETURN_ERROR_IF(
1602
+ input->pos > input->size,
1603
+ srcSize_wrong,
1604
+ "forbidden. in: pos: %u vs size: %u",
1605
+ (U32)input->pos, (U32)input->size);
1606
+ RETURN_ERROR_IF(
1607
+ output->pos > output->size,
1608
+ dstSize_tooSmall,
1609
+ "forbidden. out: pos: %u vs size: %u",
1610
+ (U32)output->pos, (U32)output->size);
1419
1611
  DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
1612
+ FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), "");
1420
1613
 
1421
1614
  while (someMoreWork) {
1422
1615
  switch(zds->streamStage)
1423
1616
  {
1424
1617
  case zdss_init :
1425
1618
  DEBUGLOG(5, "stage zdss_init => transparent reset ");
1426
- ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */
1619
+ zds->streamStage = zdss_loadHeader;
1620
+ zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
1621
+ zds->legacyVersion = 0;
1622
+ zds->hostageByte = 0;
1623
+ zds->expectedOutBuffer = *output;
1427
1624
  /* fall-through */
1428
1625
 
1429
1626
  case zdss_loadHeader :
1430
1627
  DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
1431
1628
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1432
1629
  if (zds->legacyVersion) {
1433
- /* legacy support is incompatible with static dctx */
1434
- if (zds->staticSize) return ERROR(memory_allocation);
1630
+ RETURN_ERROR_IF(zds->staticSize, memory_allocation,
1631
+ "legacy support is incompatible with static dctx");
1435
1632
  { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
1436
1633
  if (hint==0) zds->streamStage = zdss_init;
1437
1634
  return hint;
@@ -1443,14 +1640,15 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1443
1640
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1444
1641
  U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
1445
1642
  if (legacyVersion) {
1446
- const void* const dict = zds->ddict ? ZSTD_DDict_dictContent(zds->ddict) : NULL;
1447
- size_t const dictSize = zds->ddict ? ZSTD_DDict_dictSize(zds->ddict) : 0;
1643
+ ZSTD_DDict const* const ddict = ZSTD_getDDict(zds);
1644
+ const void* const dict = ddict ? ZSTD_DDict_dictContent(ddict) : NULL;
1645
+ size_t const dictSize = ddict ? ZSTD_DDict_dictSize(ddict) : 0;
1448
1646
  DEBUGLOG(5, "ZSTD_decompressStream: detected legacy version v0.%u", legacyVersion);
1449
- /* legacy support is incompatible with static dctx */
1450
- if (zds->staticSize) return ERROR(memory_allocation);
1451
- CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext,
1647
+ RETURN_ERROR_IF(zds->staticSize, memory_allocation,
1648
+ "legacy support is incompatible with static dctx");
1649
+ FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
1452
1650
  zds->previousLegacyVersion, legacyVersion,
1453
- dict, dictSize));
1651
+ dict, dictSize), "");
1454
1652
  zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
1455
1653
  { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
1456
1654
  if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */
@@ -1469,7 +1667,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1469
1667
  zds->lhSize += remainingInput;
1470
1668
  }
1471
1669
  input->pos = input->size;
1472
- return (MAX(ZSTD_FRAMEHEADERSIZE_MIN, hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
1670
+ return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
1473
1671
  }
1474
1672
  assert(ip != NULL);
1475
1673
  memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
@@ -1477,12 +1675,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1477
1675
  } }
1478
1676
 
1479
1677
  /* check for single-pass mode opportunity */
1480
- if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */
1678
+ if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
1679
+ && zds->fParams.frameType != ZSTD_skippableFrame
1481
1680
  && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
1482
1681
  size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
1483
1682
  if (cSize <= (size_t)(iend-istart)) {
1484
1683
  /* shortcut : using single-pass mode */
1485
- size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, zds->ddict);
1684
+ size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds));
1486
1685
  if (ZSTD_isError(decompressedSize)) return decompressedSize;
1487
1686
  DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
1488
1687
  ip = istart + cSize;
@@ -1493,15 +1692,23 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1493
1692
  break;
1494
1693
  } }
1495
1694
 
1695
+ /* Check output buffer is large enough for ZSTD_odm_stable. */
1696
+ if (zds->outBufferMode == ZSTD_obm_stable
1697
+ && zds->fParams.frameType != ZSTD_skippableFrame
1698
+ && zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
1699
+ && (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
1700
+ RETURN_ERROR(dstSize_tooSmall, "ZSTD_obm_stable passed but ZSTD_outBuffer is too small");
1701
+ }
1702
+
1496
1703
  /* Consume header (see ZSTDds_decodeFrameHeader) */
1497
1704
  DEBUGLOG(4, "Consume header");
1498
- CHECK_F(ZSTD_decompressBegin_usingDDict(zds, zds->ddict));
1705
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
1499
1706
 
1500
1707
  if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
1501
1708
  zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
1502
1709
  zds->stage = ZSTDds_skipFrame;
1503
1710
  } else {
1504
- CHECK_F(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
1711
+ FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), "");
1505
1712
  zds->expected = ZSTD_blockHeaderSize;
1506
1713
  zds->stage = ZSTDds_decodeBlockHeader;
1507
1714
  }
@@ -1511,39 +1718,49 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1511
1718
  (U32)(zds->fParams.windowSize >>10),
1512
1719
  (U32)(zds->maxWindowSize >> 10) );
1513
1720
  zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
1514
- if (zds->fParams.windowSize > zds->maxWindowSize) return ERROR(frameParameter_windowTooLarge);
1721
+ RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
1722
+ frameParameter_windowTooLarge, "");
1515
1723
 
1516
1724
  /* Adapt buffer sizes to frame header instructions */
1517
1725
  { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
1518
- size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize);
1519
- if ((zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize)) {
1520
- size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
1521
- DEBUGLOG(4, "inBuff : from %u to %u",
1522
- (U32)zds->inBuffSize, (U32)neededInBuffSize);
1523
- DEBUGLOG(4, "outBuff : from %u to %u",
1524
- (U32)zds->outBuffSize, (U32)neededOutBuffSize);
1525
- if (zds->staticSize) { /* static DCtx */
1526
- DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
1527
- assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
1528
- if (bufferSize > zds->staticSize - sizeof(ZSTD_DCtx))
1529
- return ERROR(memory_allocation);
1530
- } else {
1531
- ZSTD_free(zds->inBuff, zds->customMem);
1532
- zds->inBuffSize = 0;
1533
- zds->outBuffSize = 0;
1534
- zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
1535
- if (zds->inBuff == NULL) return ERROR(memory_allocation);
1536
- }
1537
- zds->inBuffSize = neededInBuffSize;
1538
- zds->outBuff = zds->inBuff + zds->inBuffSize;
1539
- zds->outBuffSize = neededOutBuffSize;
1540
- } }
1726
+ size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_obm_buffered
1727
+ ? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
1728
+ : 0;
1729
+
1730
+ ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
1731
+
1732
+ { int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
1733
+ int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
1734
+
1735
+ if (tooSmall || tooLarge) {
1736
+ size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
1737
+ DEBUGLOG(4, "inBuff : from %u to %u",
1738
+ (U32)zds->inBuffSize, (U32)neededInBuffSize);
1739
+ DEBUGLOG(4, "outBuff : from %u to %u",
1740
+ (U32)zds->outBuffSize, (U32)neededOutBuffSize);
1741
+ if (zds->staticSize) { /* static DCtx */
1742
+ DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
1743
+ assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
1744
+ RETURN_ERROR_IF(
1745
+ bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
1746
+ memory_allocation, "");
1747
+ } else {
1748
+ ZSTD_free(zds->inBuff, zds->customMem);
1749
+ zds->inBuffSize = 0;
1750
+ zds->outBuffSize = 0;
1751
+ zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
1752
+ RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, "");
1753
+ }
1754
+ zds->inBuffSize = neededInBuffSize;
1755
+ zds->outBuff = zds->inBuff + zds->inBuffSize;
1756
+ zds->outBuffSize = neededOutBuffSize;
1757
+ } } }
1541
1758
  zds->streamStage = zdss_read;
1542
1759
  /* fall-through */
1543
1760
 
1544
1761
  case zdss_read:
1545
1762
  DEBUGLOG(5, "stage zdss_read");
1546
- { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
1763
+ { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip);
1547
1764
  DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
1548
1765
  if (neededInSize==0) { /* end of frame */
1549
1766
  zds->streamStage = zdss_init;
@@ -1551,15 +1768,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1551
1768
  break;
1552
1769
  }
1553
1770
  if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
1554
- int const isSkipFrame = ZSTD_isSkipFrame(zds);
1555
- size_t const decodedSize = ZSTD_decompressContinue(zds,
1556
- zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart),
1557
- ip, neededInSize);
1558
- if (ZSTD_isError(decodedSize)) return decodedSize;
1771
+ FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
1559
1772
  ip += neededInSize;
1560
- if (!decodedSize && !isSkipFrame) break; /* this was just a header */
1561
- zds->outEnd = zds->outStart + decodedSize;
1562
- zds->streamStage = zdss_flush;
1773
+ /* Function modifies the stage so we must break */
1563
1774
  break;
1564
1775
  } }
1565
1776
  if (ip==iend) { someMoreWork = 0; break; } /* no more input */
@@ -1571,10 +1782,14 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1571
1782
  size_t const toLoad = neededInSize - zds->inPos;
1572
1783
  int const isSkipFrame = ZSTD_isSkipFrame(zds);
1573
1784
  size_t loadedSize;
1785
+ /* At this point we shouldn't be decompressing a block that we can stream. */
1786
+ assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
1574
1787
  if (isSkipFrame) {
1575
1788
  loadedSize = MIN(toLoad, (size_t)(iend-ip));
1576
1789
  } else {
1577
- if (toLoad > zds->inBuffSize - zds->inPos) return ERROR(corruption_detected); /* should never happen */
1790
+ RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
1791
+ corruption_detected,
1792
+ "should never happen");
1578
1793
  loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
1579
1794
  }
1580
1795
  ip += loadedSize;
@@ -1582,17 +1797,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1582
1797
  if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
1583
1798
 
1584
1799
  /* decode loaded input */
1585
- { size_t const decodedSize = ZSTD_decompressContinue(zds,
1586
- zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart,
1587
- zds->inBuff, neededInSize);
1588
- if (ZSTD_isError(decodedSize)) return decodedSize;
1589
- zds->inPos = 0; /* input is consumed */
1590
- if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; break; } /* this was just a header */
1591
- zds->outEnd = zds->outStart + decodedSize;
1592
- } }
1593
- zds->streamStage = zdss_flush;
1594
- /* fall-through */
1595
-
1800
+ zds->inPos = 0; /* input is consumed */
1801
+ FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize), "");
1802
+ /* Function modifies the stage so we must break */
1803
+ break;
1804
+ }
1596
1805
  case zdss_flush:
1597
1806
  { size_t const toFlushSize = zds->outEnd - zds->outStart;
1598
1807
  size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
@@ -1615,17 +1824,21 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1615
1824
 
1616
1825
  default:
1617
1826
  assert(0); /* impossible */
1618
- return ERROR(GENERIC); /* some compiler require default to do something */
1827
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
1619
1828
  } }
1620
1829
 
1621
1830
  /* result */
1622
1831
  input->pos = (size_t)(ip - (const char*)(input->src));
1623
1832
  output->pos = (size_t)(op - (char*)(output->dst));
1833
+
1834
+ /* Update the expected output buffer for ZSTD_obm_stable. */
1835
+ zds->expectedOutBuffer = *output;
1836
+
1624
1837
  if ((ip==istart) && (op==ostart)) { /* no forward progress */
1625
1838
  zds->noForwardProgress ++;
1626
1839
  if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
1627
- if (op==oend) return ERROR(dstSize_tooSmall);
1628
- if (ip==iend) return ERROR(srcSize_wrong);
1840
+ RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
1841
+ RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
1629
1842
  assert(0);
1630
1843
  }
1631
1844
  } else {