diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_float.py b/graalpython/com.oracle.graal.python.test/src/tests/test_float.py index d6f9f6fd92..70f4895178 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_float.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_float.py @@ -63,6 +63,13 @@ def test_is_integer(self): # for doubles this big, all representable values are integers... assert (2**52 + 0.5).is_integer() + def test_pow_overflow(self): + self.assertRaises(OverflowError, pow, 10.0, 400) + self.assertRaises(OverflowError, pow, 10.0, 400.0) + self.assertRaises(OverflowError, pow, -1e308, 3.0) + self.assertEqual(pow(INF, 2.0), INF) + self.assertEqual(pow(2.0, INF), INF) + def test_rounding(self): assert round(1.123, 0) == 1 assert round(1.123, 1) == 1.1 diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java index 0eb8a79a2b..8aa519dbde 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. * Copyright (c) 2014, Regents of the University of California * * All rights reserved. @@ -504,7 +504,15 @@ private static double doOperation(Node inliningTarget, double left, double right if (doSpecialCases(inliningTarget, left, right, raiseNode) == 1) { return 1.0; } - return Math.pow(left, right); + return doPow(inliningTarget, left, right, raiseNode); + } + + private static double doPow(Node inliningTarget, double left, double right, PRaiseNode raiseNode) { + double result = Math.pow(left, right); + if (Double.isInfinite(result) && Double.isFinite(left) && Double.isFinite(right)) { + throw raiseNode.raise(inliningTarget, OverflowError, ErrorMessages.NUMERICAL_RESULT_OUT_OF_RANGE); + } + return result; } @Specialization(rewriteOn = UnexpectedResultException.class) @@ -522,7 +530,7 @@ static double doDD(VirtualFrame frame, double left, double right, @SuppressWarni PythonLanguage language = PythonLanguage.get(inliningTarget); throw new UnexpectedResultException(powerNode.execute(frame, PFactory.createComplex(language, left, 0), PFactory.createComplex(language, right, 0), none)); } - return Math.pow(left, right); + return doPow(inliningTarget, left, right, raiseNode); } @Specialization(replaces = "doDD") @@ -539,7 +547,7 @@ static Object doDDToComplex(VirtualFrame frame, double left, double right, PNone PythonLanguage language = PythonLanguage.get(inliningTarget); return powerNode.execute(frame, PFactory.createComplex(language, left, 0), PFactory.createComplex(language, right, 0), none); } - return Math.pow(left, right); + return doPow(inliningTarget, left, right, raiseNode); } @Specialization diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java index 56f9cabff6..bb4370529d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java @@ -473,6 +473,7 @@ public abstract class ErrorMessages { public static final TruffleString INPUTS_ARE_NOT_THE_SAME_LENGTH = tsLiteral("Inputs are not the same length"); public static final TruffleString MATH_DOMAIN_ERROR = tsLiteral("math domain error"); public static final TruffleString MATH_RANGE_ERROR = tsLiteral("math range error"); + public static final TruffleString NUMERICAL_RESULT_OUT_OF_RANGE = tsLiteral("Numerical result out of range"); public static final TruffleString MAX_MARSHAL_STACK_DEPTH = tsLiteral("Maximum marshal stack depth"); public static final TruffleString M = tsLiteral("%m"); public static final TruffleString MEMORYVIEW_INVALID_SLICE_KEY = tsLiteral("memoryview: invalid slice key");