Python points-to: Support classes created dynamically as instances of meta-class.

This commit is contained in:
Mark Shannon
2019-04-15 12:52:37 +01:00
parent 06ab671629
commit 2e6c3c9ee3
4 changed files with 57 additions and 2 deletions

View File

@@ -277,3 +277,53 @@ class TypeInternal extends ClassObjectInternal, TType {
override predicate attributesUnknown() { any() }
}
class DynamicallyCreatedClass extends ClassObjectInternal, TDynamicClass {
override string toString() {
result = this.getOrigin().getNode().toString()
}
override ObjectInternal getClass() {
this = TDynamicClass(_, result, _)
}
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
none()
}
override predicate callResult(ObjectInternal obj, CfgOrigin origin) {
none()
}
override predicate lookup(string name, ObjectInternal value, CfgOrigin origin) {
exists(ClassObjectInternal decl |
decl = Types::getMro(this).findDeclaringClass(name) |
Types::declaredAttribute(decl, name, value, origin)
)
}
override Builtin getBuiltin() {
none()
}
override ControlFlowNode getOrigin() {
this = TDynamicClass(result, _, _)
}
override predicate attributesUnknown() { any() }
override predicate introduced(ControlFlowNode node, PointsToContext context) {
this = TDynamicClass(node, _, context)
}
override predicate calleeAndOffset(Function scope, int paramOffset) {
none()
}
override boolean isComparable() { result = true }
override ClassDecl getClassDeclaration() { none() }
}

View File

@@ -130,6 +130,11 @@ newtype TObject =
PointsToInternal::pointsTo(call.getFunction(), ctx, ObjectInternal::property(), _) and
PointsToInternal::pointsTo(call.getArg(0), ctx, getter, _)
}
or
TDynamicClass(ControlFlowNode instantiation, ClassObjectInternal metacls, PointsToContext context) {
PointsToInternal::pointsTo(instantiation.(CallNode).getFunction(), context, metacls, _) and
Types::getMro(metacls).contains(TType())
}
private predicate is_power_2(int n) {
n = 1 or

View File

@@ -1445,7 +1445,7 @@ cached module Types {
)
}
cached ClassObjectInternal getBase(ClassObjectInternal cls, int n) {
cached ObjectInternal getBase(ClassObjectInternal cls, int n) {
result.getBuiltin() = cls.getBuiltin().getBaseClass() and n = 0
or
exists(Class pycls |

View File

@@ -68,7 +68,7 @@ class ClassObject extends Object {
/** Gets a super class of this class (includes transitive super classes) or this class */
ClassObject getAnImproperSuperType() {
result = Types::getMro(theClass()).getAnItem().getSource()
result = this.getABaseType*()
}
/** Whether this class is a new style class.