Skip to content

Commit 532e491

Browse files
committed
Raise OverflowError when converting large int to float
1 parent e427508 commit 532e491

File tree

6 files changed

+41
-31
lines changed

6 files changed

+41
-31
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ PComplex complexFromLongLong(Object cls, long real, long imaginary) {
384384

385385
@Specialization
386386
PComplex complexFromLongLong(Object cls, PInt real, PInt imaginary) {
387-
return createComplex(cls, real.doubleValue(), imaginary.doubleValue());
387+
return createComplex(cls, real.doubleValueWithOverflow(getRaiseNode()), imaginary.doubleValueWithOverflow(getRaiseNode()));
388388
}
389389

390390
@Specialization
@@ -409,7 +409,7 @@ PComplex complexFromLong(Object cls, long real, @SuppressWarnings("unused") PNon
409409

410410
@Specialization(guards = "isNoValue(imag)")
411411
PComplex complexFromLong(Object cls, PInt real, @SuppressWarnings("unused") PNone imag) {
412-
return createComplex(cls, real.doubleValue(), 0);
412+
return createComplex(cls, real.doubleValueWithOverflow(getRaiseNode()), 0);
413413
}
414414

415415
@Specialization(guards = {"isNoValue(imag)", "!isNoValue(number)", "!isString(number)"}, limit = "1")
@@ -433,7 +433,7 @@ PComplex complexFromLongComplex(Object cls, long one, PComplex two) {
433433

434434
@Specialization
435435
PComplex complexFromPIntComplex(Object cls, PInt one, PComplex two) {
436-
return createComplex(cls, one.doubleValue() - two.getImag(), two.getReal());
436+
return createComplex(cls, one.doubleValueWithOverflow(getRaiseNode()) - two.getImag(), two.getReal());
437437
}
438438

439439
@Specialization
@@ -475,12 +475,12 @@ PComplex complexFromComplexPInt(VirtualFrame frame, Object cls, Object one, PInt
475475
PComplex value = getComplexNumberFromObject(frame, one, lib);
476476
if (value == null) {
477477
if (lib.canBeJavaDouble(one)) {
478-
return createComplex(cls, lib.asJavaDouble(one), two.doubleValue());
478+
return createComplex(cls, lib.asJavaDouble(one), two.doubleValueWithOverflow(getRaiseNode()));
479479
} else {
480480
throw raiseFirstArgError(one);
481481
}
482482
}
483-
return createComplex(cls, value.getReal(), value.getImag() + two.doubleValue());
483+
return createComplex(cls, value.getReal(), value.getImag() + two.doubleValueWithOverflow(getRaiseNode()));
484484
}
485485

486486
@Specialization(guards = "!isString(one)", limit = "1")

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MathModuleBuiltins.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public double doD(double value) {
129129

130130
@Specialization
131131
public double doPI(PInt value) {
132-
return count(value.doubleValue());
132+
return count(value.doubleValueWithOverflow(getRaiseNode()));
133133
}
134134

135135
@Specialization(guards = "!isNumber(value)", limit = "1")
@@ -175,6 +175,9 @@ protected static BigDecimal sqrtBigNumber(BigInteger value) {
175175
@TruffleBoundary
176176
@Override
177177
public double doPI(PInt value) {
178+
// Tests require that OverflowError is raised when the value does not fit into double
179+
// but we don't actually need the double value, so this is called for side-effect only:
180+
value.doubleValueWithOverflow(getRaiseNode());
178181
BigInteger bValue = value.getValue();
179182
checkMathDomainError(bValue.compareTo(BigInteger.ZERO) < 0);
180183
return sqrtBigNumber(bValue).doubleValue();

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

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ abstract static class AddNode extends PythonBinaryBuiltinNode {
296296

297297
@Specialization
298298
double doDPi(double left, PInt right) {
299-
return left + right.doubleValue();
299+
return left + right.doubleValueWithOverflow(getRaiseNode());
300300
}
301301

302302
@Specialization
@@ -345,7 +345,7 @@ abstract static class SubNode extends PythonBinaryBuiltinNode {
345345

346346
@Specialization
347347
double doDPi(double left, PInt right) {
348-
return left - right.doubleValue();
348+
return left - right.doubleValueWithOverflow(getRaiseNode());
349349
}
350350

351351
@Specialization
@@ -355,7 +355,7 @@ abstract static class SubNode extends PythonBinaryBuiltinNode {
355355

356356
@Specialization
357357
double doPiD(PInt left, double right) {
358-
return left.doubleValue() - right;
358+
return left.doubleValueWithOverflow(getRaiseNode()) - right;
359359
}
360360

361361
@SuppressWarnings("unused")
@@ -382,7 +382,7 @@ abstract static class MulNode extends PythonBinaryBuiltinNode {
382382

383383
@Specialization
384384
double doDP(double left, PInt right) {
385-
return left * right.doubleValue();
385+
return left * right.doubleValueWithOverflow(getRaiseNode());
386386
}
387387

388388
@Specialization
@@ -412,7 +412,7 @@ Object doDP(VirtualFrame frame, PythonNativeObject left, PInt right,
412412
@Cached FromNativeSubclassNode getFloat) {
413413
Double leftPrimitive = getFloat.execute(frame, left);
414414
if (leftPrimitive != null) {
415-
return leftPrimitive * right.doubleValue();
415+
return leftPrimitive * right.doubleValueWithOverflow(getRaiseNode());
416416
} else {
417417
return PNotImplemented.NOT_IMPLEMENTED;
418418
}
@@ -440,7 +440,7 @@ abstract static class PowerNode extends PythonTernaryBuiltinNode {
440440
@Specialization
441441
double doDPi(double left, PInt right, @SuppressWarnings("unused") PNone none,
442442
@Shared("negativeRaise") @Cached BranchProfile negativeRaise) {
443-
return doOperation(left, right.doubleValue(), negativeRaise);
443+
return doOperation(left, right.doubleValueWithOverflow(getRaiseNode()), negativeRaise);
444444
}
445445

446446
/**
@@ -519,14 +519,14 @@ Object doDLComplex(VirtualFrame frame, long left, double right, PNone none,
519519
double doDPi(VirtualFrame frame, PInt left, double right, @SuppressWarnings("unused") PNone none,
520520
@Shared("powCall") @Cached("create(__POW__)") LookupAndCallTernaryNode callPow,
521521
@Shared("negativeRaise") @Cached BranchProfile negativeRaise) throws UnexpectedResultException {
522-
return doDD(frame, left.doubleValue(), right, none, callPow, negativeRaise);
522+
return doDD(frame, left.doubleValueWithOverflow(getRaiseNode()), right, none, callPow, negativeRaise);
523523
}
524524

525525
@Specialization(replaces = "doDPi")
526526
Object doDPiToComplex(VirtualFrame frame, PInt left, double right, @SuppressWarnings("unused") PNone none,
527527
@Shared("powCall") @Cached("create(__POW__)") LookupAndCallTernaryNode callPow,
528528
@Shared("negativeRaise") @Cached BranchProfile negativeRaise) {
529-
return doDDToComplex(frame, left.doubleValue(), right, none, callPow, negativeRaise);
529+
return doDDToComplex(frame, left.doubleValueWithOverflow(getRaiseNode()), right, none, callPow, negativeRaise);
530530
}
531531

532532
@Specialization
@@ -571,7 +571,7 @@ abstract static class FloorDivNode extends FloatBinaryBuiltinNode {
571571
@Specialization
572572
double doDL(double left, PInt right) {
573573
raiseDivisionByZero(right.isZero());
574-
return Math.floor(left / right.doubleValue());
574+
return Math.floor(left / right.doubleValueWithOverflow(getRaiseNode()));
575575
}
576576

577577
@Specialization
@@ -589,7 +589,7 @@ abstract static class FloorDivNode extends FloatBinaryBuiltinNode {
589589
@Specialization
590590
double doPiD(PInt left, double right) {
591591
raiseDivisionByZero(right == 0.0);
592-
return Math.floor(left.doubleValue() / right);
592+
return Math.floor(left.doubleValueWithOverflow(getRaiseNode()) / right);
593593
}
594594

595595
@SuppressWarnings("unused")
@@ -833,7 +833,7 @@ abstract static class DivNode extends FloatBinaryBuiltinNode {
833833

834834
@Specialization
835835
double doDPi(double left, PInt right) {
836-
return left / right.doubleValue();
836+
return left / right.doubleValueWithOverflow(getRaiseNode());
837837
}
838838

839839
@Specialization
@@ -843,7 +843,7 @@ abstract static class DivNode extends FloatBinaryBuiltinNode {
843843

844844
@Specialization
845845
double div(PInt left, double right) {
846-
return left.doubleValue() / right;
846+
return left.doubleValueWithOverflow(getRaiseNode()) / right;
847847
}
848848

849849
@Specialization
@@ -937,7 +937,7 @@ boolean eqDbLn(double a, long b) {
937937

938938
@Specialization
939939
boolean eqDbPI(double a, PInt b) {
940-
return a == b.doubleValue();
940+
return Double.isFinite(a) && a == b.doubleValue();
941941
}
942942

943943
@Specialization
@@ -955,7 +955,7 @@ Object eqPDb(VirtualFrame frame, PythonNativeObject left, long right,
955955
@Specialization
956956
Object eqPDb(VirtualFrame frame, PythonNativeObject left, PInt right,
957957
@Cached FromNativeSubclassNode getFloat) {
958-
return getFloat.execute(frame, left) == right.doubleValue();
958+
return eqDbPI(getFloat.execute(frame, left), right);
959959
}
960960

961961
@Fallback
@@ -981,7 +981,7 @@ boolean neDbLn(double a, long b) {
981981

982982
@Specialization
983983
boolean neDbPI(double a, PInt b) {
984-
return a != b.doubleValue();
984+
return !(Double.isFinite(a) && a == b.doubleValue());
985985
}
986986

987987
@Specialization
@@ -999,7 +999,7 @@ Object eqPDb(VirtualFrame frame, PythonNativeObject left, long right,
999999
@Specialization
10001000
Object eqPDb(VirtualFrame frame, PythonNativeObject left, PInt right,
10011001
@Cached FromNativeSubclassNode getFloat) {
1002-
return getFloat.execute(frame, left) != right.doubleValue();
1002+
return neDbPI(getFloat.execute(frame, left), right);
10031003
}
10041004

10051005
@Fallback

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/PInt.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
package com.oracle.graal.python.builtins.objects.ints;
2727

2828
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
29+
import static com.oracle.graal.python.runtime.exception.PythonErrorType.OverflowError;
2930

3031
import java.math.BigInteger;
3132

@@ -324,6 +325,19 @@ public static double doubleValue(BigInteger value) {
324325
return value.doubleValue();
325326
}
326327

328+
public double doubleValueWithOverflow(PRaiseNode raise) {
329+
return doubleValueWithOverflow(value, raise);
330+
}
331+
332+
@TruffleBoundary
333+
public static double doubleValueWithOverflow(BigInteger value, PRaiseNode raise) {
334+
double d = value.doubleValue();
335+
if (Double.isInfinite(d)) {
336+
throw raise.raise(OverflowError, ErrorMessages.INT_TOO_LARGE_TO_CONVERT_TO_FLOAT);
337+
}
338+
return d;
339+
}
340+
327341
public int intValue() {
328342
return intValue(value);
329343
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ public abstract class ErrorMessages {
457457
public static final String TIMEOUT_VALUE_MUST_BE_POSITIVE = "timeout value must be positive";
458458
public static final String TIMEOUT_VALUE_TOO_LARGE = "timeout value is too large";
459459
public static final String TOLERANCE_MUST_NON_NEGATIVE = "tolerances must be non-negative";
460-
public static final String TOO_LARGE_TO_CONVERT_TO = "%s too large to convert to %";
460+
public static final String TOO_LARGE_TO_CONVERT_TO = "%s too large to convert to %s";
461461
public static final String TOO_MANY_ARG = "%s: too many arguments";
462462
public static final String TOO_MANY_VALUES_TO_UNPACK = "too many values to unpack (expected %d)";
463463
public static final String TRAILING_S_IN_STR = "Trailing %s in string";

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/util/CastToJavaDoubleNode.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,11 @@
4040
*/
4141
package com.oracle.graal.python.nodes.util;
4242

43-
import static com.oracle.graal.python.runtime.exception.PythonErrorType.OverflowError;
44-
4543
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
4644
import com.oracle.graal.python.builtins.modules.MathGuards;
4745
import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject;
4846
import com.oracle.graal.python.builtins.objects.ints.PInt;
4947
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
50-
import com.oracle.graal.python.nodes.ErrorMessages;
5148
import com.oracle.graal.python.nodes.PNodeWithContext;
5249
import com.oracle.graal.python.nodes.PRaiseNode;
5350
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
@@ -88,11 +85,7 @@ public double toDouble(double x) {
8885
@Specialization
8986
public double toDouble(PInt x,
9087
@Cached PRaiseNode raise) {
91-
double value = x.doubleValue();
92-
if (Double.isInfinite(value)) {
93-
throw raise.raise(OverflowError, ErrorMessages.INT_TOO_LARGE_TO_CONVERT_TO_FLOAT);
94-
}
95-
return value;
88+
return x.doubleValueWithOverflow(raise);
9689
}
9790

9891
@Specialization(limit = "1")

0 commit comments

Comments
 (0)