Python encapsulate extensionals dealing with 'builtin' objects.

This commit is contained in:
Mark Shannon
2019-03-13 11:22:50 +00:00
parent 6baf52614e
commit 9d31d09f08
10 changed files with 249 additions and 168 deletions

View File

@@ -130,7 +130,7 @@ class CheckClass extends ClassObject {
private Object object_getattribute() {
py_cmembers_versioned(theObjectType(), "__getattribute__", result, major_version().toString())
result.asBuiltin() = theObjectType().asBuiltin().getMember("__getattribute__")
}
private predicate auto_name(string name) {

View File

@@ -1,5 +1,5 @@
import python
private import semmle.python.types.Builtins
/** An alias in an import statement, the `mod as name` part of `import mod as name`. May be artificial;
`import x` is transformed into `import x as x` */
@@ -14,7 +14,7 @@ class Alias extends Alias_ {
private predicate valid_module_name(string name) {
exists(Module m | m.getName() = name)
or
exists(Object cmod | py_cobjecttypes(cmod, theModuleType()) and py_cobjectnames(cmod, name))
exists(Builtin cmod | cmod.getClass() = theModuleType().asBuiltin() and cmod.getName() = name)
}
/** An artificial expression representing an import */

View File

@@ -9,6 +9,7 @@
*/
import python
import semmle.python.dataflow.SsaDefinitions
private import semmle.python.types.Builtins
module BasePointsTo {
/** INTERNAL -- Use n.refersTo(value, _, origin) instead */
@@ -49,7 +50,7 @@ ClassObject simple_types(Object obj) {
or
obj.getOrigin() instanceof Module and result = theModuleType()
or
result = builtin_object_type(obj)
result.asBuiltin() = obj.asBuiltin().getClass()
}
private ClassObject comprehension(Expr e) {
@@ -124,34 +125,6 @@ predicate baseless_is_new_style(ClassObject cls) {
* analysis.
*/
/** Gets the base class of built-in class `cls` */
pragma [noinline]
ClassObject builtin_base_type(ClassObject cls) {
/* The extractor uses the special name ".super." to indicate the super class of a builtin class */
py_cmembers_versioned(cls, ".super.", result, _)
}
/** Gets the `name`d attribute of built-in class `cls` */
pragma [noinline]
Object builtin_class_attribute(ClassObject cls, string name) {
not name = ".super." and
py_cmembers_versioned(cls, name, result, _)
}
/** Holds if the `name`d attribute of built-in module `m` is `value` of `cls` */
pragma [noinline]
predicate builtin_module_attribute(ModuleObject m, string name, Object value, ClassObject cls) {
py_cmembers_versioned(m, name, value, _) and cls = builtin_object_type(value)
}
/** Gets the (built-in) class of the built-in object `obj` */
pragma [noinline]
ClassObject builtin_object_type(Object obj) {
py_cobjecttypes(obj, result) and not obj = unknownValue()
or
obj = unknownValue() and result = theUnknownType()
}
/** Holds if this class (not on a super-class) declares name */
pragma [noinline]
predicate class_declares_attribute(ClassObject cls, string name) {
@@ -160,11 +133,11 @@ predicate class_declares_attribute(ClassObject cls, string name) {
class_defines_name(defn, name)
)
or
exists(Object o |
o = builtin_class_attribute(cls, name) and
not exists(ClassObject sup |
sup = builtin_base_type(cls) and
o = builtin_class_attribute(sup, name)
exists(Builtin o |
o = cls.asBuiltin().getMember(name) and
not exists(Builtin sup |
sup = cls.asBuiltin().getBaseClass() and
o = sup.getMember(name)
)
)
}
@@ -556,11 +529,11 @@ Object undefinedVariable() {
/** Gets the pseudo-object representing an unknown value */
Object unknownValue() {
py_special_objects(result, "_1")
result.asBuiltin() = Builtin::unknown()
}
BuiltinCallable theTypeNewMethod() {
py_cmembers_versioned(theTypeType(), "__new__", result, major_version().toString())
result.asBuiltin() = theTypeType().asBuiltin().getMember("__new__")
}
/** Gets the `value, cls, origin` that `f` would refer to if it has not been assigned some other value */
@@ -576,7 +549,7 @@ predicate potential_builtin_points_to(NameNode f, Object value, ClassObject cls,
pragma [noinline]
predicate builtin_name_points_to(string name, Object value, ClassObject cls) {
value = Object::builtin(name) and py_cobjecttypes(value, cls)
value = Object::builtin(name) and cls.asBuiltin() = value.asBuiltin().getClass()
}
module BaseFlow {

View File

@@ -27,6 +27,7 @@ import python
private import PointsToContext
private import Base
private import semmle.python.types.Extensions
private import semmle.python.types.Builtins
private import Filters as BaseFilters
import semmle.dataflow.SSA
private import MRO
@@ -311,7 +312,7 @@ module PointsTo {
exists(SubscriptNode sub, Object sys_modules |
sub.getValue() = sys_modules_flow and
points_to(sys_modules_flow, _, sys_modules, _, _) and
builtin_module_attribute(theSysModuleObject(), "modules", sys_modules, _) and
sys_modules.asBuiltin() = Builtin::special("sys").getMember("modules") and
sub.getIndex() = n and
n.getNode().(StrConst).getText() = name and
sub.(DefinitionNode).getValue() = mod and
@@ -435,7 +436,7 @@ module PointsTo {
}
private boolean module_exports_boolean(ModuleObject mod, string name) {
py_cmembers_versioned(mod, name, _, major_version().toString()) and
exists(mod.asBuiltin().getMember(name)) and
name.charAt(0) != "_" and result = true
or
result = package_exports_boolean(mod, name)
@@ -494,7 +495,8 @@ module PointsTo {
or
package_attribute_points_to(mod, name, value, cls, origin)
or
builtin_module_attribute(mod, name, value, cls) and origin = CfgOrigin::unknown()
value.asBuiltin() = mod.asBuiltin().getMember(name) and
cls.asBuiltin() = value.asBuiltin().getClass() and origin = CfgOrigin::unknown()
}
}
@@ -2458,7 +2460,7 @@ module PointsTo {
is_new_style(cls) and not exists(cls_expr.getBase(0)) and result = theObjectType() and n = 0
)
or
result = builtin_base_type(cls) and n = 0
result.asBuiltin() = cls.asBuiltin().getBaseClass() and n = 0
or
cls = theUnknownType() and result = theObjectType() and n = 0
}
@@ -2482,7 +2484,7 @@ module PointsTo {
or
cls = theObjectType() and result = 0
or
exists(builtin_base_type(cls)) and cls != theObjectType() and result = 1
exists(cls.asBuiltin().getBaseClass()) and cls != theObjectType() and result = 1
or
cls = theUnknownType() and result = 1
}
@@ -2646,8 +2648,8 @@ module PointsTo {
ssa_variable_points_to(var, _, value, vcls, origin)
)
or
value = builtin_class_attribute(owner, name) and class_declares_attribute(owner, name) and
origin = CfgOrigin::unknown() and vcls = builtin_object_type(value)
value.asBuiltin() = owner.asBuiltin().getMember(name) and class_declares_attribute(owner, name) and
origin = CfgOrigin::unknown() and vcls.asBuiltin() = value.asBuiltin().getClass()
}
private predicate interesting_class_attribute(ClassList mro, string name) {
@@ -2754,7 +2756,11 @@ module PointsTo {
obj = unknownValue() and result = theUnknownType()
)
or
py_cobjecttypes(cls, result) and is_c_metaclass(result)
exists(Builtin meta |
result.asBuiltin() = meta and
meta = cls.asBuiltin().getClass() and
meta.inheritsFromType()
)
or
exists(ControlFlowNode meta |
Types::six_add_metaclass(_, cls, meta) and
@@ -2777,7 +2783,7 @@ module PointsTo {
}
private boolean has_declared_metaclass(ClassObject cls) {
py_cobjecttypes(cls, _) and result = true
exists(cls.asBuiltin().getClass()) and result = true
or
result = has_six_add_metaclass(cls).booleanOr(has_metaclass_var_metaclass(cls))
}

View File

@@ -0,0 +1,107 @@
import python
class Builtin extends @py_cobject {
Builtin() {
not (
/* @py_cobjects for modules which have a corresponding Python module */
exists(@py_cobject mod_type | py_special_objects(mod_type, "ModuleType") and py_cobjecttypes(this, mod_type)) and
exists(Module m | py_cobjectnames(this, m.getName()))
)
and (
/* Exclude unmatched builtin objects in the library trap files */
py_cobjectnames(this, _) or
py_cobjecttypes(this, _) or
py_special_objects(this, _)
)
}
string toString() {
not this = undefinedVariable().asBuiltin() and not this = Builtin::unknown() and
exists(Builtin type, string typename, string objname |
py_cobjecttypes(this, type) and py_cobjectnames(this, objname) and typename = type.getName() |
result = typename + " " + objname
)
}
Builtin getClass() {
py_cobjecttypes(this, result) and not this = Builtin::unknown()
or
this = Builtin::unknown() and result = Builtin::unknownType()
}
Builtin getMember(string name) {
not name = ".super." and
py_cmembers_versioned(this, name, result, major_version().toString())
}
Builtin getItem(int index) {
py_citems(this, index, result)
}
Builtin getBaseClass() {
py_cmembers_versioned(this, ".super.", result, major_version().toString())
}
predicate inheritsFromType() {
this = Builtin::special("type")
or
this.getBaseClass().inheritsFromType()
}
string getName() {
py_cobjectnames(this, result)
}
predicate isClass() {
py_cobjecttypes(_, this) or this = Builtin::unknownType()
}
predicate isFunction() {
this.getClass() = Builtin::special("BuiltinFunctionType") and
exists(Builtin mod |
mod.isModule() and
mod.getMember(_) = this
)
}
predicate isModule() {
this.getClass() = Builtin::special("ModuleType")
}
predicate isMethod() {
this.getClass() = Builtin::special("MethodDescriptorType")
or
this.getClass() = Builtin::special("BuiltinFunctionType") and
exists(Builtin cls | cls.isClass() and cls.getMember(_) = this)
or
this.getClass().getName() = "wrapper_descriptor"
}
}
module Builtin {
Builtin builtinModule() {
py_special_objects(result, "builtin_module_2") and major_version() = 2
or
py_special_objects(result, "builtin_module_3") and major_version() = 3
}
Builtin builtin(string name) {
result = builtinModule().getMember(name)
}
Builtin special(string name) {
py_special_objects(result, name)
}
Builtin unknown() {
py_special_objects(result, "_1")
}
Builtin unknownType() {
py_special_objects(result, "_semmle_unknown_type")
}
}

View File

@@ -2,12 +2,7 @@ import python
private import semmle.python.pointsto.PointsTo
private import semmle.python.pointsto.Base
private import semmle.python.pointsto.MRO as MRO
predicate is_c_metaclass(Object o) {
py_special_objects(o, "type")
or
exists(Object sup | py_cmembers_versioned(o, ".super.", sup, major_version().toString()) and is_c_metaclass(sup))
}
private import semmle.python.types.Builtins
/** A class whose instances represents Python classes.
@@ -27,22 +22,22 @@ class ClassObject extends Object {
ClassObject() {
this.getOrigin() instanceof ClassExpr or
py_cobjecttypes(_, this) or
exists(Object meta | py_cobjecttypes(this, meta) and is_c_metaclass(meta)) or
py_special_objects(this, "_semmle_unknown_type")
exists(Builtin o | o.getClass() = this.asBuiltin()) or
this.asBuiltin().getClass().inheritsFromType() or
this.asBuiltin() = Builtin::special("_semmle_unknown_type")
}
private predicate isStr() {
py_special_objects(this, "bytes") and major_version() = 2
this.asBuiltin() = Builtin::special("bytes") and major_version() = 2
or
py_special_objects(this, "unicode") and major_version() = 3
this.asBuiltin() = Builtin::special("unicode") and major_version() = 3
}
/** Gets the short (unqualified) name of this class */
string getName() {
this.isStr() and result = "str"
or
not this.isStr() and py_cobjectnames(this, result) and not this = theUnknownType()
not this.isStr() and result = this.asBuiltin().getName() and not this = theUnknownType()
or
result = this.getPyClass().getName()
}
@@ -51,7 +46,7 @@ class ClassObject extends Object {
* Should return the same name as the `__qualname__` attribute on classes in Python 3.
*/
string getQualifiedName() {
py_cobjectnames(this, _) and result = this.getName()
this.isBuiltin() and result = this.getName()
or
result = this.getPyClass().getQualifiedName()
}
@@ -70,8 +65,7 @@ class ClassObject extends Object {
predicate hasABase() {
exists(ClassExpr cls | this.getOrigin() = cls | exists(cls.getABase()))
or
/* The extractor uses the special name ".super." to indicate the super class of a builtin class */
py_cmembers_versioned(this, ".super.", _, major_version().toString())
exists(this.asBuiltin().getBaseClass())
}
/** Gets a super class of this class (includes transitive super classes) */
@@ -418,79 +412,79 @@ ClassObject theAbcMetaClassObject() {
/** The built-in class NoneType*/
ClassObject theNoneType() {
py_special_objects(result, "NoneType")
result.asBuiltin() = Builtin::special("NoneType")
}
/** The built-in class 'bool' */
ClassObject theBoolType() {
py_special_objects(result, "bool")
result.asBuiltin() = Builtin::special("bool")
}
/** The builtin class 'type' */
ClassObject theTypeType() {
py_special_objects(result, "type")
result.asBuiltin() = Builtin::special("type")
}
/** The builtin object ClassType (for old-style classes) */
ClassObject theClassType() {
py_special_objects(result, "ClassType")
result.asBuiltin() = Builtin::special("ClassType")
}
/** The builtin object InstanceType (for old-style classes) */
ClassObject theInstanceType() {
py_special_objects(result, "InstanceType")
result.asBuiltin() = Builtin::special("InstanceType")
}
/** The builtin class 'tuple' */
ClassObject theTupleType() {
py_special_objects(result, "tuple")
result.asBuiltin() = Builtin::special("tuple")
}
/** The builtin class 'int' */
ClassObject theIntType() {
py_special_objects(result, "int")
result.asBuiltin() = Builtin::special("int")
}
/** The builtin class 'long' (Python 2 only) */
ClassObject theLongType() {
py_special_objects(result, "long")
result.asBuiltin() = Builtin::special("long")
}
/** The builtin class 'float' */
ClassObject theFloatType() {
py_special_objects(result, "float")
result.asBuiltin() = Builtin::special("float")
}
/** The builtin class 'complex' */
ClassObject theComplexType() {
py_special_objects(result, "complex")
result.asBuiltin() = Builtin::special("complex")
}
/** The builtin class 'object' */
ClassObject theObjectType() {
py_special_objects(result, "object")
result.asBuiltin() = Builtin::special("object")
}
/** The builtin class 'list' */
ClassObject theListType() {
py_special_objects(result, "list")
result.asBuiltin() = Builtin::special("list")
}
/** The builtin class 'dict' */
ClassObject theDictType() {
py_special_objects(result, "dict")
result.asBuiltin() = Builtin::special("dict")
}
/** The builtin class 'Exception' */
ClassObject theExceptionType() {
py_special_objects(result, "Exception")
result.asBuiltin() = Builtin::special("Exception")
}
/** The builtin class for unicode. unicode in Python2, str in Python3 */
ClassObject theUnicodeType() {
py_special_objects(result, "unicode")
result.asBuiltin() = Builtin::special("unicode")
}
/** The builtin class '(x)range' */
@@ -502,83 +496,83 @@ ClassObject theRangeType() {
/** The builtin class for bytes. str in Python2, bytes in Python3 */
ClassObject theBytesType() {
py_special_objects(result, "bytes")
result.asBuiltin() = Builtin::special("bytes")
}
/** The builtin class 'set' */
ClassObject theSetType() {
py_special_objects(result, "set")
result.asBuiltin() = Builtin::special("set")
}
/** The builtin class 'property' */
ClassObject thePropertyType() {
py_special_objects(result, "property")
result.asBuiltin() = Builtin::special("property")
}
/** The builtin class 'BaseException' */
ClassObject theBaseExceptionType() {
py_special_objects(result, "BaseException")
result.asBuiltin() = Builtin::special("BaseException")
}
/** The class of builtin-functions */
ClassObject theBuiltinFunctionType() {
py_special_objects(result, "BuiltinFunctionType")
result.asBuiltin() = Builtin::special("BuiltinFunctionType")
}
/** The class of Python functions */
ClassObject thePyFunctionType() {
py_special_objects(result, "FunctionType")
result.asBuiltin() = Builtin::special("FunctionType")
}
/** The builtin class 'classmethod' */
ClassObject theClassMethodType() {
py_special_objects(result, "ClassMethod")
result.asBuiltin() = Builtin::special("ClassMethod")
}
/** The builtin class 'staticmethod' */
ClassObject theStaticMethodType() {
py_special_objects(result, "StaticMethod")
result.asBuiltin() = Builtin::special("StaticMethod")
}
/** The class of modules */
ClassObject theModuleType() {
py_special_objects(result, "ModuleType")
result.asBuiltin() = Builtin::special("ModuleType")
}
/** The class of generators */
ClassObject theGeneratorType() {
py_special_objects(result, "generator")
result.asBuiltin() = Builtin::special("generator")
}
/** The builtin class 'TypeError' */
ClassObject theTypeErrorType() {
py_special_objects(result, "TypeError")
result.asBuiltin() = Builtin::special("TypeError")
}
/** The builtin class 'AttributeError' */
ClassObject theAttributeErrorType() {
py_special_objects(result, "AttributeError")
result.asBuiltin() = Builtin::special("AttributeError")
}
/** The builtin class 'KeyError' */
ClassObject theKeyErrorType() {
py_special_objects(result, "KeyError")
result.asBuiltin() = Builtin::special("KeyError")
}
/** The builtin class of bound methods */
pragma [noinline]
ClassObject theBoundMethodType() {
py_special_objects(result, "MethodType")
result.asBuiltin() = Builtin::special("MethodType")
}
/** The builtin class of builtin properties */
ClassObject theGetSetDescriptorType() {
py_special_objects(result, "GetSetDescriptorType")
result.asBuiltin() = Builtin::special("GetSetDescriptorType")
}
/** The method descriptor class */
ClassObject theMethodDescriptorType() {
py_special_objects(result, "MethodDescriptorType")
result.asBuiltin() = Builtin::special("MethodDescriptorType")
}
/** The class of builtin properties */

View File

@@ -3,6 +3,7 @@ import semmle.python.types.Exceptions
private import semmle.python.pointsto.PointsTo
private import semmle.python.libraries.Zope
private import semmle.python.pointsto.Base
private import semmle.python.types.Builtins
/** A function object, whether written in Python or builtin */
abstract class FunctionObject extends Object {
@@ -254,23 +255,21 @@ abstract class BuiltinCallable extends FunctionObject {
class BuiltinMethodObject extends BuiltinCallable {
BuiltinMethodObject() {
py_cobjecttypes(this, theMethodDescriptorType())
this.asBuiltin().getClass() = theMethodDescriptorType().asBuiltin()
or
py_cobjecttypes(this, theBuiltinFunctionType()) and exists(ClassObject c | py_cmembers_versioned(c, _, this, major_version().toString()))
this.asBuiltin().getClass() = theBuiltinFunctionType().asBuiltin() and
exists(Builtin cls | cls.isClass() and cls.getMember(_) = this.asBuiltin())
or
exists(ClassObject wrapper_descriptor |
py_cobjecttypes(this, wrapper_descriptor) and
py_cobjectnames(wrapper_descriptor, "wrapper_descriptor")
)
this.asBuiltin().getClass().getName() = "wrapper_descriptor"
}
override string getQualifiedName() {
exists(ClassObject cls |
py_cmembers_versioned(cls, _, this, major_version().toString()) |
cls.asBuiltin().getMember(_) = this.asBuiltin() |
result = cls.getName() + "." + this.getName()
)
or
not exists(ClassObject cls | py_cmembers_versioned(cls, _, this, major_version().toString())) and
not exists(ClassObject cls | cls.asBuiltin().getMember(_) = this.asBuiltin()) and
result = this.getName()
}
@@ -279,7 +278,7 @@ class BuiltinMethodObject extends BuiltinCallable {
}
override string getName() {
py_cobjectnames(this, result)
result = this.asBuiltin().getName()
}
override string toString() {
@@ -305,7 +304,7 @@ class BuiltinMethodObject extends BuiltinCallable {
}
override ClassObject getAReturnType() {
ext_rettype(this, result)
ext_rettype(this.asBuiltin(), result.asBuiltin())
}
}
@@ -313,11 +312,12 @@ class BuiltinMethodObject extends BuiltinCallable {
class BuiltinFunctionObject extends BuiltinCallable {
BuiltinFunctionObject() {
py_cobjecttypes(this, theBuiltinFunctionType()) and exists(ModuleObject m | py_cmembers_versioned(m, _, this, major_version().toString()))
this.asBuiltin().getClass() = theBuiltinFunctionType().asBuiltin() and
exists(ModuleObject m | m.asBuiltin().getMember(_) = this.asBuiltin())
}
override string getName() {
py_cobjectnames(this, result)
result = this.asBuiltin().getName()
}
override string getQualifiedName() {
@@ -352,7 +352,7 @@ class BuiltinFunctionObject extends BuiltinCallable {
this = Object::builtin("intern") and result = theStrType()
or
/* Fix a few minor inaccuracies in the CPython analysis */
ext_rettype(this, result) and not (
ext_rettype(this.asBuiltin(), result.asBuiltin()) and not (
this = Object::builtin("__import__") and result = theNoneType()
or
this = Object::builtin("compile") and result = theNoneType()

View File

@@ -8,7 +8,7 @@ abstract class ModuleObject extends Object {
ModuleObject () {
exists(Module m | m.getEntryNode() = this)
or
py_cobjecttypes(this, theModuleType())
this.asBuiltin().getClass() = theModuleType().asBuiltin()
}
/** Gets the scope corresponding to this module, if this is a Python module */
@@ -103,19 +103,19 @@ abstract class ModuleObject extends Object {
class BuiltinModuleObject extends ModuleObject {
BuiltinModuleObject () {
py_cobjecttypes(this, theModuleType())
this.asBuiltin().getClass() = theModuleType().asBuiltin()
}
override string getName() {
py_cobjectnames(this, result)
result = this.asBuiltin().getName()
}
override Object getAttribute(string name) {
py_cmembers_versioned(this, name, result, major_version().toString())
result.asBuiltin() = this.asBuiltin().getMember(name)
}
override predicate hasAttribute(string name) {
py_cmembers_versioned(this, name, _, major_version().toString())
exists(this.asBuiltin().getMember(name))
}
override predicate attributeRefersTo(string name, Object value, ControlFlowNode origin) {
@@ -204,9 +204,9 @@ class PythonModuleObject extends ModuleObject {
* for each module name, with the name b'text' or u'text' (including the quotes).
*/
Object object_for_string(string text) {
py_cobjecttypes(result, theStrType()) and
result.asBuiltin().getClass() = theStrType().asBuiltin() and
exists(string repr |
py_cobjectnames(result, repr) and
repr = result.asBuiltin().getName() and
repr.charAt(1) = "'" |
/* Strip quotes off repr */
text = repr.substring(2, repr.length()-1)

View File

@@ -1,22 +1,13 @@
import python
private import semmle.python.pointsto.Base
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
and
not (
/* @py_cobjects for modules which have a corresponding Python module */
exists(@py_cobject mod_type | py_special_objects(mod_type, "ModuleType") and py_cobjecttypes(obj, mod_type)) and
exists(Module m | py_cobjectnames(obj, m.getName()))
)
and (
/* Exclude unmatched builtin objects in the library trap files */
obj instanceof ControlFlowNode or
py_cobjectnames(obj, _) or
py_cobjecttypes(obj, _) or
py_special_objects(obj, _)
)
or
obj instanceof Builtin
}
/** Instances of this class represent objects in the Python program. However, since
@@ -46,7 +37,7 @@ class Object extends @py_object {
ClassObject getAnInferredType() {
exists(ControlFlowNode somewhere | somewhere.refersTo(this, result, _))
or
py_cobjecttypes(this, result) and not this = unknownValue()
this.asBuiltin().getClass() = result.asBuiltin()and not this = unknownValue()
or
this = unknownValue() and result = theUnknownType()
}
@@ -54,7 +45,7 @@ class Object extends @py_object {
/** Whether this a builtin object. A builtin object is one defined by the implementation,
such as the integer 4 or by a native extension, such as a NumPy array class. */
predicate isBuiltin() {
py_cobjects(this)
exists(this.asBuiltin())
}
/** Retained for backwards compatibility. See Object.isBuiltin() */
@@ -79,14 +70,18 @@ class Object extends @py_object {
this.hasOrigin() and this.getOrigin().getLocation().hasLocationInfo(filepath, bl, bc, el, ec)
or
not this.hasOrigin() and filepath = ":Compiled Code" and bl = 0 and bc = 0 and el = 0 and ec = 0
}
}
/** INTERNAL -- Do not use */
Builtin asBuiltin() {
result = this
}
string toString() {
this.isC() and
not this = undefinedVariable() and not this = unknownValue() and
exists(ClassObject type, string typename, string objname |
py_cobjecttypes(this, type) and py_cobjectnames(this, objname) and typename = type.getName() |
result = typename + " " + objname
exists(ClassObject type |
type.asBuiltin() = this.asBuiltin().getClass() |
result = type.getName() + " " + this.asBuiltin().getName()
)
or
result = this.getOrigin().toString()
@@ -108,7 +103,7 @@ class Object extends @py_object {
or
this.getOrigin() instanceof Module and result = theModuleType()
or
py_cobjecttypes(this, result)
result.(Object).asBuiltin() = this.asBuiltin().getClass()
}
private
@@ -240,9 +235,9 @@ private Object findByName3(string longName) {
class NumericObject extends Object {
NumericObject() {
py_cobjecttypes(this, theIntType()) or
py_cobjecttypes(this, theLongType()) or
py_cobjecttypes(this, theFloatType())
this.asBuiltin().getClass() = theIntType().asBuiltin() or
this.asBuiltin().getClass() = theLongType().asBuiltin() or
this.asBuiltin().getClass() = theFloatType().asBuiltin()
}
/** Gets the Boolean value that this object
@@ -261,23 +256,26 @@ class NumericObject extends Object {
/** Gets the value of this object if it is a constant integer and it fits in a QL int */
int intValue() {
(py_cobjecttypes(this, theIntType()) or py_cobjecttypes(this, theLongType()))
(
this.asBuiltin().getClass() = theIntType().asBuiltin() or
this.asBuiltin().getClass() = theLongType().asBuiltin()
)
and
exists(string s | py_cobjectnames(this, s) and result = s.toInt())
result = this.asBuiltin().getName().toInt()
}
/** Gets the value of this object if it is a constant float */
float floatValue() {
(py_cobjecttypes(this, theFloatType()))
this.asBuiltin().getClass() = theFloatType().asBuiltin()
and
exists(string s | py_cobjectnames(this, s) and result = s.toFloat())
result = this.asBuiltin().getName().toFloat()
}
/** Gets the string representation of this object, equivalent to calling repr() in Python */
string repr() {
exists(string s |
py_cobjectnames(this, s) |
if py_cobjecttypes(this, theLongType()) then
exists(string s |
s = this.asBuiltin().getName() |
if this.asBuiltin().getClass() = theLongType().asBuiltin() then
result = s + "L"
else
result = s
@@ -293,8 +291,8 @@ class NumericObject extends Object {
class StringObject extends Object {
StringObject() {
py_cobjecttypes(this, theUnicodeType()) or
py_cobjecttypes(this, theBytesType())
this.asBuiltin().getClass() = theUnicodeType().asBuiltin() or
this.asBuiltin().getClass() = theBytesType().asBuiltin()
}
/** Whether this string is composed entirely of ascii encodable characters */
@@ -311,7 +309,8 @@ class StringObject extends Object {
/** Gets the text for this string */
cached string getText() {
exists(string quoted_string |
py_cobjectnames(this, quoted_string) and
quoted_string = this.asBuiltin().getName()
and
result = quoted_string.regexpCapture("[bu]'([\\s\\S]*)'", 1)
)
}
@@ -333,7 +332,7 @@ abstract class SequenceObject extends Object {
/** Gets the nth item of this builtin sequence */
Object getBuiltinElement(int n) {
py_citems(this, n, result)
result.asBuiltin() = this.asBuiltin().getItem(n)
}
/** Gets the nth source element of this sequence */
@@ -352,7 +351,7 @@ abstract class SequenceObject extends Object {
class TupleObject extends SequenceObject {
TupleObject() {
py_cobjecttypes(this, theTupleType())
this.asBuiltin().getClass() = theTupleType().asBuiltin()
or
this instanceof TupleNode
or
@@ -364,7 +363,11 @@ class TupleObject extends SequenceObject {
module TupleObject {
TupleObject empty() {
py_cobjecttypes(result, theTupleType()) and not py_citems(result, _, _)
exists(Builtin empty |
empty = result.asBuiltin() and
empty.getClass() = theTupleType().asBuiltin() and
not exists(empty.getItem(_))
)
}
}
@@ -385,7 +388,7 @@ class NonEmptyTupleObject extends TupleObject {
class ListObject extends SequenceObject {
ListObject() {
py_cobjecttypes(this, theListType())
this.asBuiltin().getClass() = theListType().asBuiltin()
or
this instanceof ListNode
}
@@ -394,14 +397,12 @@ class ListObject extends SequenceObject {
/** The `builtin` module */
BuiltinModuleObject theBuiltinModuleObject() {
py_special_objects(result, "builtin_module_2") and major_version() = 2
or
py_special_objects(result, "builtin_module_3") and major_version() = 3
result.asBuiltin() = Builtin::builtinModule()
}
/** The `sys` module */
BuiltinModuleObject theSysModuleObject() {
py_special_objects(result, "sys")
result.asBuiltin() = Builtin::special("sys")
}
/** DEPRECATED -- Use `Object::builtin(name)` instead. */
@@ -412,17 +413,17 @@ Object builtin_object(string name) {
/** The built-in object None */
Object theNoneObject() {
py_special_objects(result, "None")
result.asBuiltin() = Builtin::special("None")
}
/** The built-in object True */
Object theTrueObject() {
py_special_objects(result, "True")
result.asBuiltin() = Builtin::special("True")
}
/** The built-in object False */
Object theFalseObject() {
py_special_objects(result, "False")
result.asBuiltin() = Builtin::special("False")
}
/** The NameError class */
@@ -466,7 +467,7 @@ Object theEmptyTupleObject() {
module Object {
Object builtin(string name) {
py_cmembers_versioned(theBuiltinModuleObject(), name, result, major_version().toString())
result.asBuiltin() = Builtin::builtin(name)
}
/** The named quitter object (quit or exit) in the builtin namespace */
@@ -510,6 +511,6 @@ private ClassObject string_literal(Expr e) {
}
Object theUnknownType() {
py_special_objects(result, "_semmle_unknown_type")
result.asBuiltin() = Builtin::unknownType()
}

View File

@@ -12,7 +12,7 @@ abstract class PropertyObject extends Object {
PropertyObject() {
property_getter(this, _)
or
py_cobjecttypes(this, theBuiltinPropertyType())
this.asBuiltin().getClass() = theBuiltinPropertyType().asBuiltin()
}
/** Gets the name of this property */
@@ -78,16 +78,16 @@ class PythonPropertyObject extends PropertyObject {
class BuiltinPropertyObject extends PropertyObject {
BuiltinPropertyObject() {
py_cobjecttypes(this, theBuiltinPropertyType())
this.asBuiltin().getClass() = theBuiltinPropertyType().asBuiltin()
}
override string getName() {
py_cobjectnames(this, result)
result = this.asBuiltin().getName()
}
/** Gets the getter method wrapper of this property */
override Object getGetter() {
py_cmembers_versioned(this, "__get__", result, major_version().toString())
result.asBuiltin() = this.asBuiltin().getMember("__get__")
}
override ClassObject getInferredPropertyType() {
@@ -96,12 +96,12 @@ class BuiltinPropertyObject extends PropertyObject {
/** Gets the setter method wrapper of this property */
override Object getSetter() {
py_cmembers_versioned(this, "__set__", result, major_version().toString())
result.asBuiltin() = this.asBuiltin().getMember("__set__")
}
/** Gets the deleter method wrapper of this property */
override Object getDeleter() {
py_cmembers_versioned(this, "__delete__", result, major_version().toString())
result.asBuiltin() = this.asBuiltin().getMember("__delete__")
}
}