Skip to content

Commit 117bb29

Browse files
[3.14] gh-132983: Split _zstd_set_c_parameters (GH-133921) (#134838)
gh-132983: Split ``_zstd_set_c_parameters`` (GH-133921) (cherry picked from commit 11f7a93) Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
1 parent 072d033 commit 117bb29

File tree

6 files changed

+228
-157
lines changed

6 files changed

+228
-157
lines changed

Lib/compression/zstd/_zstdfile.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import io
22
from os import PathLike
3-
from _zstd import (ZstdCompressor, ZstdDecompressor, ZstdError,
4-
ZSTD_DStreamOutSize)
3+
from _zstd import ZstdCompressor, ZstdDecompressor, ZSTD_DStreamOutSize
54
from compression._common import _streams
65

76
__all__ = ('ZstdFile', 'open')

Lib/test/test_zstd.py

Lines changed: 105 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@
6565

6666
SUPPORT_MULTITHREADING = False
6767

68+
C_INT_MIN = -(2**31)
69+
C_INT_MAX = (2**31) - 1
70+
71+
6872
def setUpModule():
6973
global SUPPORT_MULTITHREADING
7074
SUPPORT_MULTITHREADING = CompressionParameter.nb_workers.bounds() != (0, 0)
@@ -196,14 +200,21 @@ def test_simple_compress_bad_args(self):
196200
self.assertRaises(TypeError, ZstdCompressor, zstd_dict=b"abcd1234")
197201
self.assertRaises(TypeError, ZstdCompressor, zstd_dict={1: 2, 3: 4})
198202

199-
with self.assertRaises(ValueError):
200-
ZstdCompressor(2**31)
201-
with self.assertRaises(ValueError):
202-
ZstdCompressor(options={2**31: 100})
203+
# valid range for compression level is [-(1<<17), 22]
204+
msg = r'illegal compression level {}; the valid range is \[-?\d+, -?\d+\]'
205+
with self.assertRaisesRegex(ValueError, msg.format(C_INT_MAX)):
206+
ZstdCompressor(C_INT_MAX)
207+
with self.assertRaisesRegex(ValueError, msg.format(C_INT_MIN)):
208+
ZstdCompressor(C_INT_MIN)
209+
msg = r'illegal compression level; the valid range is \[-?\d+, -?\d+\]'
210+
with self.assertRaisesRegex(ValueError, msg):
211+
ZstdCompressor(level=-(2**1000))
212+
with self.assertRaisesRegex(ValueError, msg):
213+
ZstdCompressor(level=2**1000)
203214

204-
with self.assertRaises(ZstdError):
215+
with self.assertRaises(ValueError):
205216
ZstdCompressor(options={CompressionParameter.window_log: 100})
206-
with self.assertRaises(ZstdError):
217+
with self.assertRaises(ValueError):
207218
ZstdCompressor(options={3333: 100})
208219

209220
# Method bad arguments
@@ -254,18 +265,32 @@ def test_compress_parameters(self):
254265
}
255266
ZstdCompressor(options=d)
256267

257-
# larger than signed int, ValueError
258268
d1 = d.copy()
259-
d1[CompressionParameter.ldm_bucket_size_log] = 2**31
260-
self.assertRaises(ValueError, ZstdCompressor, options=d1)
269+
# larger than signed int
270+
d1[CompressionParameter.ldm_bucket_size_log] = C_INT_MAX
271+
with self.assertRaises(ValueError):
272+
ZstdCompressor(options=d1)
273+
# smaller than signed int
274+
d1[CompressionParameter.ldm_bucket_size_log] = C_INT_MIN
275+
with self.assertRaises(ValueError):
276+
ZstdCompressor(options=d1)
261277

