https://github.com/python/cpython/commit/8a25840a2acdc9e7dcc35451556402a91f450430
commit: 8a25840a2acdc9e7dcc35451556402a91f450430
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: vstinner <[email protected]>
date: 2026-03-26T11:38:42Z
summary:
[3.14] gh-145633: Fix struct.pack('f') on s390x (GH-146422) (#146460)
gh-145633: Fix struct.pack('f') on s390x (GH-146422)
Use PyFloat_Pack4() to raise OverflowError.
Add more tests on packing/unpacking floats.
(cherry picked from commit 8de70b31c59b1d572d95f8bb471a09cfe4cd2b13)
Co-authored-by: Victor Stinner <[email protected]>
Co-authored-by: Sergey B Kirpichev <[email protected]>
files:
A Misc/NEWS.d/next/Library/2026-03-26-11-04-42.gh-issue-145633.RWjlaX.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 598f10b1862317..d2a30804bedb2c 100644
--- a/Lib/test/test_struct.py
+++ b/Lib/test/test_struct.py
@@ -397,6 +397,21 @@ def test_705836(self):
big = (1 << 25) - 1
big = math.ldexp(big, 127 - 24)
self.assertRaises(OverflowError, struct.pack, ">f", big)
+ self.assertRaises(OverflowError, struct.pack, "<f", big)
+ # same for native format, see gh-145633
+ self.assertRaises(OverflowError, struct.pack, "f", big)
+
+ # And for half-floats
+ big = (1 << 11) - 1
+ big = math.ldexp(big, 15 - 10)
+ packed = struct.pack(">e", big)
+ unpacked = struct.unpack(">e", packed)[0]
+ self.assertEqual(big, unpacked)
+ big = (1 << 12) - 1
+ big = math.ldexp(big, 15 - 11)
+ self.assertRaises(OverflowError, struct.pack, ">e", big)
+ self.assertRaises(OverflowError, struct.pack, "<e", big)
+ self.assertRaises(OverflowError, struct.pack, "e", big)
def test_1530559(self):
for code, byteorder in iter_integer_formats():
@@ -862,6 +877,24 @@ def test_operations_on_half_initialized_Struct(self):
self.assertRaises(RuntimeError, repr, S)
self.assertEqual(S.size, -1)
+ def test_float_round_trip(self):
+ for format in (
+ "f", "<f", ">f",
+ "d", "<d", ">d",
+ "e", "<e", ">e",
+ ):
+ with self.subTest(format=format):
+ f = struct.unpack(format, struct.pack(format, 1.5))[0]
+ self.assertEqual(f, 1.5)
+ f = struct.unpack(format, struct.pack(format, NAN))[0]
+ self.assertTrue(math.isnan(f), f)
+ f = struct.unpack(format, struct.pack(format, INF))[0]
+ self.assertTrue(math.isinf(f), f)
+ self.assertEqual(math.copysign(1.0, f), 1.0)
+ f = struct.unpack(format, struct.pack(format, -INF))[0]
+ self.assertTrue(math.isinf(f), f)
+ self.assertEqual(math.copysign(1.0, f), -1.0)
+
class UnpackIteratorTest(unittest.TestCase):
"""
diff --git
a/Misc/NEWS.d/next/Library/2026-03-26-11-04-42.gh-issue-145633.RWjlaX.rst
b/Misc/NEWS.d/next/Library/2026-03-26-11-04-42.gh-issue-145633.RWjlaX.rst
new file mode 100644
index 00000000000000..00507fe89d07ec
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-03-26-11-04-42.gh-issue-145633.RWjlaX.rst
@@ -0,0 +1,2 @@
+Fix ``struct.pack('f', float)``: use :c:func:`PyFloat_Pack4` to raise
+:exc:`OverflowError`. Patch by Sergey B Kirpichev and Victor Stinner.
diff --git a/Modules/_struct.c b/Modules/_struct.c
index fe8c689b629ee3..c77d195d881dbe 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -762,14 +762,13 @@ np_halffloat(_structmodulestate *state, char *p, PyObject
*v, const formatdef *f
static int
np_float(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
{
- float x = (float)PyFloat_AsDouble(v);
+ double x = PyFloat_AsDouble(v);
if (x == -1 && PyErr_Occurred()) {
PyErr_SetString(state->StructError,
"required argument is not a float");
return -1;
}
- memcpy(p, &x, sizeof x);
- return 0;
+ return PyFloat_Pack4(x, p, PY_LITTLE_ENDIAN);
}
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]