Skip to content

Commit f83fe34

Browse files
committed
Fix: 'issubclass' must check arguments.
1 parent 2f45246 commit f83fe34

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

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

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,10 +528,36 @@ public boolean isInstance(Object cls, Object instance) {
528528
@GenerateNodeFactory
529529
static abstract class SubclassCheckNode extends PythonBinaryBuiltinNode {
530530
@Child private IsSubtypeNode isSubtypeNode = IsSubtypeNode.create();
531+
@Child private TypeNodes.IsSameTypeNode isSameTypeNode = TypeNodes.IsSameTypeNode.create();
532+
533+
@Specialization(guards = {"!isNativeClass(cls)", "!isNativeClass(derived)"})
534+
boolean doManagedManaged(LazyPythonClass cls, LazyPythonClass derived) {
535+
return isSameType(cls, derived) || isSubtypeNode.execute(derived, cls);
536+
}
531537

532538
@Specialization
533-
boolean instanceCheck(LazyPythonClass cls, Object derived) {
534-
return cls == derived || isSubtypeNode.execute(derived, cls);
539+
boolean doObjectObject(Object cls, Object derived,
540+
@Cached("create()") TypeNodes.IsTypeNode isClsTypeNode,
541+
@Cached("create()") TypeNodes.IsTypeNode isDerivedTypeNode) {
542+
if (isSameType(cls, derived)) {
543+
return true;
544+
}
545+
546+
// no profiles required because IsTypeNode profiles already
547+
if (isClsTypeNode.execute(cls) && isDerivedTypeNode.execute(derived)) {
548+
return isSubtypeNode.execute(derived, cls);
549+
}
550+
if (!isDerivedTypeNode.execute(derived)) {
551+
throw raise(PythonBuiltinClassType.TypeError, "issubclass() arg 1 must be a class");
552+
}
553+
if (!isClsTypeNode.execute(cls)) {
554+
throw raise(PythonBuiltinClassType.TypeError, "issubclass() arg 2 must be a class or tuple of classes");
555+
}
556+
return false;
557+
}
558+
559+
protected boolean isSameType(Object a, Object b) {
560+
return isSameTypeNode.execute(a, b);
535561
}
536562
}
537563

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,11 @@ boolean doBuiltinType(@SuppressWarnings("unused") PythonBuiltinClassType obj) {
686686
boolean doManagedClass(PythonAbstractNativeObject obj,
687687
@Cached("create()") IsBuiltinClassProfile profile,
688688
@Cached("create()") GetLazyClassNode getClassNode) {
689+
// TODO(fa): this check may not be enough since a type object may indirectly inherit
690+
// from 'type'
691+
// CPython has two different checks if some object is a type:
692+
// 1. test if type flag 'Py_TPFLAGS_TYPE_SUBCLASS' is set
693+
// 2. test if attribute '__bases__' is a tuple
689694
return profile.profileClass(getClassNode.execute(obj), PythonBuiltinClassType.PythonClass);
690695
}
691696

0 commit comments

Comments
 (0)