Skip to content

Commit ec969c7

Browse files
committed
Avoid catching ArithmeticException in PE code when working with ranges
1 parent be77d44 commit ec969c7

File tree

6 files changed

+190
-80
lines changed

6 files changed

+190
-80
lines changed

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

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@
154154
import com.oracle.graal.python.builtins.objects.range.PBigRange;
155155
import com.oracle.graal.python.builtins.objects.range.PIntRange;
156156
import com.oracle.graal.python.builtins.objects.range.RangeNodes;
157+
import com.oracle.graal.python.builtins.objects.range.RangeNodes.LenOfIntRangeNodeExact;
157158
import com.oracle.graal.python.builtins.objects.set.PFrozenSet;
158159
import com.oracle.graal.python.builtins.objects.set.PSet;
159160
import com.oracle.graal.python.builtins.objects.str.PString;
@@ -212,6 +213,7 @@
212213
import com.oracle.graal.python.runtime.sequence.storage.ObjectSequenceStorage;
213214
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
214215
import com.oracle.graal.python.util.PythonUtils;
216+
import com.oracle.graal.python.util.OverflowException;
215217
import com.oracle.truffle.api.Assumption;
216218
import com.oracle.truffle.api.CompilerAsserts;
217219
import com.oracle.truffle.api.CompilerDirectives;
@@ -700,7 +702,7 @@ public PythonObject reversed(@SuppressWarnings("unused") Object cls, PIntRange r
700702
int lstart = range.getIntStart();
701703
int lstop = range.getIntStop();
702704
int lstep = range.getIntStep();
703-
int ulen = lenOfRangeNode.len(lstart, lstop, lstep);
705+
int ulen = lenOfRangeNode.executeInt(lstart, lstop, lstep);
704706
int new_stop = lstart - lstep;
705707
int new_start = new_stop + ulen * lstep;
706708

@@ -714,7 +716,7 @@ public PythonObject reversed(@SuppressWarnings("unused") Object cls, PBigRange r
714716
BigInteger lstart = range.getBigIntegerStart();
715717
BigInteger lstop = range.getBigIntegerStop();
716718
BigInteger lstep = range.getBigIntegerStep();
717-
BigInteger ulen = (BigInteger) lenOfRangeNode.execute(lstart, lstop, lstep);
719+
BigInteger ulen = lenOfRangeNode.execute(lstart, lstop, lstep);
718720

719721
BigInteger new_stop = lstart.subtract(lstep);
720722
BigInteger new_start = new_stop.add(ulen.multiply(lstep));
@@ -1648,9 +1650,9 @@ public abstract static class RangeNode extends PythonQuaternaryBuiltinNode {
16481650
Object doIntStop(Object cls, int stop, @SuppressWarnings("unused") PNone start, @SuppressWarnings("unused") PNone step,
16491651
@Shared("stepZeroProfile") @Cached ConditionProfile stepZeroProfile,
16501652
@Shared("exceptionProfile") @Cached BranchProfile exceptionProfile,
1651-
@Shared("lenOfRangeNode") @Cached RangeNodes.LenOfRangeNode lenOfRangeNode,
1653+
@Shared("lenOfRangeNodeExact") @Cached LenOfIntRangeNodeExact lenOfRangeNodeExact,
16521654
@Shared("createBigRangeNode") @Cached RangeNodes.CreateBigRangeNode createBigRangeNode) {
1653-
return doInt(cls, 0, stop, 1, stepZeroProfile, exceptionProfile, lenOfRangeNode, createBigRangeNode);
1655+
return doInt(cls, 0, stop, 1, stepZeroProfile, exceptionProfile, lenOfRangeNodeExact, createBigRangeNode);
16541656
}
16551657

16561658
@Specialization(guards = "isStop(start, stop, step)")
@@ -1664,21 +1666,21 @@ Object doPintStop(Object cls, PInt stop, @SuppressWarnings("unused") PNone start
16641666
Object doGenericStop(Object cls, Object stop, @SuppressWarnings("unused") PNone start, @SuppressWarnings("unused") PNone step,
16651667
@Shared("stepZeroProfile") @Cached ConditionProfile stepZeroProfile,
16661668
@Shared("exceptionProfile") @Cached BranchProfile exceptionProfile,
1667-
@Shared("lenOfRangeNode") @Cached RangeNodes.LenOfRangeNode lenOfRangeNode,
1669+
@Shared("lenOfRangeNodeExact") @Cached LenOfIntRangeNodeExact lenOfRangeNodeExact,
16681670
@Shared("createBigRangeNode") @Cached RangeNodes.CreateBigRangeNode createBigRangeNode,
16691671
@Shared("polGeneric") @CachedLibrary(limit = "3") PythonObjectLibrary pol,
16701672
@Shared("libGeneric") @CachedLibrary(limit = "3") InteropLibrary lib) {
1671-
return doGeneric(cls, 0, stop, 1, stepZeroProfile, exceptionProfile, lenOfRangeNode, createBigRangeNode, pol, lib);
1673+
return doGeneric(cls, 0, stop, 1, stepZeroProfile, exceptionProfile, lenOfRangeNodeExact, createBigRangeNode, pol, lib);
16721674
}
16731675

16741676
// start stop
16751677
@Specialization(guards = "isStartStop(start, stop, step)")
16761678
Object doIntStartStop(Object cls, int start, int stop, @SuppressWarnings("unused") PNone step,
16771679
@Shared("stepZeroProfile") @Cached ConditionProfile stepZeroProfile,
16781680
@Shared("exceptionProfile") @Cached BranchProfile exceptionProfile,
1679-
@Shared("lenOfRangeNode") @Cached RangeNodes.LenOfRangeNode lenOfRangeNode,
1681+
@Shared("lenOfRangeNodeExact") @Cached LenOfIntRangeNodeExact lenOfRangeNodeExact,
16801682
@Shared("createBigRangeNode") @Cached RangeNodes.CreateBigRangeNode createBigRangeNode) {
1681-
return doInt(cls, start, stop, 1, stepZeroProfile, exceptionProfile, lenOfRangeNode, createBigRangeNode);
1683+
return doInt(cls, start, stop, 1, stepZeroProfile, exceptionProfile, lenOfRangeNodeExact, createBigRangeNode);
16821684
}
16831685

16841686
@Specialization(guards = "isStartStop(start, stop, step)")
@@ -1692,27 +1694,27 @@ Object doPintStartStop(Object cls, PInt start, PInt stop, @SuppressWarnings("unu
16921694
Object doGenericStartStop(Object cls, Object start, Object stop, @SuppressWarnings("unused") PNone step,
16931695
@Shared("stepZeroProfile") @Cached ConditionProfile stepZeroProfile,
16941696
@Shared("exceptionProfile") @Cached BranchProfile exceptionProfile,
1695-
@Shared("lenOfRangeNode") @Cached RangeNodes.LenOfRangeNode lenOfRangeNode,
1697+
@Shared("lenOfRangeNodeExact") @Cached LenOfIntRangeNodeExact lenOfRangeNodeExact,
16961698
@Shared("createBigRangeNode") @Cached RangeNodes.CreateBigRangeNode createBigRangeNode,
16971699
@Shared("polGeneric") @CachedLibrary(limit = "3") PythonObjectLibrary pol,
16981700
@Shared("libGeneric") @CachedLibrary(limit = "3") InteropLibrary lib) {
1699-
return doGeneric(cls, start, stop, 1, stepZeroProfile, exceptionProfile, lenOfRangeNode, createBigRangeNode, pol, lib);
1701+
return doGeneric(cls, start, stop, 1, stepZeroProfile, exceptionProfile, lenOfRangeNodeExact, createBigRangeNode, pol, lib);
17001702
}
17011703

17021704
// start stop step
17031705
@Specialization
17041706
Object doInt(@SuppressWarnings("unused") Object cls, int start, int stop, int step,
17051707
@Shared("stepZeroProfile") @Cached ConditionProfile stepZeroProfile,
17061708
@Shared("exceptionProfile") @Cached BranchProfile exceptionProfile,
1707-
@Shared("lenOfRangeNode") @Cached RangeNodes.LenOfRangeNode lenOfRangeNode,
1709+
@Shared("lenOfRangeNodeExact") @Cached LenOfIntRangeNodeExact lenOfRangeNode,
17081710
@Shared("createBigRangeNode") @Cached RangeNodes.CreateBigRangeNode createBigRangeNode) {
17091711
if (stepZeroProfile.profile(step == 0)) {
17101712
throw raise(ValueError, ARG_MUST_NOT_BE_ZERO, "range()", 3);
17111713
}
17121714
try {
1713-
int len = lenOfRangeNode.len(start, stop, step);
1715+
int len = lenOfRangeNode.executeInt(start, stop, step);
17141716
return factory().createIntRange(start, stop, step, len);
1715-
} catch (ArithmeticException e) {
1717+
} catch (OverflowException e) {
17161718
exceptionProfile.enter();
17171719
return createBigRangeNode.execute(start, stop, step, factory());
17181720
}
@@ -1725,20 +1727,20 @@ Object doPint(@SuppressWarnings("unused") Object cls, PInt start, PInt stop, PIn
17251727
if (stepZeroProfile.profile(step.isZero())) {
17261728
throw raise(ValueError, ARG_MUST_NOT_BE_ZERO, "range()", 3);
17271729
}
1728-
BigInteger len = (BigInteger) lenOfRangeNode.execute(start, stop, step);
1730+
BigInteger len = lenOfRangeNode.execute(start.getValue(), stop.getValue(), step.getValue());
17291731
return factory().createBigRange(start, stop, step, factory().createInt(len));
17301732
}
17311733

17321734
@Specialization(guards = "isStartStopStep(start, stop, step)")
17331735
Object doGeneric(@SuppressWarnings("unused") Object cls, Object start, Object stop, Object step,
17341736
@Shared("stepZeroProfile") @Cached ConditionProfile stepZeroProfile,
17351737
@Shared("exceptionProfile") @Cached BranchProfile exceptionProfile,
1736-
@Shared("lenOfRangeNode") @Cached RangeNodes.LenOfRangeNode lenOfRangeNode,
1738+
@Shared("lenOfRangeNodeExact") @Cached LenOfIntRangeNodeExact lenOfRangeNodeExact,
17371739
@Shared("createBigRangeNode") @Cached RangeNodes.CreateBigRangeNode createBigRangeNode,
17381740
@Shared("polGeneric") @CachedLibrary(limit = "3") PythonObjectLibrary pol,
17391741
@Shared("libGeneric") @CachedLibrary(limit = "3") InteropLibrary lib) {
17401742
if (canBeInt(start, stop, step, lib)) {
1741-
return doInt(cls, pol.asSize(start), pol.asSize(stop), pol.asSize(step), stepZeroProfile, exceptionProfile, lenOfRangeNode, createBigRangeNode);
1743+
return doInt(cls, pol.asSize(start), pol.asSize(stop), pol.asSize(step), stepZeroProfile, exceptionProfile, lenOfRangeNodeExact, createBigRangeNode);
17421744
} else if (canBePint(start, stop, step, pol)) {
17431745
return createBigRangeNode.execute(start, stop, step, factory());
17441746
} else {
@@ -1747,7 +1749,7 @@ Object doGeneric(@SuppressWarnings("unused") Object cls, Object start, Object st
17471749
Object lstep = pol.asIndex(step);
17481750

17491751
if (canBeInt(start, stop, step, lib)) {
1750-
return doInt(cls, pol.asSize(start), pol.asSize(stop), pol.asSize(step), stepZeroProfile, exceptionProfile, lenOfRangeNode, createBigRangeNode);
1752+
return doInt(cls, pol.asSize(start), pol.asSize(stop), pol.asSize(step), stepZeroProfile, exceptionProfile, lenOfRangeNodeExact, createBigRangeNode);
17511753
} else {
17521754
return createBigRangeNode.execute(lstart, lstop, lstep, factory());
17531755
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,10 @@
125125
import com.oracle.graal.python.nodes.subscript.SliceLiteralNode.ComputeIndices;
126126
import com.oracle.graal.python.nodes.util.CastToByteNode;
127127
import com.oracle.graal.python.nodes.util.CastToJavaByteNode;
128+
import com.oracle.graal.python.nodes.util.ExactMath;
128129
import com.oracle.graal.python.runtime.PythonContext;
129130
import com.oracle.graal.python.runtime.PythonOptions;
130131
import com.oracle.graal.python.runtime.exception.PException;
131-
import com.oracle.graal.python.runtime.exception.PythonErrorType;
132132
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
133133
import com.oracle.graal.python.runtime.sequence.PSequence;
134134
import com.oracle.graal.python.runtime.sequence.storage.BasicSequenceStorage;
@@ -2301,8 +2301,8 @@ public ExtendNode(GenNodeSupplier genNodeProvider) {
23012301

23022302
private static int lengthResult(int current, int ext) {
23032303
try {
2304-
return Math.addExact(current, ext);
2305-
} catch (ArithmeticException e) {
2304+
return ExactMath.addExact(current, ext);
2305+
} catch (OverflowException e) {
23062306
// (mq) There is no need to ensure capacity as we either
23072307
// run out of memory or dealing with a fake length.
23082308
return current;
@@ -2314,9 +2314,7 @@ SequenceStorage doWithStorage(SequenceStorage left, PSequence seq, int len,
23142314
@SuppressWarnings("unused") @CachedLibrary(limit = "3") PythonObjectLibrary lib,
23152315
@Cached GetSequenceStorageNode getStorageNode,
23162316
@Cached LenNode lenNode,
2317-
@Cached PRaiseNode raiseNode,
23182317
@Cached EnsureCapacityNode ensureCapacityNode,
2319-
@Cached BranchProfile overflowErrorProfile,
23202318
@Cached ConcatBaseNode concatStoragesNode) {
23212319
SequenceStorage right = getStorageNode.execute(seq);
23222320
int lenLeft = lenNode.execute(left);
@@ -2328,15 +2326,13 @@ SequenceStorage doWithStorage(SequenceStorage left, PSequence seq, int len,
23282326
}
23292327
SequenceStorage dest = null;
23302328
try {
2329+
// EnsureCapacityNode handles the overflow and raises an error
23312330
dest = ensureCapacityNode.execute(left, lenResult);
23322331
return concatStoragesNode.execute(dest, left, right);
23332332
} catch (SequenceStoreException e) {
23342333
dest = generalizeStore(dest, e.getIndicationValue());
23352334
dest = ensureCapacityNode.execute(dest, lenResult);
23362335
return concatStoragesNode.execute(dest, left, right);
2337-
} catch (ArithmeticException e) {
2338-
overflowErrorProfile.enter();
2339-
throw raiseNode.raise(PythonErrorType.OverflowError);
23402336
}
23412337
}
23422338

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/iterator/IteratorBuiltins.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ public Object reduce(VirtualFrame frame, PIntRangeIterator self,
405405
int start = self.getReduceStart();
406406
int stop = self.getReduceStop();
407407
int step = self.getReduceStep();
408-
int len = (int) length.execute(start, stop, step);
408+
int len = length.executeInt(start, stop, step);
409409
return reduceInternal(frame, factory().createIntRange(start, stop, step, len), self.getIndex(), context, pol);
410410
}
411411

@@ -417,7 +417,7 @@ public Object reduce(VirtualFrame frame, PBigRangeIterator self,
417417
PInt start = self.getReduceStart();
418418
PInt stop = self.getReduceStop(factory());
419419
PInt step = self.getReduceStep();
420-
PInt len = factory().createInt((BigInteger) length.execute(start, stop, step));
420+
PInt len = factory().createInt(length.execute(start.getValue(), stop.getValue(), step.getValue()));
421421
return reduceInternal(frame, factory().createBigRange(start, stop, step, len), self.getLongIndex(factory()), context, pol);
422422
}
423423

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/range/RangeBuiltins.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import com.oracle.graal.python.builtins.objects.object.PythonObject;
5757
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
5858
import com.oracle.graal.python.builtins.objects.range.RangeNodes.CoerceToBigRange;
59+
import com.oracle.graal.python.builtins.objects.range.RangeNodes.LenOfIntRangeNodeExact;
5960
import com.oracle.graal.python.builtins.objects.range.RangeNodes.PRangeStartNode;
6061
import com.oracle.graal.python.builtins.objects.range.RangeNodes.PRangeStepNode;
6162
import com.oracle.graal.python.builtins.objects.range.RangeNodes.PRangeStopNode;
@@ -364,16 +365,17 @@ Object doPRangeSliceSlowPath(PIntRange self, PSlice slice,
364365
@Cached IsBuiltinClassProfile profileError,
365366
@Cached CoerceToBigRange toBigIntRange,
366367
@Cached CoerceToObjectSlice toBigIntSlice,
368+
@Cached LenOfIntRangeNodeExact lenOfRangeNodeExact,
367369
@Cached RangeNodes.LenOfRangeNode lenOfRangeNode) {
368370
try {
369371
final int rStart = self.getIntStart();
370372
final int rStep = self.getIntStep();
371373
SliceInfo info = compute.execute(slice, self.getIntLength());
372-
return createRange(info, rStart, rStep, lenOfRangeNode);
374+
return createRange(info, rStart, rStep, lenOfRangeNodeExact);
373375
} catch (PException pe) {
374376
pe.expect(PythonBuiltinClassType.OverflowError, profileError);
375377
// pass
376-
} catch (CannotCastException | ArithmeticException e) {
378+
} catch (CannotCastException | OverflowException e) {
377379
// pass
378380
}
379381
PBigRange rangeBI = toBigIntRange.execute(self, factory());
@@ -390,17 +392,18 @@ Object doPRangeSliceSlowPath(PBigRange self, PSlice slice,
390392
@Cached IsBuiltinClassProfile profileError,
391393
@Cached CoerceToBigRange toBigIntRange,
392394
@Cached CoerceToObjectSlice toBigIntSlice,
395+
@Cached LenOfIntRangeNodeExact lenOfRangeNodeExact,
393396
@Cached RangeNodes.LenOfRangeNode lenOfRangeNode,
394397
@CachedLibrary(limit = "3") PythonObjectLibrary lib) {
395398
try {
396399
int rStart = lib.asSize(self.getStart());
397400
int rStep = lib.asSize(self.getStep());
398401
SliceInfo info = compute.execute(slice, lib.asSize(self.getLength()));
399-
return createRange(info, rStart, rStep, lenOfRangeNode);
402+
return createRange(info, rStart, rStep, lenOfRangeNodeExact);
400403
} catch (PException pe) {
401404
pe.expect(PythonBuiltinClassType.OverflowError, profileError);
402405
// pass
403-
} catch (CannotCastException | ArithmeticException e) {
406+
} catch (CannotCastException | OverflowException e) {
404407
// pass
405408
}
406409
PBigRange rangeBI = toBigIntRange.execute(self, factory());
@@ -419,6 +422,7 @@ Object doGeneric(PRange self, Object idx,
419422
@Cached IsBuiltinClassProfile profileError,
420423
@Cached CoerceToBigRange toBigIntRange,
421424
@Cached CoerceToObjectSlice toBigIntSlice,
425+
@Cached LenOfIntRangeNodeExact lenOfRangeNodeExact,
422426
@Cached RangeNodes.LenOfRangeNode lenOfRangeNode,
423427
@Cached CastToJavaBigIntegerNode toBigInt,
424428
@CachedLibrary(limit = "getCallSiteInlineCacheMaxDepth()") PythonObjectLibrary pol) {
@@ -431,9 +435,9 @@ Object doGeneric(PRange self, Object idx,
431435
if (isSliceIndexProfile.profile(idx instanceof PSlice)) {
432436
PSlice slice = (PSlice) idx;
433437
if (self instanceof PIntRange) {
434-
return doPRangeSliceSlowPath((PIntRange) self, slice, compute, profileError, toBigIntRange, toBigIntSlice, lenOfRangeNode);
438+
return doPRangeSliceSlowPath((PIntRange) self, slice, compute, profileError, toBigIntRange, toBigIntSlice, lenOfRangeNodeExact, lenOfRangeNode);
435439
}
436-
return doPRangeSliceSlowPath((PBigRange) self, slice, compute, profileError, toBigIntRange, toBigIntSlice, lenOfRangeNode, pol);
440+
return doPRangeSliceSlowPath((PBigRange) self, slice, compute, profileError, toBigIntRange, toBigIntSlice, lenOfRangeNodeExact, lenOfRangeNode, pol);
437441
}
438442
throw raise(TypeError, ErrorMessages.OBJ_INDEX_MUST_BE_INT_OR_SLICES, "range", idx);
439443
}
@@ -455,11 +459,11 @@ private BigInteger computeBigRangeItem(PBigRange range, Object idx, CastToJavaBi
455459
return i;
456460
}
457461

458-
private PIntRange createRange(SliceInfo info, int rStart, int rStep, RangeNodes.LenOfRangeNode lenOfRangeNode) {
462+
private PIntRange createRange(SliceInfo info, int rStart, int rStep, LenOfIntRangeNodeExact lenOfRangeNode) throws OverflowException {
459463
int newStep = rStep * info.step;
460464
int newStart = rStart + info.start * rStep;
461465
int newStop = rStart + info.stop * rStep;
462-
int len = (int) lenOfRangeNode.execute(newStart, newStop, newStep);
466+
int len = lenOfRangeNode.executeInt(newStart, newStop, newStep);
463467
return factory().createIntRange(newStart, newStop, newStep, len);
464468
}
465469

@@ -472,7 +476,7 @@ private PBigRange createRange(SliceObjectInfo info, BigInteger rStart, BigIntege
472476
BigInteger step = rStep.multiply(sliceStep);
473477
BigInteger start = rStart.add(sliceStart.multiply(rStep));
474478
BigInteger stop = rStart.add(sliceStop.multiply(rStep));
475-
BigInteger len = (BigInteger) lenOfRangeNode.execute(start, stop, step);
479+
BigInteger len = lenOfRangeNode.execute(start, stop, step);
476480
return factory().createBigRange(factory().createInt(start), factory().createInt(stop), factory().createInt(step), factory().createInt(len));
477481
}
478482
}

0 commit comments

Comments
 (0)