Skip to content

Commit d4b3229

Browse files
committed
Refactor zstd_contentsize_converter to handle all values
1 parent 0dafae5 commit d4b3229

File tree

2 files changed

+47
-16
lines changed

2 files changed

+47
-16
lines changed

Lib/test/test_zstd.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,31 @@ def test_set_pledged_input_size(self):
404404
with self.assertRaisesRegex(ValueError,
405405
r'should be a positive int less than \d+'):
406406
c.set_pledged_input_size(-300)
407+
# overflow
408+
with self.assertRaisesRegex(ValueError,
409+
r'should be a positive int less than \d+'):
410+
c.set_pledged_input_size(2**64)
411+
# ZSTD_CONTENTSIZE_ERROR is invalid
412+
with self.assertRaisesRegex(ValueError,
413+
r'should be a positive int less than \d+'):
414+
c.set_pledged_input_size(2**64-2)
415+
# ZSTD_CONTENTSIZE_UNKNOWN should use None
416+
with self.assertRaisesRegex(ValueError,
417+
r'should be a positive int less than \d+'):
418+
c.set_pledged_input_size(2**64-1)
419+
420+
# check valid values are settable
421+
c.set_pledged_input_size(2**63)
422+
c.set_pledged_input_size(2**64-3)
423+
424+
# check that zero means empty frame
425+
c = ZstdCompressor(level=1)
426+
c.set_pledged_input_size(0)
427+
c.compress(b'')
428+
dat = c.flush()
429+
ret = get_frame_info(dat)
430+
self.assertEqual(ret.decompressed_size, 0)
431+
407432

408433
# wrong mode
409434
c = ZstdCompressor(level=1)

Modules/_zstd/compressor.c

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ class zstd_contentsize_converter(CConverter):
5555
[python start generated code]*/
5656
/*[python end generated code: output=da39a3ee5e6b4b0d input=0932c350d633c7de]*/
5757

58+
static inline int
59+
raise_wrong_contentsize(void)
60+
{
61+
PyErr_Format(PyExc_ValueError,
62+
"size argument should be a positive int less "
63+
"than %ull", ZSTD_CONTENTSIZE_ERROR);
64+
return 0;
65+
}
66+
5867
static int
5968
zstd_contentsize_converter(PyObject *size, unsigned long long *p)
6069
{
@@ -65,19 +74,21 @@ zstd_contentsize_converter(PyObject *size, unsigned long long *p)
6574
else {
6675
/* ZSTD_CONTENTSIZE_UNKNOWN is 0ULL - 1
6776
ZSTD_CONTENTSIZE_ERROR is 0ULL - 2
68-
Users should only pass values <= ZSTD_CONTENTSIZE_ERROR
69-
If they wish to pass ZSTD_CONTENTSIZE_UNKNOWN, they need to pass
70-
None (see above). */
77+
Users should only pass values < ZSTD_CONTENTSIZE_ERROR */
7178
unsigned long long pledged_size = PyLong_AsUnsignedLongLong(size);
79+
/* Here we check for (unsigned long long)-1 as a sign of an error in
80+
PyLong_AsUnsignedLongLong */
7281
if (pledged_size == (unsigned long long)-1 && PyErr_Occurred()) {
7382
*p = ZSTD_CONTENTSIZE_ERROR;
7483
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
75-
PyErr_Format(PyExc_ValueError,
76-
"size argument should be a positive int less "
77-
"than %ull", ZSTD_CONTENTSIZE_ERROR);
84+
return raise_wrong_contentsize();
7885
}
7986
return 0;
8087
}
88+
if (pledged_size >= ZSTD_CONTENTSIZE_ERROR) {
89+
*p = ZSTD_CONTENTSIZE_ERROR;
90+
return raise_wrong_contentsize();
91+
}
8192
*p = pledged_size;
8293
}
8394
return 1;
@@ -752,7 +763,6 @@ _zstd_ZstdCompressor_set_pledged_input_size_impl(ZstdCompressor *self,
752763
/*[clinic end generated code: output=3a09e55cc0e3b4f9 input=563b9a1ddd4facc3]*/
753764
{
754765
size_t zstd_ret;
755-
PyObject *ret;
756766

757767
// Error occured while converting argument, should be unreachable
758768
assert(size != ZSTD_CONTENTSIZE_ERROR);
@@ -765,24 +775,20 @@ _zstd_ZstdCompressor_set_pledged_input_size_impl(ZstdCompressor *self,
765775
PyErr_SetString(PyExc_RuntimeError,
766776
"set_pledged_input_size() method must be called "
767777
"when last_mode == FLUSH_FRAME");
768-
goto error;
778+
PyMutex_Unlock(&self->lock);
779+
return NULL;
769780
}
770781

771782
/* Set pledged content size */
772783
zstd_ret = ZSTD_CCtx_setPledgedSrcSize(self->cctx, size);
784+
PyMutex_Unlock(&self->lock);
773785
if (ZSTD_isError(zstd_ret)) {
774786
_zstd_state* mod_state = PyType_GetModuleState(Py_TYPE(self));
775787
set_zstd_error(mod_state, ERR_SET_PLEDGED_INPUT_SIZE, zstd_ret);
776-
goto error;
788+
return NULL;
777789
}
778790

779-
ret = Py_None;
780-
goto success;
781-
error:
782-
ret = NULL;
783-
success:
784-
PyMutex_Unlock(&self->lock);
785-
return ret;
791+
Py_RETURN_NONE;
786792
}
787793

788794
static PyMethodDef ZstdCompressor_methods[] = {

0 commit comments

Comments
 (0)