Skip to content

Commit f2ee178

Browse files
committed
Ensure loopCounts never overflow.
1 parent 1c65a11 commit f2ee178

7 files changed

Lines changed: 53 additions & 42 deletions

File tree

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

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2025, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2026, Oracle and/or its affiliates.
33
* Copyright (c) 2013, Regents of the University of California
44
*
55
* All rights reserved.
@@ -498,19 +498,21 @@ static boolean doObject(VirtualFrame frame, Object object,
498498
@Cached PyIterNextNode nextNode,
499499
@Cached PyObjectIsTrueNode isTrueNode) {
500500
Object iterator = getIter.execute(frame, inliningTarget, object);
501-
int nbrIter = 0;
501+
int loopCount = 0;
502502

503503
while (true) {
504504
try {
505505
Object next = nextNode.execute(frame, inliningTarget, iterator);
506-
nbrIter++;
506+
if (CompilerDirectives.hasNextTier() && loopCount < Integer.MAX_VALUE) {
507+
loopCount++;
508+
}
507509
if (!isTrueNode.execute(frame, next)) {
508510
return false;
509511
}
510512
} catch (IteratorExhausted e) {
511513
break;
512514
} finally {
513-
LoopNode.reportLoopCount(inliningTarget, nbrIter);
515+
LoopNode.reportLoopCount(inliningTarget, loopCount);
514516
}
515517
}
516518

@@ -549,19 +551,21 @@ static boolean doObject(VirtualFrame frame, Object object,
549551
@Cached PyIterNextNode nextNode,
550552
@Cached PyObjectIsTrueNode isTrueNode) {
551553
Object iterator = getIter.execute(frame, inliningTarget, object);
552-
int nbrIter = 0;
554+
int loopCount = 0;
553555

554556
while (true) {
555557
try {
556558
Object next = nextNode.execute(frame, inliningTarget, iterator);
557-
nbrIter++;
559+
if (CompilerDirectives.hasNextTier() && loopCount < Integer.MAX_VALUE) {
560+
loopCount++;
561+
}
558562
if (isTrueNode.execute(frame, next)) {
559563
return true;
560564
}
561565
} catch (IteratorExhausted e) {
562566
break;
563567
} finally {
564-
LoopNode.reportLoopCount(inliningTarget, nbrIter);
568+
LoopNode.reportLoopCount(inliningTarget, loopCount);
565569
}
566570
}
567571

@@ -1563,11 +1567,13 @@ static Object minmaxSequenceWithKey(VirtualFrame frame, Node inliningTarget, Obj
15631567
currentKey = nextKey;
15641568
currentValue = nextValue;
15651569
}
1566-
loopCount++;
1570+
if (CompilerDirectives.hasNextTier() && loopCount < Integer.MAX_VALUE) {
1571+
loopCount++;
1572+
}
15671573
} catch (IteratorExhausted e) {
15681574
break;
15691575
} finally {
1570-
LoopNode.reportLoopCount(inliningTarget, loopCount < 0 ? Integer.MAX_VALUE : loopCount);
1576+
LoopNode.reportLoopCount(inliningTarget, loopCount);
15711577
}
15721578
}
15731579

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -893,19 +893,21 @@ static double doIt(VirtualFrame frame, Object iterable,
893893
assert tpIternext != null;
894894

895895
var acc = new XSum.SmallAccumulator();
896-
int nbrIter = 0;
896+
int loopCount = 0;
897897
while (true) {
898898
try {
899899
Object next = nextNodeCallNext.execute(frame, inliningTarget, tpIternext, iterator);
900-
nbrIter++;
900+
if (CompilerDirectives.hasNextTier() && loopCount < Integer.MAX_VALUE) {
901+
loopCount++;
902+
}
901903
acc.add(asDoubleNode.execute(frame, inliningTarget, next));
902904
} catch (IteratorExhausted e) {
903905
break;
904906
} catch (PException e) {
905907
e.expectStopIteration(inliningTarget, nextNodeStopIterationProfile);
906908
break;
907909
} finally {
908-
LoopNode.reportLoopCount(inliningTarget, nbrIter);
910+
LoopNode.reportLoopCount(inliningTarget, loopCount);
909911
}
910912
}
911913

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/functools/FunctoolsModuleBuiltins.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -45,7 +45,6 @@
4545
import static com.oracle.graal.python.nodes.BuiltinNames.T_FUNCTOOLS;
4646
import static com.oracle.graal.python.nodes.ErrorMessages.REDUCE_EMPTY_SEQ;
4747
import static com.oracle.graal.python.nodes.ErrorMessages.S_ARG_N_MUST_SUPPORT_ITERATION;
48-
import static com.oracle.truffle.api.nodes.LoopNode.reportLoopCount;
4948

5049
import java.util.List;
5150

@@ -75,6 +74,7 @@
7574
import com.oracle.truffle.api.dsl.NodeFactory;
7675
import com.oracle.truffle.api.dsl.Specialization;
7776
import com.oracle.truffle.api.frame.VirtualFrame;
77+
import com.oracle.truffle.api.nodes.LoopNode;
7878
import com.oracle.truffle.api.nodes.Node;
7979
import com.oracle.truffle.api.profiles.InlinedConditionProfile;
8080

@@ -136,7 +136,7 @@ Object doReduce(VirtualFrame frame, Object function, Object sequence, Object ini
136136

137137
Object[] args = new Object[2];
138138

139-
int count = 0;
139+
int loopCount = 0;
140140
while (true) {
141141
Object op2;
142142
try {
@@ -152,11 +152,11 @@ Object doReduce(VirtualFrame frame, Object function, Object sequence, Object ini
152152
args[1] = op2;
153153
result = callNode.execute(frame, function, args);
154154
}
155-
if (CompilerDirectives.hasNextTier()) {
156-
count++;
155+
if (CompilerDirectives.hasNextTier() && loopCount < Integer.MAX_VALUE) {
156+
loopCount++;
157157
}
158158
}
159-
reportLoopCount(this, count >= 0 ? count : Integer.MAX_VALUE);
159+
LoopNode.reportLoopCount(this, loopCount);
160160

161161
if (result == null) {
162162
throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.TypeError, REDUCE_EMPTY_SEQ);

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -1216,12 +1216,12 @@ static boolean doIt(Frame frame, Node inliningTarget, HashingStorage aStorage, H
12161216
if (lenANode.execute(inliningTarget, aStorage) != lenBNode.execute(inliningTarget, bStorage)) {
12171217
return false;
12181218
}
1219-
int index = 0;
1219+
int loopCount = 0;
12201220
try {
12211221
HashingStorageIterator aIter = getAIter.execute(inliningTarget, aStorage);
12221222
while (loopProfile.profile(inliningTarget, aIterNext.execute(inliningTarget, aStorage, aIter))) {
1223-
if (CompilerDirectives.hasNextTier()) {
1224-
index++;
1223+
if (CompilerDirectives.hasNextTier() && loopCount < Integer.MAX_VALUE) {
1224+
loopCount++;
12251225
}
12261226

12271227
Object aKey = aIterKey.execute(inliningTarget, aStorage, aIter);
@@ -1236,8 +1236,8 @@ static boolean doIt(Frame frame, Node inliningTarget, HashingStorage aStorage, H
12361236
return false;
12371237
}
12381238
} finally {
1239-
if (index != 0) {
1240-
LoopNode.reportLoopCount(inliningTarget, index);
1239+
if (loopCount != 0) {
1240+
LoopNode.reportLoopCount(inliningTarget, loopCount);
12411241
}
12421242
}
12431243
return true;
@@ -1287,19 +1287,19 @@ static Object doIt(Frame frame, Node callbackInliningTarget, HashingStorage stor
12871287
@Cached HashingStorageGetIterator getIter,
12881288
@Cached HashingStorageIteratorNext iterNext,
12891289
@Cached InlinedLoopConditionProfile loopProfile) {
1290-
int index = 0;
1290+
int loopCount = 0;
12911291
Object accumulator = accumulatorIn;
12921292
try {
12931293
HashingStorageIterator aIter = getIter.execute(inliningTarget, storage);
12941294
while (loopProfile.profile(inliningTarget, iterNext.execute(inliningTarget, storage, aIter))) {
1295-
if (CompilerDirectives.hasNextTier()) {
1296-
index++;
1295+
if (CompilerDirectives.hasNextTier() && loopCount < Integer.MAX_VALUE) {
1296+
loopCount++;
12971297
}
12981298
accumulator = callback.execute(frame, callbackInliningTarget, storage, aIter, accumulator);
12991299
}
13001300
} finally {
1301-
if (index != 0) {
1302-
LoopNode.reportLoopCount(getIter, index);
1301+
if (loopCount != 0) {
1302+
LoopNode.reportLoopCount(getIter, loopCount);
13031303
}
13041304
}
13051305
return accumulator;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictReprBuiltin.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -407,7 +407,7 @@ static void repr(VirtualFrame frame, POrderedDict dict, TruffleStringBuilder sb,
407407
@Cached FormatKeyValueDictRepr formatKeyValueDictRepr) {
408408
Object oditems = callMethod.execute(frame, inliningTarget, dict, T_ITEMS);
409409
ReprState s = new ReprState(dict, sb, false);
410-
int count = 0;
410+
int loopCount = 0;
411411
try {
412412
Object iter = getIter.execute(frame, inliningTarget, oditems);
413413
while (true) {
@@ -417,8 +417,8 @@ static void repr(VirtualFrame frame, POrderedDict dict, TruffleStringBuilder sb,
417417
} catch (IteratorExhausted e) {
418418
break;
419419
}
420-
if (CompilerDirectives.hasNextTier()) {
421-
count++;
420+
if (CompilerDirectives.hasNextTier() && loopCount < Integer.MAX_VALUE) {
421+
loopCount++;
422422
}
423423
assert PGuards.isPTuple(next);
424424
ObjectSequenceStorage item = (ObjectSequenceStorage) ((PTuple) next).getSequenceStorage();
@@ -427,8 +427,8 @@ static void repr(VirtualFrame frame, POrderedDict dict, TruffleStringBuilder sb,
427427
formatKeyValueDictRepr.execute(key, value, s);
428428
}
429429
} finally {
430-
if (count != 0) {
431-
LoopNode.reportLoopCount(inliningTarget, count);
430+
if (loopCount != 0) {
431+
LoopNode.reportLoopCount(inliningTarget, loopCount);
432432
}
433433
}
434434
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictViewBuiltins.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -46,9 +46,9 @@
4646
import java.util.List;
4747

4848
import com.oracle.graal.python.PythonLanguage;
49+
import com.oracle.graal.python.annotations.Builtin;
4950
import com.oracle.graal.python.annotations.Slot;
5051
import com.oracle.graal.python.annotations.Slot.SlotKind;
51-
import com.oracle.graal.python.annotations.Builtin;
5252
import com.oracle.graal.python.builtins.CoreFunctions;
5353
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
5454
import com.oracle.graal.python.builtins.PythonBuiltins;
@@ -75,7 +75,6 @@
7575
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotBinaryOp.BinaryOpBuiltinNode;
7676
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotLen.LenBuiltinNode;
7777
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotRichCompare;
78-
import com.oracle.graal.python.lib.RichCmpOp;
7978
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotSqContains.SqContainsBuiltinNode;
8079
import com.oracle.graal.python.lib.IteratorExhausted;
8180
import com.oracle.graal.python.lib.PyIterNextNode;
@@ -84,12 +83,14 @@
8483
import com.oracle.graal.python.lib.PyObjectRichCompareBool;
8584
import com.oracle.graal.python.lib.PyObjectSizeNode;
8685
import com.oracle.graal.python.lib.PySequenceContainsNode;
86+
import com.oracle.graal.python.lib.RichCmpOp;
8787
import com.oracle.graal.python.nodes.PNodeWithContext;
8888
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
8989
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
9090
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
9191
import com.oracle.graal.python.runtime.object.PFactory;
9292
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
93+
import com.oracle.truffle.api.CompilerDirectives;
9394
import com.oracle.truffle.api.dsl.Bind;
9495
import com.oracle.truffle.api.dsl.Cached;
9596
import com.oracle.truffle.api.dsl.Cached.Exclusive;
@@ -308,7 +309,7 @@ public boolean doIt(VirtualFrame frame, Object self, Object other,
308309
@Cached PyObjectIsTrueNode isTrueNode) {
309310
Object iterator = getIterNode.execute(frame, inliningTarget, self);
310311
boolean ok = checkAll;
311-
int i = 0;
312+
int loopCount = 0;
312313
try {
313314
while (loopConditionProfile.profile(inliningTarget, checkAll && ok || !checkAll && !ok)) {
314315
Object item;
@@ -318,10 +319,12 @@ public boolean doIt(VirtualFrame frame, Object self, Object other,
318319
break;
319320
}
320321
ok = isTrueNode.execute(frame, containsNode.execute(frame, inliningTarget, other, item));
321-
i++;
322+
if (CompilerDirectives.hasNextTier() && loopCount < Integer.MAX_VALUE) {
323+
loopCount++;
324+
}
322325
}
323326
} finally {
324-
LoopNode.reportLoopCount(this, i < 0 ? Integer.MAX_VALUE : i);
327+
LoopNode.reportLoopCount(this, loopCount);
325328
}
326329
return ok;
327330
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0

0 commit comments

Comments
 (0)