Skip to content

Commit aa2679b

Browse files
authored
[mypyc] Fixes to float to int conversion (#14936)
Fix undefined behavior due to converting a negative float to an unsigned integer type. Fix edge cases on 32-bit platforms. The first issue was caught by the testI32BasicOps test case, but only in some configurations, it looks like.
1 parent 9944d5f commit aa2679b

File tree

3 files changed

+13
-2
lines changed

3 files changed

+13
-2
lines changed

mypyc/lib-rt/int_ops.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,8 @@ PyObject *CPyLong_FromStr(PyObject *o) {
294294
}
295295

296296
CPyTagged CPyTagged_FromFloat(double f) {
297-
if (f < (double)CPY_TAGGED_MAX && f > CPY_TAGGED_MIN) {
298-
return (CPyTagged)f << 1;
297+
if (f < ((double)CPY_TAGGED_MAX + 1.0) && f > (CPY_TAGGED_MIN - 1.0)) {
298+
return (Py_ssize_t)f << 1;
299299
}
300300
PyObject *o = PyLong_FromDouble(f);
301301
if (o == NULL)

mypyc/test-data/run-floats.test

+10
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,16 @@ def test_explicit_conversion_to_int() -> None:
185185
else:
186186
assert repr(int(x)) == repr(int_any(x))
187187

188+
# Test some edge cases
189+
assert 2**30 == int(2.0**30 + int())
190+
assert 2**30 - 1 == int(1073741823.9999999 + int()) # math.nextafter(2.0**30, 0))
191+
assert -2**30 - 1 == int(-2.0**30 - 1 + int())
192+
assert -2**30 == int(-1073741824.9999998 + int()) # math.nextafter(-2.0**30 - 1, 0)
193+
assert 2**62 == int(2.0**62 + int())
194+
assert 2**62 == int(2.0**62 - 1 + int())
195+
assert -2**62 == int(-2.0**62 + int())
196+
assert -2**62 == int(-2.0**62 - 1 + int())
197+
188198
def str_to_float(x: str) -> float:
189199
return float(x)
190200

test-data/unit/lib-stub/math.pyi

+1
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ def copysign(__x: float, __y: float) -> float: ...
1313
def isinf(__x: float) -> bool: ...
1414
def isnan(__x: float) -> bool: ...
1515
def isfinite(__x: float) -> bool: ...
16+
def nextafter(__x: float, __y: float) -> float: ...

0 commit comments

Comments
 (0)