Skip to content

Commit 6c52ada

Browse files
Eclips4tomasr8iritkatriel
authored
gh-100239: Handle NaN and zero division in guards for BINARY_OP_EXTEND (#128963)
Co-authored-by: Tomas R. <[email protected]> Co-authored-by: Irit Katriel <[email protected]>
1 parent 5aaf416 commit 6c52ada

File tree

2 files changed

+71
-6
lines changed

2 files changed

+71
-6
lines changed

Lib/test/test_opcache.py

+47
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,53 @@ def binary_op_add_extend():
13621362
self.assert_specialized(binary_op_add_extend, "BINARY_OP_EXTEND")
13631363
self.assert_no_opcode(binary_op_add_extend, "BINARY_OP")
13641364

1365+
def binary_op_zero_division():
1366+
def compactlong_lhs(arg):
1367+
42 / arg
1368+
def float_lhs(arg):
1369+
42.0 / arg
1370+
1371+
with self.assertRaises(ZeroDivisionError):
1372+
compactlong_lhs(0)
1373+
with self.assertRaises(ZeroDivisionError):
1374+
compactlong_lhs(0.0)
1375+
with self.assertRaises(ZeroDivisionError):
1376+
float_lhs(0.0)
1377+
with self.assertRaises(ZeroDivisionError):
1378+
float_lhs(0)
1379+
1380+
self.assert_no_opcode(compactlong_lhs, "BINARY_OP_EXTEND")
1381+
self.assert_no_opcode(float_lhs, "BINARY_OP_EXTEND")
1382+
1383+
binary_op_zero_division()
1384+
1385+
def binary_op_nan():
1386+
def compactlong_lhs(arg):
1387+
return (
1388+
42 + arg,
1389+
42 - arg,
1390+
42 * arg,
1391+
42 / arg,
1392+
)
1393+
def compactlong_rhs(arg):
1394+
return (
1395+
arg + 42,
1396+
arg - 42,
1397+
arg * 2,
1398+
arg / 42,
1399+
)
1400+
nan = float('nan')
1401+
self.assertEqual(compactlong_lhs(1.0), (43.0, 41.0, 42.0, 42.0))
1402+
for _ in range(100):
1403+
self.assertTrue(all(filter(lambda x: x is nan, compactlong_lhs(nan))))
1404+
self.assertEqual(compactlong_rhs(42.0), (84.0, 0.0, 84.0, 1.0))
1405+
for _ in range(100):
1406+
self.assertTrue(all(filter(lambda x: x is nan, compactlong_rhs(nan))))
1407+
1408+
self.assert_no_opcode(compactlong_lhs, "BINARY_OP_EXTEND")
1409+
self.assert_no_opcode(compactlong_rhs, "BINARY_OP_EXTEND")
1410+
1411+
binary_op_nan()
13651412

13661413
@cpython_only
13671414
@requires_specialization_ft

Python/specialize.c

+24-6
Original file line numberDiff line numberDiff line change
@@ -2416,16 +2416,25 @@ binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)
24162416

24172417
/* float-long */
24182418

2419-
static int
2419+
static inline int
24202420
float_compactlong_guard(PyObject *lhs, PyObject *rhs)
24212421
{
24222422
return (
24232423
PyFloat_CheckExact(lhs) &&
2424+
!isnan(PyFloat_AsDouble(lhs)) &&
24242425
PyLong_CheckExact(rhs) &&
24252426
_PyLong_IsCompact((PyLongObject *)rhs)
24262427
);
24272428
}
24282429

2430+
static inline int
2431+
nonzero_float_compactlong_guard(PyObject *lhs, PyObject *rhs)
2432+
{
2433+
return (
2434+
float_compactlong_guard(lhs, rhs) && !PyLong_IsZero(rhs)
2435+
);
2436+
}
2437+
24292438
#define FLOAT_LONG_ACTION(NAME, OP) \
24302439
static PyObject * \
24312440
(NAME)(PyObject *lhs, PyObject *rhs) \
@@ -2442,13 +2451,22 @@ FLOAT_LONG_ACTION(float_compactlong_true_div, /)
24422451

24432452
/* long-float */
24442453

2445-
static int
2454+
static inline int
24462455
compactlong_float_guard(PyObject *lhs, PyObject *rhs)
24472456
{
24482457
return (
2449-
PyFloat_CheckExact(rhs) &&
24502458
PyLong_CheckExact(lhs) &&
2451-
_PyLong_IsCompact((PyLongObject *)lhs)
2459+
_PyLong_IsCompact((PyLongObject *)lhs) &&
2460+
PyFloat_CheckExact(rhs) &&
2461+
!isnan(PyFloat_AsDouble(rhs))
2462+
);
2463+
}
2464+
2465+
static inline int
2466+
nonzero_compactlong_float_guard(PyObject *lhs, PyObject *rhs)
2467+
{
2468+
return (
2469+
compactlong_float_guard(lhs, rhs) && PyFloat_AsDouble(rhs) != 0.0
24522470
);
24532471
}
24542472

@@ -2469,14 +2487,14 @@ LONG_FLOAT_ACTION(compactlong_float_true_div, /)
24692487
static _PyBinaryOpSpecializationDescr float_compactlong_specs[NB_OPARG_LAST+1] = {
24702488
[NB_ADD] = {float_compactlong_guard, float_compactlong_add},
24712489
[NB_SUBTRACT] = {float_compactlong_guard, float_compactlong_subtract},
2472-
[NB_TRUE_DIVIDE] = {float_compactlong_guard, float_compactlong_true_div},
2490+
[NB_TRUE_DIVIDE] = {nonzero_float_compactlong_guard, float_compactlong_true_div},
24732491
[NB_MULTIPLY] = {float_compactlong_guard, float_compactlong_multiply},
24742492
};
24752493

24762494
static _PyBinaryOpSpecializationDescr compactlong_float_specs[NB_OPARG_LAST+1] = {
24772495
[NB_ADD] = {compactlong_float_guard, compactlong_float_add},
24782496
[NB_SUBTRACT] = {compactlong_float_guard, compactlong_float_subtract},
2479-
[NB_TRUE_DIVIDE] = {compactlong_float_guard, compactlong_float_true_div},
2497+
[NB_TRUE_DIVIDE] = {nonzero_compactlong_float_guard, compactlong_float_true_div},
24802498
[NB_MULTIPLY] = {compactlong_float_guard, compactlong_float_multiply},
24812499
};
24822500

0 commit comments

Comments
 (0)