Skip to content

Commit 0597899

Browse files
committed
Fix: 'issubclass' checks if arguments have attribute '__bases__'.
1 parent 3f4d72a commit 0597899

File tree

1 file changed

+29
-2
lines changed
  • graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type

1 file changed

+29
-2
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,11 @@
9999
import com.oracle.graal.python.nodes.object.GetLazyClassNode;
100100
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
101101
import com.oracle.graal.python.nodes.truffle.PythonTypes;
102+
import com.oracle.graal.python.runtime.exception.PException;
102103
import com.oracle.graal.python.runtime.exception.PythonErrorType;
103104
import com.oracle.truffle.api.CompilerAsserts;
104105
import com.oracle.truffle.api.CompilerDirectives;
106+
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
105107
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
106108
import com.oracle.truffle.api.dsl.Cached;
107109
import com.oracle.truffle.api.dsl.Fallback;
@@ -529,6 +531,11 @@ public boolean isInstance(Object cls, Object instance) {
529531
static abstract class SubclassCheckNode extends PythonBinaryBuiltinNode {
530532
@Child private IsSubtypeNode isSubtypeNode = IsSubtypeNode.create();
531533
@Child private TypeNodes.IsSameTypeNode isSameTypeNode = TypeNodes.IsSameTypeNode.create();
534+
@Child private GetFixedAttributeNode getBasesAttrNode;
535+
@Child private GetLazyClassNode getClassNode;
536+
537+
@CompilationFinal private IsBuiltinClassProfile isAttrErrorProfile;
538+
@CompilationFinal private IsBuiltinClassProfile isTupleProfile;
532539

533540
@Specialization(guards = {"!isNativeClass(cls)", "!isNativeClass(derived)"})
534541
boolean doManagedManaged(LazyPythonClass cls, LazyPythonClass derived) {
@@ -547,15 +554,35 @@ boolean doObjectObject(Object cls, Object derived,
547554
if (isClsTypeNode.execute(cls) && isDerivedTypeNode.execute(derived)) {
548555
return isSubtypeNode.execute(derived, cls);
549556
}
550-
if (!isDerivedTypeNode.execute(derived)) {
557+
if (!checkClass(derived)) {
551558
throw raise(PythonBuiltinClassType.TypeError, "issubclass() arg 1 must be a class");
552559
}
553-
if (!isClsTypeNode.execute(cls)) {
560+
if (!checkClass(cls)) {
554561
throw raise(PythonBuiltinClassType.TypeError, "issubclass() arg 2 must be a class or tuple of classes");
555562
}
556563
return false;
557564
}
558565

566+
// checks if object has '__bases__' (see CPython 'abstract.c' function
567+
// 'recursive_issubclass')
568+
private boolean checkClass(Object obj) {
569+
if (getBasesAttrNode == null || isAttrErrorProfile == null || isTupleProfile == null || getClassNode == null) {
570+
CompilerDirectives.transferToInterpreterAndInvalidate();
571+
getBasesAttrNode = insert(GetFixedAttributeNode.create(SpecialAttributeNames.__BASES__));
572+
isAttrErrorProfile = IsBuiltinClassProfile.create();
573+
isTupleProfile = IsBuiltinClassProfile.create();
574+
getClassNode = insert(GetLazyClassNode.create());
575+
}
576+
Object basesObj;
577+
try {
578+
basesObj = getBasesAttrNode.executeObject(obj);
579+
} catch (PException e) {
580+
e.expectAttributeError(isAttrErrorProfile);
581+
return false;
582+
}
583+
return isTupleProfile.profileClass(getClassNode.execute(basesObj), PythonBuiltinClassType.PTuple);
584+
}
585+
559586
protected boolean isSameType(Object a, Object b) {
560587
return isSameTypeNode.execute(a, b);
561588
}

0 commit comments

Comments
 (0)