https://github.com/python/cpython/commit/0b447baeaac43723be7d4903d90f22780cc7e374
commit: 0b447baeaac43723be7d4903d90f22780cc7e374
branch: main
author: Sergey B Kirpichev <[email protected]>
committer: vstinner <[email protected]>
date: 2026-09-24T10:33:51+02:00
summary:

gh-156865: struct.pack() check for overflows for Zf type (#156868)

Co-authored-by: Victor Stinner <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-09-03-04-32-06.gh-issue-156867.hq3efC.rst
M Lib/test/test_struct.py
M Modules/_struct.c

diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py
index 3809f2d2643895..d0773490ac807b 100644
--- a/Lib/test/test_struct.py
+++ b/Lib/test/test_struct.py
@@ -424,6 +424,20 @@ def test_705836(self):
         self.assertRaises(OverflowError, struct.pack, "<e", big)
         self.assertRaises(OverflowError, struct.pack, "e", big)
 
+    def test_float_complex_overflow(self):
+        for value in (
+            1e300 + 0.5j,  # big real
+            1.5 + 1e300j,  # big imag
+        ):
+            for format in (">Zf", "<Zf", "Zf"):
+                with self.subTest(value=value, format=format):
+                    self.assertRaises(OverflowError, struct.pack, format, 
value)
+
+                    ba = bytearray(8)
+                    with self.assertRaises(OverflowError):
+                        struct.Struct(format).pack_into(ba, 0, value)
+                    self.assertEqual(ba, bytearray(8))
+
     def test_1530559(self):
         for code, byteorder in iter_integer_formats():
             format = byteorder + code
diff --git 
a/Misc/NEWS.d/next/Library/2026-09-03-04-32-06.gh-issue-156867.hq3efC.rst 
b/Misc/NEWS.d/next/Library/2026-09-03-04-32-06.gh-issue-156867.hq3efC.rst
new file mode 100644
index 00000000000000..2e5ea55f86cc2f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-09-03-04-32-06.gh-issue-156867.hq3efC.rst
@@ -0,0 +1,3 @@
+Raise :exc:`OverflowError`'s for native ``'Zf'`` format in :func:`struct.pack`,
+like for ``'f'`` format.  Previously overflows in the :c:expr:`float complex`
+type were silent.  Patch by Sergey B Kirpichev.
diff --git a/Modules/_struct.c b/Modules/_struct.c
index 8caadf091767e3..fb2f40ab9766c5 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -790,14 +790,19 @@ np_float_complex(_structmodulestate *state, char *p, 
PyObject *v,
                  const formatdef *f)
 {
     Py_complex c = PyComplex_AsCComplex(v);
-    float x[2] = {(float)c.real, (float)c.imag};
+    char tmp[8];
 
     if (c.real == -1 && PyErr_Occurred()) {
         PyErr_SetString(state->StructError,
                         "required argument is not a complex");
         return -1;
     }
-    memcpy(p, &x, sizeof(x));
+    if (PyFloat_Pack4(c.real, tmp, PY_LITTLE_ENDIAN)
+        || PyFloat_Pack4(c.imag, tmp + 4, PY_LITTLE_ENDIAN))
+    {
+        return -1;
+    }
+    memcpy(p, tmp, 8);
     return 0;
 }
 
@@ -1132,15 +1137,20 @@ static int
 bp_float_complex(_structmodulestate *state, char *p, PyObject *v, const 
formatdef *f)
 {
     Py_complex x = PyComplex_AsCComplex(v);
+    char tmp[8];
+
     if (x.real == -1 && PyErr_Occurred()) {
         PyErr_SetString(state->StructError,
                         "required argument is not a complex");
         return -1;
     }
-    if (PyFloat_Pack4(x.real, p, 0)) {
+    if (PyFloat_Pack4(x.real, tmp, 0)
+        || PyFloat_Pack4(x.imag, tmp + 4, 0))
+    {
         return -1;
     }
-    return PyFloat_Pack4(x.imag, p + 4, 0);
+    memcpy(p, tmp, 8);
+    return 0;
 }
 
 static int
@@ -1458,16 +1468,20 @@ static int
 lp_float_complex(_structmodulestate *state, char *p, PyObject *v, const 
formatdef *f)
 {
     Py_complex x = PyComplex_AsCComplex(v);
+    char tmp[8];
+
     if (x.real == -1 && PyErr_Occurred()) {
         PyErr_SetString(state->StructError,
                         "required argument is not a complex");
         return -1;
     }
-    if (PyFloat_Pack4(x.real, p, 1)) {
+    if (PyFloat_Pack4(x.real, tmp, 1)
+        || PyFloat_Pack4(x.imag, tmp + 4, 1))
+    {
         return -1;
     }
-    return PyFloat_Pack4(x.imag, p + 4, 1);
-
+    memcpy(p, tmp, 8);
+    return 0;
 }
 
 static int

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to