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]
