Merge pull request #1840 from markshannon/python-better-hasattribute-handling

Python: Add 'hasAttribute' predicate to ObjectInternal and Value.
This commit is contained in:
Rebecca Valentine
2019-08-28 10:45:44 -07:00
committed by GitHub
13 changed files with 103 additions and 7 deletions

View File

@@ -97,6 +97,12 @@ abstract class ClassObjectInternal extends ObjectInternal {
/* Classes aren't usually iterable, but can e.g. Enums */
override ObjectInternal getIterNext() { result = ObjectInternal::unknown() }
override predicate hasAttribute(string name) {
this.getClassDeclaration().declaresAttribute(name)
or
Types::getBase(this, _).hasAttribute(name)
}
}
/** Class representing Python source classes */

View File

@@ -59,6 +59,18 @@ abstract class ModuleObjectInternal extends ObjectInternal {
/* Modules aren't iterable */
override ObjectInternal getIterNext() { none() }
/** Holds if this module "exports" name.
* That is, does it define `name` in `__all__` or is
* `__all__` not defined and `name` a global variable that does not start with "_"
* This is the set of names imported by `from ... import *`.
*/
predicate exports(string name) {
not this.(ModuleObjectInternal).attribute("__all__", _, _) and this.hasAttribute(name)
and not name.charAt(0) = "_"
or
py_exports(this.getSourceModule(), name)
}
}
/** A class representing built-in modules */
@@ -209,6 +221,13 @@ class PackageObjectInternal extends ModuleObjectInternal, TPackageObject {
)
}
/** Holds if this value has the attribute `name` */
override predicate hasAttribute(string name) {
this.getInitModule().hasAttribute(name)
or
exists(this.submodule(name))
}
}
/** A class representing Python modules */
@@ -261,6 +280,24 @@ class PythonModuleObjectInternal extends ModuleObjectInternal, TPythonModule {
result = this.getSourceModule().getEntryNode()
}
/** Holds if this value has the attribute `name` */
override predicate hasAttribute(string name) {
name = "__name__"
or
this.getSourceModule().(ImportTimeScope).definesName(name)
or
exists(ModuleObjectInternal mod, ImportStarNode imp |
PointsToInternal::pointsTo(imp, _, mod, _) and
imp.getScope() = this.getSourceModule() and
mod.exports(name)
)
or
exists(ObjectInternal defined |
this.attribute(name, defined, _) and
not defined instanceof UndefinedInternal
)
}
}
/** A class representing a module that is missing from the DB, but inferred to exists from imports. */

View File

@@ -94,6 +94,11 @@ class Value extends TObject {
result = this.(ObjectInternal).getName()
}
/** Holds if this value has the attribute `name` */
predicate hasAttribute(string name) {
this.(ObjectInternal).hasAttribute(name)
}
}
/** Class representing modules in the Python program
@@ -111,10 +116,7 @@ class ModuleValue extends Value {
* This is the set of names imported by `from ... import *`.
*/
predicate exports(string name) {
not this.(ModuleObjectInternal).attribute("__all__", _, _) and exists(this.attr(name))
and not name.charAt(0) = "_"
or
py_exports(this.getScope(), name)
PointsTo::moduleExports(this, name)
}
/** Gets the scope for this module, provided that it is a Python module. */

View File

@@ -182,6 +182,11 @@ class ObjectInternal extends TObject {
*/
abstract ObjectInternal getIterNext();
/** Holds if this value has the attribute `name` */
predicate hasAttribute(string name) {
this.(ObjectInternal).attribute(name, _, _)
}
}

View File

@@ -166,6 +166,10 @@ module PointsTo {
)
}
cached predicate moduleExports(ModuleObjectInternal mod, string name) {
InterModulePointsTo::moduleExportsBoolean(mod, name) = true
}
}
cached module PointsToInternal {

View File

@@ -151,7 +151,7 @@ class ClassObject extends Object {
/** Whether this class has a attribute named `name`, either declared or inherited.*/
predicate hasAttribute(string name) {
Types::getMro(theClass()).getAnItem().getClassDeclaration().declaresAttribute(name)
theClass().hasAttribute(name)
}
/** Whether it is impossible to know all the attributes of this class. Usually because it is

View File

@@ -51,9 +51,8 @@ abstract class ModuleObject extends Object {
result = this.getAttribute(name)
}
predicate hasAttribute(string name) {
exists(theModule().attr(name))
theModule().hasAttribute(name)
}
predicate attributeRefersTo(string name, Object obj, ControlFlowNode origin) {