Skip to content

Commit a16099b

Browse files
committed
Fixed huge right shifts of integers
1 parent d807550 commit a16099b

File tree

2 files changed

+30
-13
lines changed
  • graalpython
    • com.oracle.graal.python.test/src/tests/unittest_tags
    • com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints

2 files changed

+30
-13
lines changed

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_long.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*graalpython.lib-python.3.test.test_long.LongTest.test_from_bytes
1313
*graalpython.lib-python.3.test.test_long.LongTest.test_huge_lshift
1414
*graalpython.lib-python.3.test.test_long.LongTest.test_huge_lshift_of_zero
15+
*graalpython.lib-python.3.test.test_long.LongTest.test_huge_rshift
1516
*graalpython.lib-python.3.test.test_long.LongTest.test_huge_rshift_of_huge
1617
*graalpython.lib-python.3.test.test_long.LongTest.test_karatsuba
1718
*graalpython.lib-python.3.test.test_long.LongTest.test_logs

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

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,9 @@ static long doLLFast(long left, long right, @SuppressWarnings("unused") PNone no
704704
result = Math.multiplyExact(result, base);
705705
}
706706
exponent >>= 1;
707-
base = Math.multiplyExact(base, base);
707+
if (exponent != 0) { // prevent overflow in last iteration
708+
base = Math.multiplyExact(base, base);
709+
}
708710
}
709711
return result;
710712
}
@@ -1313,15 +1315,13 @@ long doLL(long left, long right) {
13131315
}
13141316

13151317
@Specialization
1316-
PInt doIPi(int left, PInt right) {
1317-
raiseNegativeShiftCount(!right.isZeroOrPositive());
1318-
return factory().createInt(op(PInt.longToBigInteger(left), right.intValue()));
1318+
Object doIPi(int left, PInt right) {
1319+
return doHugeShift(PInt.longToBigInteger(left), right);
13191320
}
13201321

13211322
@Specialization
1322-
PInt doLPi(long left, PInt right) {
1323-
raiseNegativeShiftCount(!right.isZeroOrPositive());
1324-
return factory().createInt(op(PInt.longToBigInteger(left), right.intValue()));
1323+
Object doLPi(long left, PInt right) {
1324+
return doHugeShift(PInt.longToBigInteger(left), right);
13251325
}
13261326

13271327
@Specialization
@@ -1331,15 +1331,20 @@ PInt doPiI(PInt left, int right) {
13311331
}
13321332

13331333
@Specialization
1334-
PInt doPiL(PInt left, long right) {
1334+
Object doPiL(PInt left, long right) {
13351335
raiseNegativeShiftCount(right < 0);
1336-
return factory().createInt(op(left.getValue(), (int) right));
1336+
int rightI = (int) right;
1337+
if (rightI == right) {
1338+
return factory().createInt(op(left.getValue(), rightI));
1339+
}
1340+
// right is >= 2**31, BigInteger's bitLength is at most 2**31-1
1341+
// therefore the result of shifting right is just the sign bit
1342+
return left.isNegative() ? -1 : 0;
13371343
}
13381344

13391345
@Specialization
1340-
PInt doPInt(PInt left, PInt right) {
1341-
raiseNegativeShiftCount(!right.isZeroOrPositive());
1342-
return factory().createInt(op(left.getValue(), right.intValue()));
1346+
Object doPInt(PInt left, PInt right) {
1347+
return doHugeShift(left.getValue(), right);
13431348
}
13441349

13451350
private void raiseNegativeShiftCount(boolean cond) {
@@ -1354,8 +1359,19 @@ PNotImplemented doGeneric(Object a, Object b) {
13541359
return PNotImplemented.NOT_IMPLEMENTED;
13551360
}
13561361

1362+
private Object doHugeShift(BigInteger left, PInt right) {
1363+
raiseNegativeShiftCount(!right.isZeroOrPositive());
1364+
try {
1365+
return factory().createInt(op(left, right.intValueExact()));
1366+
} catch (ArithmeticException e) {
1367+
// right is >= 2**31, BigInteger's bitLength is at most 2**31-1
1368+
// therefore the result of shifting right is just the sign bit
1369+
return left.signum() < 0 ? -1 : 0;
1370+
}
1371+
}
1372+
13571373
@TruffleBoundary
1358-
public static BigInteger op(BigInteger left, int right) {
1374+
private static BigInteger op(BigInteger left, int right) {
13591375
return left.shiftRight(right);
13601376
}
13611377

0 commit comments

Comments
 (0)