diff --git a/python/ql/src/semmle/python/objects/TObject.qll b/python/ql/src/semmle/python/objects/TObject.qll index 5a5093cd182..8832d3d340f 100644 --- a/python/ql/src/semmle/python/objects/TObject.qll +++ b/python/ql/src/semmle/python/objects/TObject.qll @@ -80,6 +80,8 @@ newtype TObject = TSpecificInstance(ControlFlowNode instantiation, ClassObjectInternal cls, PointsToContext context) { PointsTo2::points_to(instantiation.(CallNode).getFunction(), context, cls, _) and cls.isSpecial() = false + or + literal_instantiation(instantiation, cls, context) } or TSelfInstance(ParameterDefinition def, PointsToContext context, PythonClassObjectInternal cls) { @@ -129,6 +131,19 @@ predicate class_method(CallNode instantiation, CallableObjectInternal function, PointsTo2::points_to(instantiation.getArg(0), context, function, _) } +predicate literal_instantiation(ControlFlowNode n, ClassObjectInternal cls, PointsToContext context) { + context.appliesTo(n) and + ( + n instanceof ListNode and cls = ObjectInternal::builtin("list") + or + n instanceof DictNode and cls = ObjectInternal::builtin("dict") + or + n.getNode() instanceof FloatLiteral and cls = ObjectInternal::builtin("float") + or + n.getNode() instanceof ImaginaryLiteral and cls = ObjectInternal::builtin("complex") + ) +} + predicate super_instantiation(CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, PointsToContext context) { PointsTo2::points_to(instantiation.getFunction(), context, ObjectInternal::builtin("super"), _) and ( @@ -267,12 +282,20 @@ library class ClassDecl extends @py_object { predicate isSpecial() { exists(string name | this = Builtin::special(name) | - 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") + name = "type" or + name = "bool" or + name = "NoneType" or + name = "int" or + name = "long" or + name = "str" or + name = "bytes" or + name = "unicode" or + name = "tuple" or + name = "property" or + name = "classmethod" or + name = "staticmethod" or + name = "MethodType" or + name = "ModuleType" ) } diff --git a/python/ql/src/semmle/python/pointsto/PointsTo2.qll b/python/ql/src/semmle/python/pointsto/PointsTo2.qll index 9e9abf2fbe8..34cefd5b339 100644 --- a/python/ql/src/semmle/python/pointsto/PointsTo2.qll +++ b/python/ql/src/semmle/python/pointsto/PointsTo2.qll @@ -166,7 +166,7 @@ cached module PointsTo2 { /* Holds if the edge `pred` -> `succ` is reachable, given the context `context`. */ pragma [noopt] - private predicate controlledReachableEdge(BasicBlock pred, BasicBlock succ, PointsToContext context) { + cached predicate controlledReachableEdge(BasicBlock pred, BasicBlock succ, PointsToContext context) { exists(ConditionBlock guard, ObjectInternal value, boolean sense, ControlFlowNode test | test = guard.getLastNode() and points_to(test, context, value, _) and diff --git a/python/ql/src/semmle/python/types/Object.qll b/python/ql/src/semmle/python/types/Object.qll index 37315eefa62..8d57865c492 100644 --- a/python/ql/src/semmle/python/types/Object.qll +++ b/python/ql/src/semmle/python/types/Object.qll @@ -6,7 +6,8 @@ private import semmle.python.types.Builtins private cached predicate is_an_object(@py_object obj) { /* CFG nodes for numeric literals, all of which have a @py_cobject for the value of that literal */ obj instanceof ControlFlowNode and - not obj.(ControlFlowNode).getNode() instanceof ImmutableLiteral + not obj.(ControlFlowNode).getNode() instanceof IntegerLiteral and + not obj.(ControlFlowNode).getNode() instanceof StrConst or obj instanceof Builtin }