Skip to content

Commit f5a51fa

Browse files
committed
Use custom int/longValueExact that throws custom checked singleton exception
1 parent 6d07f1c commit f5a51fa

28 files changed

+434
-190
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
* Copyright (c) 2020, 2020, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
42+
package com.oracle.graal.python.nodes.util;
43+
44+
import java.math.BigInteger;
45+
46+
import org.junit.Assert;
47+
import org.junit.Test;
48+
import org.junit.experimental.theories.Theory;
49+
50+
import com.oracle.graal.python.util.OverflowException;
51+
52+
public class BigIntegerUtilsTests {
53+
@Test
54+
public void smallInts() {
55+
checkInt(-2);
56+
checkInt(-2);
57+
checkInt(-1);
58+
checkInt(0);
59+
checkInt(1);
60+
checkInt(2);
61+
}
62+
63+
@Test
64+
public void intLongBoundary() {
65+
checkLong(Integer.MIN_VALUE - 1L);
66+
checkIntOverflow(Integer.MIN_VALUE - 1L);
67+
checkInt(Integer.MIN_VALUE);
68+
checkInt(Integer.MIN_VALUE + 1);
69+
70+
checkInt(Integer.MAX_VALUE - 1);
71+
checkInt(Integer.MAX_VALUE);
72+
checkLong(Integer.MAX_VALUE + 1L);
73+
checkIntOverflow(Integer.MAX_VALUE + 1L);
74+
}
75+
76+
@Theory
77+
@Test
78+
public void long32bitBoundary() {
79+
checkLong(-0x100000001L);
80+
checkIntOverflow(-0x100000001L);
81+
checkLong(-0x100000000L);
82+
checkIntOverflow(-0x100000000L);
83+
checkLong(-0xFFFFFFFFL);
84+
checkIntOverflow(-0xFFFFFFFFL);
85+
86+
checkLong(0xFFFFFFFFL);
87+
checkIntOverflow(0xFFFFFFFFL);
88+
checkLong(0x100000000L);
89+
checkIntOverflow(0x100000000L);
90+
checkLong(0x100000001L);
91+
checkIntOverflow(0x100000001L);
92+
}
93+
94+
@Test
95+
public void longBoundary() {
96+
checkLongOverflow(Long.MIN_VALUE, -1);
97+
checkLong(Long.MIN_VALUE);
98+
checkLong(Long.MIN_VALUE + 1L);
99+
100+
checkLong(Long.MAX_VALUE - 1L);
101+
checkLong(Long.MAX_VALUE);
102+
checkLongOverflow(Long.MAX_VALUE, 1);
103+
104+
checkLongOverflow(Long.MAX_VALUE, Long.MAX_VALUE);
105+
checkLongOverflow(Long.MIN_VALUE, Long.MIN_VALUE);
106+
}
107+
108+
private static void checkInt(int value) {
109+
try {
110+
Assert.assertEquals(value, BigIntegerUtils.intValueExact(BigInteger.valueOf(value)));
111+
} catch (OverflowException e) {
112+
Assert.fail("intValueExact: unexpected overflow");
113+
}
114+
}
115+
116+
private static void checkIntOverflow(long value) {
117+
try {
118+
BigIntegerUtils.intValueExact(BigInteger.valueOf(value));
119+
Assert.fail("intValueExact should overflow for " + value);
120+
} catch (OverflowException e) {
121+
// nop
122+
}
123+
}
124+
125+
private static void checkLong(long value) {
126+
try {
127+
Assert.assertEquals(value, BigIntegerUtils.longValueExact(BigInteger.valueOf(value)));
128+
} catch (OverflowException e) {
129+
Assert.fail("intValueExact: unexpected overflow");
130+
}
131+
}
132+
133+
private static void checkLongOverflow(long value1, long value2) {
134+
try {
135+
BigInteger value = BigInteger.valueOf(value1).add(BigInteger.valueOf(value2));
136+
BigIntegerUtils.longValueExact(value);
137+
Assert.fail("intValueExact should overflow for " + value);
138+
} catch (OverflowException e) {
139+
// nop
140+
}
141+
}
142+
}

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@
160160
import com.oracle.graal.python.runtime.PythonParser.ParserMode;
161161
import com.oracle.graal.python.runtime.exception.PException;
162162
import com.oracle.graal.python.runtime.exception.PythonErrorType;
163+
import com.oracle.graal.python.util.OverflowException;
163164
import com.oracle.graal.python.util.PythonUtils;
164165
import com.oracle.graal.python.util.Supplier;
165166
import com.oracle.truffle.api.Assumption;
@@ -989,12 +990,13 @@ long doId(int integer) {
989990

990991
@Specialization
991992
long doId(PInt value,
993+
@Cached BranchProfile overflowProfile,
992994
@Shared("isBuiltin") @Cached IsBuiltinClassProfile isBuiltin) {
993995
if (isBuiltin.profileIsAnyBuiltinObject(value)) {
994996
try {
995997
return doId(value.intValueExact());
996-
} catch (ArithmeticException e) {
997-
// fall through
998+
} catch (OverflowException e) {
999+
overflowProfile.enter();
9981000
}
9991001
}
10001002
return doGeneric(value);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ static boolean doLong(long checkID) {
481481
static boolean doLong(PInt checkID) {
482482
try {
483483
return doInt(checkID.intValueExact());
484-
} catch (ArithmeticException e) {
484+
} catch (OverflowException e) {
485485
return false;
486486
}
487487
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
import java.util.concurrent.TimeUnit;
8585

8686
import com.oracle.graal.python.nodes.PGuards;
87+
import com.oracle.graal.python.util.OverflowException;
8788
import org.graalvm.nativeimage.ImageInfo;
8889
import org.graalvm.nativeimage.ProcessProperties;
8990

@@ -903,8 +904,8 @@ int dup(VirtualFrame frame, int fd, int fd2) {
903904
}
904905
}
905906

906-
@Specialization(rewriteOn = ArithmeticException.class)
907-
int dupPInt(VirtualFrame frame, PInt fd, PInt fd2) {
907+
@Specialization(rewriteOn = OverflowException.class)
908+
int dupPInt(VirtualFrame frame, PInt fd, PInt fd2) throws OverflowException {
908909
try {
909910
return getResources().dup2(fd.intValueExact(), fd2.intValueExact());
910911
} catch (IOException e) {
@@ -916,7 +917,7 @@ int dupPInt(VirtualFrame frame, PInt fd, PInt fd2) {
916917
int dupOvf(VirtualFrame frame, PInt fd, PInt fd2) {
917918
try {
918919
return dupPInt(frame, fd, fd2);
919-
} catch (ArithmeticException e) {
920+
} catch (OverflowException e) {
920921
throw raiseOSError(frame, OSErrorEnum.EBADF);
921922
}
922923
}
@@ -1876,7 +1877,7 @@ PTuple getTerminalSize(VirtualFrame frame, PInt fd) {
18761877
if (getContext().getResources().getFileChannel(value) == null) {
18771878
throw raiseOSError(frame, OSErrorEnum.EBADF);
18781879
}
1879-
} catch (ArithmeticException e) {
1880+
} catch (OverflowException e) {
18801881
throw raise(PythonErrorType.OverflowError, ErrorMessages.PYTHON_INT_TOO_LARGE_TO_CONV_TO, "C long");
18811882
}
18821883
return factory().createTuple(new Object[]{getTerminalWidth(), getTerminalHeight()});

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,7 +1423,7 @@ Object doUnicode(VirtualFrame frame, String s, long elementSize, long elements,
14231423
Object doUnicode(VirtualFrame frame, String s, PInt elementSize, @SuppressWarnings("unused") PNone elements, Object errorMarker) {
14241424
try {
14251425
return doUnicode(frame, s, elementSize.longValueExact(), -1, errorMarker);
1426-
} catch (ArithmeticException e) {
1426+
} catch (OverflowException e) {
14271427
return raiseNative(frame, errorMarker, PythonErrorType.ValueError, ErrorMessages.INVALID_PARAMS);
14281428
}
14291429
}
@@ -1432,7 +1432,7 @@ Object doUnicode(VirtualFrame frame, String s, PInt elementSize, @SuppressWarnin
14321432
Object doUnicode(VirtualFrame frame, String s, PInt elementSize, PInt elements, Object errorMarker) {
14331433
try {
14341434
return doUnicode(frame, s, elementSize.longValueExact(), elements.longValueExact(), errorMarker);
1435-
} catch (ArithmeticException e) {
1435+
} catch (OverflowException e) {
14361436
return raiseNative(frame, errorMarker, PythonErrorType.ValueError, ErrorMessages.INVALID_PARAMS);
14371437
}
14381438
}
@@ -2088,8 +2088,8 @@ PBytes doLongOvf(long size,
20882088
}
20892089
}
20902090

2091-
@Specialization(rewriteOn = ArithmeticException.class)
2092-
PBytes doPInt(PInt size) {
2091+
@Specialization(rewriteOn = OverflowException.class)
2092+
PBytes doPInt(PInt size) throws OverflowException {
20932093
return doInt(size.intValueExact());
20942094
}
20952095

@@ -2098,7 +2098,7 @@ PBytes doPIntOvf(PInt size,
20982098
@Shared("raiseNode") @Cached PRaiseNode raiseNode) {
20992099
try {
21002100
return doInt(size.intValueExact());
2101-
} catch (ArithmeticException e) {
2101+
} catch (OverflowException e) {
21022102
throw raiseNode.raiseNumberTooLarge(IndexError, size);
21032103
}
21042104
}
@@ -2504,7 +2504,7 @@ long doPointer(PInt n,
25042504
@Cached BranchProfile overflowProfile) {
25052505
try {
25062506
return n.longValueExact();
2507-
} catch (ArithmeticException e) {
2507+
} catch (OverflowException e) {
25082508
overflowProfile.enter();
25092509
throw raise(OverflowError);
25102510
}

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
import com.oracle.graal.python.runtime.PythonCore;
6767
import com.oracle.graal.python.runtime.exception.PythonErrorType;
6868
import com.oracle.truffle.api.CompilerDirectives;
69+
import com.oracle.graal.python.util.OverflowException;
6970
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
7071
import com.oracle.truffle.api.dsl.Cached;
7172
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
@@ -164,8 +165,8 @@ int alarm(long seconds) {
164165
return 0;
165166
}
166167

167-
@Specialization(rewriteOn = ArithmeticException.class)
168-
int alarm(PInt seconds) {
168+
@Specialization(rewriteOn = OverflowException.class)
169+
int alarm(PInt seconds) throws OverflowException {
169170
Signals.scheduleAlarm(seconds.longValueExact());
170171
return 0;
171172
}
@@ -175,7 +176,7 @@ int alarmOvf(PInt seconds) {
175176
try {
176177
Signals.scheduleAlarm(seconds.longValueExact());
177178
return 0;
178-
} catch (ArithmeticException e) {
179+
} catch (OverflowException e) {
179180
throw raise(PythonErrorType.OverflowError, ErrorMessages.PYTHON_INT_TOO_LARGE_TO_CONV_TO, "C long");
180181
}
181182
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -386,10 +386,10 @@ PFrame countedLongOvf(VirtualFrame frame, long num,
386386
}
387387
}
388388

389-
@Specialization(rewriteOn = ArithmeticException.class)
389+
@Specialization(rewriteOn = OverflowException.class)
390390
PFrame countedPInt(VirtualFrame frame, PInt num,
391391
@Shared("caller") @Cached ReadCallerFrameNode readCallerNode,
392-
@Shared("callStackDepthProfile") @Cached("createBinaryProfile()") ConditionProfile callStackDepthProfile) {
392+
@Shared("callStackDepthProfile") @Cached("createBinaryProfile()") ConditionProfile callStackDepthProfile) throws OverflowException {
393393
return counted(frame, num.intValueExact(), readCallerNode, callStackDepthProfile);
394394
}
395395

@@ -399,7 +399,7 @@ PFrame countedPIntOvf(VirtualFrame frame, PInt num,
399399
@Shared("callStackDepthProfile") @Cached("createBinaryProfile()") ConditionProfile callStackDepthProfile) {
400400
try {
401401
return counted(frame, num.intValueExact(), readCallerNode, callStackDepthProfile);
402-
} catch (ArithmeticException e) {
402+
} catch (OverflowException e) {
403403
throw raiseCallStackDepth();
404404
}
405405
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesBuiltins.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage;
106106
import com.oracle.graal.python.runtime.sequence.storage.IntSequenceStorage;
107107
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
108+
import com.oracle.graal.python.util.OverflowException;
108109
import com.oracle.graal.python.util.PythonUtils;
109110
import com.oracle.truffle.api.CompilerAsserts;
110111
import com.oracle.truffle.api.CompilerDirectives;
@@ -1386,7 +1387,7 @@ private AbstractSplitNode getRecursiveNode() {
13861387
private int getIntValue(PInt from) {
13871388
try {
13881389
return from.intValueExact();
1389-
} catch (ArithmeticException e) {
1390+
} catch (OverflowException e) {
13901391
throw raise(PythonErrorType.OverflowError, ErrorMessages.PYTHON_INT_TOO_LARGE_TO_CONV_TO, "C long");
13911392
}
13921393
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@
135135
import com.oracle.graal.python.runtime.exception.PythonErrorType;
136136
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
137137
import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage;
138+
import com.oracle.graal.python.util.OverflowException;
138139
import com.oracle.truffle.api.Assumption;
139140
import com.oracle.truffle.api.CompilerAsserts;
140141
import com.oracle.truffle.api.CompilerDirectives;
@@ -2344,7 +2345,7 @@ static int doPIntToInt32Signed(PInt obj, @SuppressWarnings("unused") int signed,
23442345
@Shared("raiseNode") @Cached PRaiseNode raiseNode) {
23452346
try {
23462347
return obj.intValueExact();
2347-
} catch (ArithmeticException e) {
2348+
} catch (OverflowException e) {
23482349
// fall through
23492350
}
23502351
errorProfile.enter();
@@ -2368,7 +2369,7 @@ static long doPIntToInt64Signed(PInt obj, @SuppressWarnings("unused") int signed
23682369
@Shared("raiseNode") @Cached PRaiseNode raiseNode) {
23692370
try {
23702371
return obj.longValueExact();
2371-
} catch (ArithmeticException e) {
2372+
} catch (OverflowException e) {
23722373
// fall through
23732374
}
23742375
errorProfile.enter();

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ static int doPIntTo32Bit(PInt obj, int signed, @SuppressWarnings("unused") long
548548
}
549549
return obj.intValue();
550550
}
551-
} catch (ArithmeticException e) {
551+
} catch (OverflowException e) {
552552
// fall through
553553
}
554554
return raiseTooLarge(raiseNativeNode, targetTypeSize);
@@ -567,7 +567,7 @@ static long doPIntTo64Bit(PInt obj, int signed, @SuppressWarnings("unused") long
567567
}
568568
return obj.longValue();
569569
}
570-
} catch (ArithmeticException e) {
570+
} catch (OverflowException e) {
571571
// fall through
572572
}
573573
return raiseTooLarge(raiseNativeNode, targetTypeSize);

0 commit comments

Comments
 (0)