262-
# clamp compressionLevel
278+
# out of bounds compression level
263279
level_min, level_max = CompressionParameter.compression_level.bounds()
264-
compress(b'', level_max+1)
265-
compress(b'', level_min-1)
266-
267-
compress(b'', options={CompressionParameter.compression_level:level_max+1})
268-
compress(b'', options={CompressionParameter.compression_level:level_min-1})
280+
with self.assertRaises(ValueError):
281+
compress(b'', level_max+1)
282+
with self.assertRaises(ValueError):
283+
compress(b'', level_min-1)
284+
with self.assertRaises(ValueError):
285+
compress(b'', 2**1000)
286+
with self.assertRaises(ValueError):
287+
compress(b'', -(2**1000))
288+
with self.assertRaises(ValueError):
289+
compress(b'', options={
290+
CompressionParameter.compression_level: level_max+1})
291+
with self.assertRaises(ValueError):
292+
compress(b'', options={
293+
CompressionParameter.compression_level: level_min-1})
269294

270295
# zstd lib doesn't support MT compression
271296
if not SUPPORT_MULTITHREADING:
@@ -278,19 +303,19 @@ def test_compress_parameters(self):
278303

279304
# out of bounds error msg
280305
option = {CompressionParameter.window_log:100}
281-
with self.assertRaisesRegex(ZstdError,
282-
(r'Error when setting zstd compression parameter "window_log", '
283-
r'it should \d+ <= value <= \d+, provided value is 100\. '
284-
r'\((?:32|64)-bit build\)')):
306+
with self.assertRaisesRegex(
307+
ValueError,
308+
"compression parameter 'window_log' received an illegal value 100; "
309+
r'the valid range is \[-?\d+, -?\d+\]',
310+
):
285311
compress(b'', options=option)
286312

287313
def test_unknown_compression_parameter(self):
288314
KEY = 100001234
289315
option = {CompressionParameter.compression_level: 10,
290316
KEY: 200000000}
291-
pattern = (r'Invalid zstd compression parameter.*?'
292-
fr'"unknown parameter \(key {KEY}\)"')
293-
with self.assertRaisesRegex(ZstdError, pattern):
317+
pattern = rf"invalid compression parameter 'unknown parameter \(key {KEY}\)'"
318+
with self.assertRaisesRegex(ValueError, pattern):
294319
ZstdCompressor(options=option)
295320

