From e58813bb2bfaf4e6e38470c3aa92ac3611f1b5d3 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 28 Apr 2025 20:44:37 +0300 Subject: [PATCH 1/3] gh-132987: Support __index__() in the lzma module --- Modules/_lzmamodule.c | 47 +++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index c05cc8a4e4cb49..6c543ab2a44922 100644 --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -203,25 +203,28 @@ PyLzma_Free(void *opaque, void *ptr) to be strictly correct, we need to define two separate converters. */ -#define INT_TYPE_CONVERTER_FUNC(TYPE, FUNCNAME) \ - static int \ - FUNCNAME(PyObject *obj, void *ptr) \ - { \ - unsigned long long val; \ - \ - val = PyLong_AsUnsignedLongLong(obj); \ - if (PyErr_Occurred()) \ - return 0; \ - if ((unsigned long long)(TYPE)val != val) { \ - PyErr_SetString(PyExc_OverflowError, \ - "Value too large for " #TYPE " type"); \ - return 0; \ - } \ - *(TYPE *)ptr = (TYPE)val; \ - return 1; \ - } +#define INT_TYPE_CONVERTER_FUNC(TYPE, FUNCNAME) \ +static int \ +FUNCNAME(PyObject *obj, void *ptr) \ +{ \ + Py_ssize_t bytes = PyLong_AsNativeBytes(obj, ptr, sizeof(TYPE), \ + Py_ASNATIVEBYTES_NATIVE_ENDIAN | \ + Py_ASNATIVEBYTES_ALLOW_INDEX | \ + Py_ASNATIVEBYTES_REJECT_NEGATIVE | \ + Py_ASNATIVEBYTES_UNSIGNED_BUFFER); \ + if (bytes < 0) { \ + return 0; \ + } \ + if ((size_t)bytes > sizeof(TYPE)) { \ + PyErr_SetString(PyExc_OverflowError, \ + "Python int too large for C "#TYPE); \ + return 0; \ + } \ + return 1; \ +} INT_TYPE_CONVERTER_FUNC(uint32_t, uint32_converter) +INT_TYPE_CONVERTER_FUNC(uint64_t, uint64_converter) INT_TYPE_CONVERTER_FUNC(lzma_vli, lzma_vli_converter) INT_TYPE_CONVERTER_FUNC(lzma_mode, lzma_mode_converter) INT_TYPE_CONVERTER_FUNC(lzma_match_finder, lzma_mf_converter) @@ -355,11 +358,12 @@ lzma_filter_converter(_lzma_state *state, PyObject *spec, void *ptr) "Filter specifier must have an \"id\" entry"); return 0; } - f->id = PyLong_AsUnsignedLongLong(id_obj); - Py_DECREF(id_obj); - if (PyErr_Occurred()) { + lzma_vli id; + if (!lzma_vli_converter(id_obj, &id)) { + Py_DECREF(id_obj); return 0; } + f->id = id; switch (f->id) { case LZMA_FILTER_LZMA1: @@ -1221,8 +1225,7 @@ _lzma_LZMADecompressor_impl(PyTypeObject *type, int format, "Cannot specify memory limit with FORMAT_RAW"); return NULL; } - memlimit_ = PyLong_AsUnsignedLongLong(memlimit); - if (PyErr_Occurred()) { + if (!uint64_converter(memlimit, &memlimit_)) { return NULL; } } From 5f152e5387578a24aa765c449006b30183c84019 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 28 Apr 2025 21:27:35 +0300 Subject: [PATCH 2/3] Fix tests. --- Lib/test/test_lzma.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_lzma.py b/Lib/test/test_lzma.py index d7e8327cfee18a..9ffb93e797dd80 100644 --- a/Lib/test/test_lzma.py +++ b/Lib/test/test_lzma.py @@ -657,10 +657,12 @@ def test_init_bad_preset(self): LZMAFile(BytesIO(), "w", preset=10) with self.assertRaises(LZMAError): LZMAFile(BytesIO(), "w", preset=23) - with self.assertRaises(OverflowError): + with self.assertRaises(ValueError): LZMAFile(BytesIO(), "w", preset=-1) - with self.assertRaises(OverflowError): + with self.assertRaises(ValueError): LZMAFile(BytesIO(), "w", preset=-7) + with self.assertRaises(OverflowError): + LZMAFile(BytesIO(), "w", preset=2**1000) with self.assertRaises(TypeError): LZMAFile(BytesIO(), "w", preset="foo") # Cannot specify a preset with mode="r". From 7ce4ae2c3866208812cd3f048c25c66a87fb8965 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 29 Apr 2025 16:46:40 +0300 Subject: [PATCH 3/3] Update Modules/_lzmamodule.c --- Modules/_lzmamodule.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index 6c543ab2a44922..f9b4c2a170e9c5 100644 --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -363,6 +363,7 @@ lzma_filter_converter(_lzma_state *state, PyObject *spec, void *ptr) Py_DECREF(id_obj); return 0; } + Py_DECREF(id_obj); f->id = id; switch (f->id) {