Skip to content

Commit 02cd6d7

Browse files
authored
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).
1 parent 698c6e3 commit 02cd6d7

File tree

2 files changed

+12
-9
lines changed

2 files changed

+12
-9
lines changed

Modules/_testcapi/float.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,11 @@ _testcapi_float_set_snan(PyObject *module, PyObject *obj)
182182
uint64_t v;
183183
memcpy(&v, &d, 8);
184184
v &= ~(1ULL << 51); /* make sNaN */
185-
memcpy(&d, &v, 8);
186-
return PyFloat_FromDouble(d);
185+
186+
// gh-130317: memcpy() is needed to preserve the sNaN flag on x86 (32-bit)
187+
PyObject *res = PyFloat_FromDouble(0.0);
188+
memcpy(&((PyFloatObject *)res)->ob_fval, &v, 8);
189+
return res;
187190
}
188191

189192
static PyMethodDef test_methods[] = {

Objects/floatobject.c

+7-7
Original file line numberDiff line numberDiff line change
@@ -2197,12 +2197,10 @@ PyFloat_Pack4(double x, char *data, int le)
21972197

21982198
memcpy(&v, &x, 8);
21992199
if ((v & (1ULL << 51)) == 0) {
2200-
union float_val {
2201-
float f;
2202-
uint32_t u32;
2203-
} *py = (union float_val *)&y;
2204-
2205-
py->u32 &= ~(1 << 22); /* make sNaN */
2200+
uint32_t u32;
2201+
memcpy(&u32, &y, 4);
2202+
u32 &= ~(1 << 22); /* make sNaN */
2203+
memcpy(&y, &u32, 4);
22062204
}
22072205
}
22082206

@@ -2340,7 +2338,9 @@ PyFloat_Pack8(double x, char *data, int le)
23402338
return -1;
23412339
}
23422340
else {
2343-
const unsigned char *s = (unsigned char*)&x;
2341+
unsigned char as_bytes[8];
2342+
memcpy(as_bytes, &x, 8);
2343+
const unsigned char *s = as_bytes;
23442344
int i, incr = 1;
23452345

23462346
if ((double_format == ieee_little_endian_format && !le)

0 commit comments

Comments
 (0)