296321
@unittest.skipIf(not SUPPORT_MULTITHREADING,
@@ -385,12 +410,22 @@ def test_simple_decompress_bad_args(self):
385410
self.assertRaises(TypeError, ZstdDecompressor, options=b'abc')
386411

387412
with self.assertRaises(ValueError):
388-
ZstdDecompressor(options={2**31 : 100})
413+
ZstdDecompressor(options={C_INT_MAX: 100})
414+
with self.assertRaises(ValueError):
415+
ZstdDecompressor(options={C_INT_MIN: 100})
416+
with self.assertRaises(ValueError):
417+
ZstdDecompressor(options={0: C_INT_MAX})
418+
with self.assertRaises(OverflowError):
419+
ZstdDecompressor(options={2**1000: 100})
420+
with self.assertRaises(OverflowError):
421+
ZstdDecompressor(options={-(2**1000): 100})
422+
with self.assertRaises(OverflowError):
423+
ZstdDecompressor(options={0: -(2**1000)})
389424

390-
with self.assertRaises(ZstdError):
391-
ZstdDecompressor(options={DecompressionParameter.window_log_max:100})
392-
with self.assertRaises(ZstdError):
393-
ZstdDecompressor(options={3333 : 100})
425+
with self.assertRaises(ValueError):
426+
ZstdDecompressor(options={DecompressionParameter.window_log_max: 100})
427+
with self.assertRaises(ValueError):
428+
ZstdDecompressor(options={3333: 100})
394429

395430
empty = compress(b'')
396431
lzd = ZstdDecompressor()
@@ -403,26 +438,52 @@ def test_decompress_parameters(self):
403438
d = {DecompressionParameter.window_log_max : 15}
404439
ZstdDecompressor(options=d)
405440

406-
# larger than signed int, ValueError
407441
d1 = d.copy()
408-
d1[DecompressionParameter.window_log_max] = 2**31
409-
self.assertRaises(ValueError, ZstdDecompressor, None, d1)
442+
# larger than signed int
443+
d1[DecompressionParameter.window_log_max] = 2**1000
444+
with self.assertRaises(OverflowError):
445+
ZstdDecompressor(None, d1)
446+
# smaller than signed int
447+
d1[DecompressionParameter.window_log_max] = -(2**1000)
448+
with self.assertRaises(OverflowError):
449+
ZstdDecompressor(None, d1)
450+
451+
d1[DecompressionParameter.window_log_max] = C_INT_MAX
452+
with self.assertRaises(ValueError):
453+
ZstdDecompressor(None, d1)
454+
d1[DecompressionParameter.window_log_max] = C_INT_MIN
455+
with self.assertRaises(ValueError):
456+
ZstdDecompressor(None, d1)
410457

411458
# out of bounds error msg
412459
options = {DecompressionParameter.window_log_max:100}
413-
with self.assertRaisesRegex(ZstdError,
414-
(r'Error when setting zstd decompression parameter "window_log_max", '
415-
r'it should \d+ <= value <= \d+, provided value is 100\. '
416-
r'\((?:32|64)-bit build\)')):
460+
with self.assertRaisesRegex(
461+
ValueError,
462+
"decompression parameter 'window_log_max' received an illegal value 100; "
463+
r'the valid range is \[-?\d+, -?\d+\]',
464+
):
465+
decompress(b'', options=options)
466+
467+
# out of bounds deecompression parameter
468+
options[DecompressionParameter.window_log_max] = C_INT_MAX
469+
with self.assertRaises(ValueError):
470+
decompress(b'', options=options)
471+
options[DecompressionParameter.window_log_max] = C_INT_MIN
472+
with self.assertRaises(ValueError):
473+
decompress(b'', options=options)
474+
options[DecompressionParameter.window_log_max] = 2**1000
475+
with self.assertRaises(OverflowError):
476+
decompress(b'', options=options)
477+
options[DecompressionParameter.window_log_max] = -(2**1000)
478+
with self.assertRaises(OverflowError):
417479
decompress(b'', options=options)
418480

419481
def test_unknown_decompression_parameter(self):
420482
KEY = 100001234
421483
options = {DecompressionParameter.window_log_max: DecompressionParameter.window_log_max.bounds()[1],
422484
KEY: 200000000}
423-
pattern = (r'Invalid zstd decompression parameter.*?'
424-
fr'"unknown parameter \(key {KEY}\)"')
425-
with self.assertRaisesRegex(ZstdError, pattern):
485+
pattern = rf"invalid decompression parameter 'unknown parameter \(key {KEY}\)'"
486+
with self.assertRaisesRegex(ValueError, pattern):
426487
ZstdDecompressor(options=options)
427488

428489
def test_decompress_epilogue_flags(self):
@@ -1425,11 +1486,11 @@ def test_init_bad_mode(self):
14251486
ZstdFile(io.BytesIO(COMPRESSED_100_PLUS_32KB), "rw")
14261487

14271488
with self.assertRaisesRegex(TypeError,
1428-
r"NOT be a CompressionParameter"):
1489+
r"not be a CompressionParameter"):
14291490
ZstdFile(io.BytesIO(), 'rb',
14301491
options={CompressionParameter.compression_level:5})
14311492
with self.assertRaisesRegex(TypeError,
1432-
r"NOT be a DecompressionParameter"):
1493+
r"not be a DecompressionParameter"):
14331494
ZstdFile(io.BytesIO(), 'wb',
14341495
options={DecompressionParameter.window_log_max:21})
14351496

@@ -1440,19 +1501,19 @@ def test_init_bad_check(self):
14401501
with self.assertRaises(TypeError):
14411502
ZstdFile(io.BytesIO(), "w", level='asd')
14421503
# CHECK_UNKNOWN and anything above CHECK_ID_MAX should be invalid.
1443-
with self.assertRaises(ZstdError):
1504+
with self.assertRaises(ValueError):
14441505
ZstdFile(io.BytesIO(), "w", options={999:9999})
1445-
with self.assertRaises(ZstdError):
1506+
with self.assertRaises(ValueError):
14461507
ZstdFile(io.BytesIO(), "w", options={CompressionParameter.window_log:99})
14471508

