From: Victor Stinner Date: Tue, 29 Apr 2025 14:27:50 +0000 (+0200) Subject: gh-130317: Fix strict aliasing in PyFloat_Pack8() (#133150) X-Git-Tag: v3.14.0b1~192 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=02cd6d709709e28c7a8fa62ce3620ea000b524d3;p=thirdparty%2FPython%2Fcpython.git gh-130317: Fix strict aliasing in PyFloat_Pack8() (#133150) * Fix strict aliasing in PyFloat_Pack8() and PyFloat_Pack4(). * Fix _testcapi.float_set_snan() on x86 (32-bit). --- diff --git a/Modules/_testcapi/float.c b/Modules/_testcapi/float.c index 2feeb205d8a3..007884bc1f9d 100644 --- a/Modules/_testcapi/float.c +++ b/Modules/_testcapi/float.c @@ -182,8 +182,11 @@ _testcapi_float_set_snan(PyObject *module, PyObject *obj) uint64_t v; memcpy(&v, &d, 8); v &= ~(1ULL << 51); /* make sNaN */ - memcpy(&d, &v, 8); - return PyFloat_FromDouble(d); + + // gh-130317: memcpy() is needed to preserve the sNaN flag on x86 (32-bit) + PyObject *res = PyFloat_FromDouble(0.0); + memcpy(&((PyFloatObject *)res)->ob_fval, &v, 8); + return res; } static PyMethodDef test_methods[] = { diff --git a/Objects/floatobject.c b/Objects/floatobject.c index e0a8f0c62d49..76ed24d29fd2 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -2197,12 +2197,10 @@ PyFloat_Pack4(double x, char *data, int le) memcpy(&v, &x, 8); if ((v & (1ULL << 51)) == 0) { - union float_val { - float f; - uint32_t u32; - } *py = (union float_val *)&y; - - py->u32 &= ~(1 << 22); /* make sNaN */ + uint32_t u32; + memcpy(&u32, &y, 4); + u32 &= ~(1 << 22); /* make sNaN */ + memcpy(&y, &u32, 4); } } @@ -2340,7 +2338,9 @@ PyFloat_Pack8(double x, char *data, int le) return -1; } else { - const unsigned char *s = (unsigned char*)&x; + unsigned char as_bytes[8]; + memcpy(as_bytes, &x, 8); + const unsigned char *s = as_bytes; int i, incr = 1; if ((double_format == ieee_little_endian_format && !le)