]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-132987: Support __index__() in the lzma module (GH-133099)
authorSerhiy Storchaka <storchaka@gmail.com>
Tue, 29 Apr 2025 14:14:33 +0000 (17:14 +0300)
committerGitHub <noreply@github.com>
Tue, 29 Apr 2025 14:14:33 +0000 (14:14 +0000)
Lib/test/test_lzma.py
Modules/_lzmamodule.c

index d7e8327cfee18ad05119da98e2b83fed4de1814c..9ffb93e797dd80f4e28533b1a5404bcc35e500e7 100644 (file)
@@ -657,10 +657,12 @@ class FileTestCase(unittest.TestCase):
             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".
index c05cc8a4e4cb49fa442b26783d295768675c396b..f9b4c2a170e9c5b1b6c8e32dfd85c9b3a6002e37 100644 (file)
@@ -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,13 @@ 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;
     }
+    Py_DECREF(id_obj);
+    f->id = id;
 
     switch (f->id) {
         case LZMA_FILTER_LZMA1:
@@ -1221,8 +1226,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;
         }
     }