14481509
with self.assertRaises(TypeError):
14491510
ZstdFile(io.BytesIO(COMPRESSED_100_PLUS_32KB), "r", options=33)
14501511

1451-
with self.assertRaises(ValueError):
1512+
with self.assertRaises(OverflowError):
14521513
ZstdFile(io.BytesIO(COMPRESSED_100_PLUS_32KB),
14531514
options={DecompressionParameter.window_log_max:2**31})
14541515

1455-
with self.assertRaises(ZstdError):
1516+
with self.assertRaises(ValueError):
14561517
ZstdFile(io.BytesIO(COMPRESSED_100_PLUS_32KB),
14571518
options={444:333})
14581519

@@ -1468,7 +1529,7 @@ def test_init_close_fp(self):
14681529
tmp_f.write(DAT_130K_C)
14691530
filename = tmp_f.name
14701531

1471-
with self.assertRaises(ValueError):
1532+
with self.assertRaises(TypeError):
14721533
ZstdFile(filename, options={'a':'b'})
14731534

14741535
# for PyPy

Modules/_zstd/_zstdmodule.c

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,13 @@ static const ParameterInfo dp_list[] = {
103103
};
104104

105105
void
106-
set_parameter_error(const _zstd_state* const state, int is_compress,
107-
int key_v, int value_v)
106+
set_parameter_error(int is_compress, int key_v, int value_v)
108107
{
109108
ParameterInfo const *list;
110109
int list_size;
111-
char const *name;
112110
char *type;
113111
ZSTD_bounds bounds;
114-
int i;
115-
char pos_msg[128];
112+
char pos_msg[64];
116113

117114
if (is_compress) {
118115
list = cp_list;
@@ -126,8 +123,8 @@ set_parameter_error(const _zstd_state* const state, int is_compress,
126123
}
127124

128125
/* Find parameter's name */
129-
name = NULL;
130-
for (i = 0; i < list_size; i++) {
126+
char const *name = NULL;
127+
for (int i = 0; i < list_size; i++) {
131128
if (key_v == (list+i)->parameter) {
132129
name = (list+i)->parameter_name;
133130
break;
@@ -149,20 +146,16 @@ set_parameter_error(const _zstd_state* const state, int is_compress,
149146
bounds = ZSTD_dParam_getBounds(key_v);
150147
}
151148
if (ZSTD_isError(bounds.error)) {
152-
PyErr_Format(state->ZstdError,
153-
"Invalid zstd %s parameter \"%s\".",
149+
PyErr_Format(PyExc_ValueError, "invalid %s parameter '%s'",
154150
type, name);
155151
return;
156152
}
157153

158154
/* Error message */
159-
PyErr_Format(state->ZstdError,
160-
"Error when setting zstd %s parameter \"%s\", it "
161-
"should %d <= value <= %d, provided value is %d. "
162-
"(%d-bit build)",
163-
type, name,
164-
bounds.lowerBound, bounds.upperBound, value_v,
165-
8*(int)sizeof(Py_ssize_t));
155+
PyErr_Format(PyExc_ValueError,
156+
"%s parameter '%s' received an illegal value %d; "
157+
"the valid range is [%d, %d]",
158+
type, name, value_v, bounds.lowerBound, bounds.upperBound);
166159
}
167160

168161
static inline _zstd_state*

Modules/_zstd/_zstdmodule.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ set_zstd_error(const _zstd_state* const state,
4949
const error_type type, size_t zstd_ret);
5050

5151
extern void
52-
set_parameter_error(const _zstd_state* const state, int is_compress,
53-
int key_v, int value_v);
52+
set_parameter_error(int is_compress, int key_v, int value_v);
5453

5554
#endif // !ZSTD_MODULE_H

0 commit comments

Comments
 (0)