Skip to content

Commit da2fa45

Browse files
committed
Fix infinite result handling in float nb_power
Fixes #754
1 parent 90e4e52 commit da2fa45

3 files changed

Lines changed: 20 additions & 4 deletions

File tree

graalpython/com.oracle.graal.python.test/src/tests/test_float.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ def test_is_integer(self):
6363
# for doubles this big, all representable values are integers...
6464
assert (2**52 + 0.5).is_integer()
6565

66+
def test_pow_overflow(self):
67+
self.assertRaises(OverflowError, pow, 10.0, 400)
68+
self.assertRaises(OverflowError, pow, 10.0, 400.0)
69+
self.assertRaises(OverflowError, pow, -1e308, 3.0)
70+
self.assertEqual(pow(INF, 2.0), INF)
71+
self.assertEqual(pow(2.0, INF), INF)
72+
6673
def test_rounding(self):
6774
assert round(1.123, 0) == 1
6875
assert round(1.123, 1) == 1.1

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2025, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2026, Oracle and/or its affiliates.
33
* Copyright (c) 2014, Regents of the University of California
44
*
55
* All rights reserved.
@@ -504,7 +504,15 @@ private static double doOperation(Node inliningTarget, double left, double right
504504
if (doSpecialCases(inliningTarget, left, right, raiseNode) == 1) {
505505
return 1.0;
506506
}
507-
return Math.pow(left, right);
507+
return doPow(inliningTarget, left, right, raiseNode);
508+
}
509+
510+
private static double doPow(Node inliningTarget, double left, double right, PRaiseNode raiseNode) {
511+
double result = Math.pow(left, right);
512+
if (Double.isInfinite(result) && Double.isFinite(left) && Double.isFinite(right)) {
513+
throw raiseNode.raise(inliningTarget, OverflowError, ErrorMessages.NUMERICAL_RESULT_OUT_OF_RANGE);
514+
}
515+
return result;
508516
}
509517

510518
@Specialization(rewriteOn = UnexpectedResultException.class)
@@ -522,7 +530,7 @@ static double doDD(VirtualFrame frame, double left, double right, @SuppressWarni
522530
PythonLanguage language = PythonLanguage.get(inliningTarget);
523531
throw new UnexpectedResultException(powerNode.execute(frame, PFactory.createComplex(language, left, 0), PFactory.createComplex(language, right, 0), none));
524532
}
525-
return Math.pow(left, right);
533+
return doPow(inliningTarget, left, right, raiseNode);
526534
}
527535

528536
@Specialization(replaces = "doDD")
@@ -539,7 +547,7 @@ static Object doDDToComplex(VirtualFrame frame, double left, double right, PNone
539547
PythonLanguage language = PythonLanguage.get(inliningTarget);
540548
return powerNode.execute(frame, PFactory.createComplex(language, left, 0), PFactory.createComplex(language, right, 0), none);
541549
}
542-
return Math.pow(left, right);
550+
return doPow(inliningTarget, left, right, raiseNode);
543551
}
544552

545553
@Specialization

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,7 @@ public abstract class ErrorMessages {
473473
public static final TruffleString INPUTS_ARE_NOT_THE_SAME_LENGTH = tsLiteral("Inputs are not the same length");
474474
public static final TruffleString MATH_DOMAIN_ERROR = tsLiteral("math domain error");
475475
public static final TruffleString MATH_RANGE_ERROR = tsLiteral("math range error");
476+
public static final TruffleString NUMERICAL_RESULT_OUT_OF_RANGE = tsLiteral("Numerical result out of range");
476477
public static final TruffleString MAX_MARSHAL_STACK_DEPTH = tsLiteral("Maximum marshal stack depth");
477478
public static final TruffleString M = tsLiteral("%m");
478479
public static final TruffleString MEMORYVIEW_INVALID_SLICE_KEY = tsLiteral("memoryview: invalid slice key");

0 commit comments

Comments
 (0)