diff --git a/Modules/_testcapi/float.c b/Modules/_testcapi/float.c index 2feeb205d8a376..007884bc1f9da3 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 e0a8f0c62d4951..76ed24d29fd25c 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)