Python points-to: Improve handling of 'type' object.

This commit is contained in:
Mark Shannon
2019-03-25 15:17:03 +00:00
parent 85a9016c8c
commit 48297e299e
5 changed files with 70 additions and 19 deletions

View File

@@ -80,10 +80,7 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti
PointsTo2::points_to(rval, callee, obj, origin)
)
}
override predicate callResult(ObjectInternal obj, CfgOrigin origin) {
none()
}
override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() }
override predicate calleeAndOffset(Function scope, int paramOffset) {
scope = this.getScope() and paramOffset = 0
@@ -115,9 +112,7 @@ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunc
override boolean isComparable() { result = true }
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
none()
}
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() }
override predicate callResult(ObjectInternal obj, CfgOrigin origin) {
exists(Builtin func, ClassObjectInternal cls |
@@ -191,9 +186,7 @@ class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethod
override boolean isComparable() { result = true }
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
none()
}
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() }
override predicate callResult(ObjectInternal obj, CfgOrigin origin) {
// TO DO .. Result should be be a unknown value of a known class if the return type is known or just an unknown.
@@ -247,7 +240,7 @@ class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod {
}
override predicate callResult(ObjectInternal obj, CfgOrigin origin) {
this.getFunction().callResult(obj, origin)
none()
}
override ControlFlowNode getOrigin() {
@@ -295,10 +288,10 @@ class ClassMethodObjectInternal extends ObjectInternal, TClassMethod {
override ControlFlowNode getOrigin() { this = TClassMethod(result, _) }
override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() }
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() }
override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() }
override int intValue() { none() }
override string strValue() { none() }
@@ -344,10 +337,10 @@ class StaticMethodObjectInternal extends ObjectInternal, TStaticMethod {
override ControlFlowNode getOrigin() { this = TStaticMethod(result, _) }
override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() }
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() }
override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() }
override int intValue() { none() }
override string strValue() { none() }

View File

@@ -140,7 +140,7 @@ class BuiltinClassObjectInternal extends ClassObjectInternal, TBuiltinClassObjec
}
override predicate callResult(ObjectInternal obj, CfgOrigin origin) {
// TO DO .. Result should (in most cases) be an instance
// Handled by Instance classes.
none()
}
@@ -197,4 +197,55 @@ class UnknownClassInternal extends ClassObjectInternal, TUnknownClass {
}
class TypeInternal extends ClassObjectInternal, TType {
override string toString() {
result = "type"
}
override ClassDecl getClassDeclaration() {
result = Builtin::special("type")
}
override ObjectInternal getClass() {
result = this
}
override predicate introduced(ControlFlowNode node, PointsToContext context) {
none()
}
override boolean isComparable() { result = false }
override Builtin getBuiltin() {
result = Builtin::special("type")
}
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
exists(CallNode call, PointsToContext caller, ObjectInternal instance |
callee.fromCall(call, caller) |
count(call.getAnArg()) = 1 and
PointsTo2::points_to(call.getArg(0), caller, instance, origin) and
obj = instance.getClass()
)
}
override predicate callResult(ObjectInternal obj, CfgOrigin origin) {
none()
}
override ControlFlowNode getOrigin() {
none()
}
override predicate calleeAndOffset(Function scope, int paramOffset) {
none()
}
override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) {
none()
}
override predicate attributesUnknown() { any() }
}

View File

@@ -12,12 +12,12 @@ abstract class ModuleObjectInternal extends ObjectInternal {
abstract Module getSourceModule();
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
override predicate callResult(ObjectInternal obj, CfgOrigin origin) {
// Modules aren't callable
none()
}
override predicate callResult(ObjectInternal obj, CfgOrigin origin) {
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
// Modules aren't callable
none()
}

View File

@@ -311,6 +311,8 @@ module ObjectInternal {
result = TBuiltinFunctionObject(Builtin::builtin(name))
or
result = TBuiltinOpaqueObject(Builtin::builtin(name))
or
name = "type" and result = TType()
}
ObjectInternal sysModules() {

View File

@@ -6,7 +6,9 @@ private import semmle.python.pointsto.PointsToContext
newtype TObject =
TBuiltinClassObject(Builtin bltn) {
bltn.isClass() and not bltn = Builtin::unknownType()
bltn.isClass() and
not bltn = Builtin::unknownType() and
not bltn = Builtin::special("type")
}
or
TBuiltinFunctionObject(Builtin bltn) { bltn.isFunction() }
@@ -109,6 +111,8 @@ newtype TObject =
TPythonTuple(TupleNode origin, PointsToContext context) {
context.appliesTo(origin)
}
or
TType()
private predicate is_power_2(int n) {
n = 1 or
@@ -266,6 +270,7 @@ library class ClassDecl extends @py_object {
not name = "object" and
not name = "list" and
not name = "set" and
not name = "dict" and
not name.matches("%Exception") and
not name.matches("%Error")
)