Skip to content

Commit 4cf9e55

Browse files
committed
in lengthWithState check for negative values before calling asSize, otherwise OverflowError is thrown instead of ValueError
1 parent fae2db3 commit 4cf9e55

File tree

3 files changed

+38
-18
lines changed

3 files changed

+38
-18
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/PythonAbstractObject.java

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676

7777
import com.oracle.graal.python.PythonLanguage;
7878
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
79+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.OverflowError;
7980
import com.oracle.graal.python.builtins.modules.BuiltinFunctions;
8081
import com.oracle.graal.python.builtins.modules.MathGuards;
8182
import com.oracle.graal.python.builtins.modules.WarningsModuleBuiltins.WarnNode;
@@ -645,25 +646,32 @@ public boolean isSequence(@CachedLibrary("this") PythonObjectLibrary plib,
645646
public int lengthWithState(ThreadState state,
646647
@CachedLibrary("this") PythonObjectLibrary plib,
647648
@Shared("methodLib") @CachedLibrary(limit = "2") PythonObjectLibrary methodLib,
648-
@Shared("gotState") @Cached ConditionProfile gotState,
649649
@Exclusive @Cached ConditionProfile hasLen,
650650
@Exclusive @Cached ConditionProfile ltZero,
651651
@Shared("raise") @Cached PRaiseNode raiseNode,
652-
@Exclusive @CachedLibrary(limit = "1") PythonObjectLibrary lib) {
652+
@Exclusive @CachedLibrary(limit = "1") PythonObjectLibrary lib,
653+
@Exclusive @Cached CastToJavaLongLossyNode toLong,
654+
@Exclusive @Cached ConditionProfile ignoreOverflow,
655+
@Exclusive @Cached BranchProfile overflow) {
653656
Object lenFunc = plib.lookupAttributeOnType(this, __LEN__);
654657
if (hasLen.profile(lenFunc != PNone.NO_VALUE)) {
655658
Object lenResult = methodLib.callUnboundMethodWithState(lenFunc, state, this);
656-
int len;
657-
if (gotState.profile(state == null)) {
658-
len = lib.asSize(lenResult);
659-
} else {
660-
len = lib.asSizeWithState(lenResult, state);
661-
}
662-
if (ltZero.profile(len < 0)) {
663-
throw raiseNode.raise(PythonBuiltinClassType.ValueError, ErrorMessages.LEN_SHOULD_RETURN_MT_ZERO);
664-
} else {
665-
return len;
659+
// the following mimics typeobject.c#slot_sq_length()
660+
// - PyNumber_Index is called first
661+
// - checked if negative
662+
// - PyNumber_AsSsize_t is called, in scope of which PyNumber_Index is called again
663+
lenResult = lib.asIndexWithState(lenResult, state);
664+
long longResult;
665+
try {
666+
longResult = toLong.execute(lenResult); // this is a lossy cast
667+
if (ltZero.profile(longResult < 0)) {
668+
throw raiseNode.raise(PythonBuiltinClassType.ValueError, ErrorMessages.LEN_SHOULD_RETURN_MT_ZERO);
669+
}
670+
} catch (CannotCastException e) {
671+
CompilerDirectives.transferToInterpreterAndInvalidate();
672+
throw new IllegalStateException("cannot cast index to long - must not happen because then the #asIndex message impl should have raised");
666673
}
674+
return longToInt(longResult, overflow, ignoreOverflow, OverflowError, raiseNode, lenResult);
667675
} else {
668676
throw raiseNode.raiseHasNoLength(this);
669677
}
@@ -1105,6 +1113,10 @@ public int asSizeWithState(Object type, ThreadState state,
11051113
CompilerDirectives.transferToInterpreterAndInvalidate();
11061114
throw new IllegalStateException("cannot cast index to long - must not happen because then the #asIndex message impl should have raised");
11071115
}
1116+
return longToInt(longResult, overflow, ignoreOverflow, type, raise, result);
1117+
}
1118+
1119+
private static int longToInt(long longResult, BranchProfile overflow, ConditionProfile ignoreOverflow, Object type, PRaiseNode raise, Object result) throws PException {
11081120
try {
11091121
return PInt.intValueExact(longResult);
11101122
} catch (OverflowException e) {

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
import com.oracle.truffle.api.library.ExportMessage;
5454
import com.oracle.truffle.api.object.Shape;
5555
import com.oracle.truffle.api.profiles.ConditionProfile;
56+
import com.oracle.graal.python.nodes.util.CastToJavaLongLossyNode;
57+
import com.oracle.truffle.api.profiles.BranchProfile;
5658

5759
@ExportLibrary(PythonObjectLibrary.class)
5860
public final class PDict extends PHashingCollection {
@@ -143,13 +145,15 @@ static int doBuiltin(PDict self, ThreadState state,
143145
static int doSubclassed(PDict self, ThreadState state,
144146
@CachedLibrary("self") PythonObjectLibrary plib,
145147
@Shared("methodLib") @CachedLibrary(limit = "2") PythonObjectLibrary methodLib,
146-
@Shared("gotState") @Cached ConditionProfile gotState,
147148
@Exclusive @Cached ConditionProfile hasLen,
148149
@Exclusive @Cached ConditionProfile ltZero,
149150
@Shared("raise") @Cached PRaiseNode raiseNode,
150-
@Exclusive @CachedLibrary(limit = "1") PythonObjectLibrary lib) {
151+
@Exclusive @CachedLibrary(limit = "1") PythonObjectLibrary lib,
152+
@Exclusive @Cached CastToJavaLongLossyNode toLong,
153+
@Exclusive @Cached ConditionProfile ignoreOverflow,
154+
@Exclusive @Cached BranchProfile overflow) {
151155
// call the generic implementation in the superclass
152-
return self.lengthWithState(state, plib, methodLib, gotState, hasLen, ltZero, raiseNode, lib);
156+
return self.lengthWithState(state, plib, methodLib, hasLen, ltZero, raiseNode, lib, toLong, ignoreOverflow, overflow);
153157
}
154158
}
155159

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/str/PString.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
4242
import com.oracle.graal.python.nodes.util.CannotCastException;
4343
import com.oracle.graal.python.nodes.util.CastToJavaIntExactNode;
44+
import com.oracle.graal.python.nodes.util.CastToJavaLongLossyNode;
4445
import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
4546
import com.oracle.graal.python.runtime.sequence.PSequence;
4647
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
@@ -57,6 +58,7 @@
5758
import com.oracle.truffle.api.library.ExportMessage;
5859
import com.oracle.truffle.api.library.ExportMessage.Ignore;
5960
import com.oracle.truffle.api.object.Shape;
61+
import com.oracle.truffle.api.profiles.BranchProfile;
6062
import com.oracle.truffle.api.profiles.ConditionProfile;
6163

6264
@ExportLibrary(InteropLibrary.class)
@@ -160,13 +162,15 @@ static int nativeStringMat(@SuppressWarnings("unused") PString self, @SuppressWa
160162
static int subclassedString(PString self, ThreadState state,
161163
@CachedLibrary("self") PythonObjectLibrary plib,
162164
@Shared("methodLib") @CachedLibrary(limit = "2") PythonObjectLibrary methodLib,
163-
@Shared("gotState") @Cached ConditionProfile gotState,
164165
@Exclusive @Cached ConditionProfile hasLen,
165166
@Exclusive @Cached ConditionProfile ltZero,
166167
@Shared("raise") @Cached PRaiseNode raiseNode,
167-
@Exclusive @CachedLibrary(limit = "1") PythonObjectLibrary lib) {
168+
@Exclusive @CachedLibrary(limit = "1") PythonObjectLibrary lib,
169+
@Exclusive @Cached CastToJavaLongLossyNode toLong,
170+
@Exclusive @Cached ConditionProfile ignoreOverflow,
171+
@Exclusive @Cached BranchProfile overflow) {
168172
// call the generic implementation in the superclass
169-
return self.lengthWithState(state, plib, methodLib, gotState, hasLen, ltZero, raiseNode, lib);
173+
return self.lengthWithState(state, plib, methodLib, hasLen, ltZero, raiseNode, lib, toLong, ignoreOverflow, overflow);
170174
}
171175

172176
static NativeCharSequence getNativeCharSequence(PString self) {

0 commit comments

Comments
 (0)