Skip to content

Commit dce8046

Browse files
skirpichevmaurycy
andauthored
gh-156865: Correctly handle float/complex overflows in memoryview (#156916)
Co-authored-by: Maurycy Pawłowski-Wieroński <maurycy@maurycy.com>
1 parent 5bde996 commit dce8046

3 files changed

Lines changed: 33 additions & 4 deletions

File tree

‎Lib/test/test_memoryview.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,24 @@ def test_picklebuffer_reference_loop(self):
931931
gc.collect()
932932
self.assertIsNone(wr())
933933

934+
def test_overflows_in_floats(self):
935+
half_data = array.array('e', [0.0])
936+
float_data = array.array('f', [0.0])
937+
complex_data = array.array('Zf', [123+321j])
938+
half_view = memoryview(half_data)
939+
float_view = memoryview(float_data)
940+
complex_view = memoryview(complex_data)
941+
with self.assertRaises(ValueError):
942+
half_view[0] = 123456.0
943+
with self.assertRaises(ValueError):
944+
float_view[0] = 1e300
945+
with self.assertRaises(ValueError):
946+
complex_view[0] = 1e300
947+
self.assertEqual(complex_view[0], 123+321j)
948+
with self.assertRaises(ValueError):
949+
complex_view[0] = 1e300j
950+
self.assertEqual(complex_view[0], 123+321j)
951+
934952

935953
@threading_helper.requires_working_threading()
936954
@support.requires_resource("cpu")
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Raise :exc:`ValueError`'s for overflows, while trying to change
2+
:class:`memoryview` elements with ``'f'`` and ``'Zf'`` format codes. Patch
3+
by Sergey B Kirpichev.

‎Objects/memoryobject.c‎

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2037,7 +2037,9 @@ pack_single(PyMemoryViewObject *self, char *ptr, PyObject *item, const char *fmt
20372037
goto err_occurred;
20382038
CHECK_RELEASED_INT_AGAIN(self);
20392039
if (fmt[0] == 'f') {
2040-
PACK_SINGLE(ptr, d, float);
2040+
if (PyFloat_Pack4(d, ptr, endian) < 0) {
2041+
goto err_occurred;
2042+
}
20412043
}
20422044
else if (fmt[0] == 'd') {
20432045
PACK_SINGLE(ptr, d, double);
@@ -2064,9 +2066,15 @@ pack_single(PyMemoryViewObject *self, char *ptr, PyObject *item, const char *fmt
20642066
memcpy(ptr, &x, sizeof(x));
20652067
}
20662068
else {
2067-
float x[2] = {(float)c.real, (float)c.imag};
2068-
2069-
memcpy(ptr, &x, sizeof(x));
2069+
char tmp[8];
2070+
2071+
if (PyFloat_Pack4(c.real, tmp, endian) < 0) {
2072+
goto err_occurred;
2073+
}
2074+
if (PyFloat_Pack4(c.imag, tmp + 4, endian) < 0) {
2075+
goto err_occurred;
2076+
}
2077+
memcpy(ptr, tmp, 8);
20702078
}
20712079
break;
20722080

0 commit comments

Comments
 (0)