Python points-to: Fix support for backwards compatible extensions.

This commit is contained in:
Mark Shannon
2019-04-17 11:37:33 +01:00
parent dffbf698d2
commit 989d587617
12 changed files with 126 additions and 63 deletions

View File

@@ -217,8 +217,8 @@ class ControlFlowNode extends @py_flow_node {
this.pointsTo(_, value, _)
}
/** Gets the value that this ControlFlowNode points-to. */
Value pointsTo() {
/** Gets a value that this ControlFlowNode may points-to. */
Value inferredValue() {
this.pointsTo(_, result, _)
}

View File

@@ -202,7 +202,7 @@ class UnknownClassInternal extends ClassObjectInternal, TUnknownClass {
override boolean isComparable() { result = false }
override Builtin getBuiltin() {
none()
result = Builtin::unknownType()
}
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {

View File

@@ -180,10 +180,6 @@ class PackageObjectInternal extends ModuleObjectInternal, TPackageObject {
pragma [noinline] override predicate attributesUnknown() { none() }
override ControlFlowNode getOrigin() {
result = this.getSourceModule().getEntryNode()
}
override @py_object getSource() {
exists(Module package |
package.isPackage() and
package.getPath() = this.getFolder() and

View File

@@ -9,9 +9,9 @@ class ObjectSource = Object;
class Value extends TObject {
Value() {
not this = ObjectInternal::unknown() and
not this = ObjectInternal::unknownClass() and
not this = ObjectInternal::undefined()
this != ObjectInternal::unknown() and
this != ObjectInternal::unknownClass() and
this != ObjectInternal::undefined()
}
string toString() {

View File

@@ -214,7 +214,7 @@ class UnknownInternal extends ObjectInternal, TUnknown {
override boolean isComparable() { result = false }
override Builtin getBuiltin() {
none()
result = Builtin::unknown()
}
override predicate callResult(ObjectInternal obj, CfgOrigin origin) {

View File

@@ -6,6 +6,7 @@ private import semmle.python.pointsto.Filters
private import semmle.python.pointsto.PointsToContext
private import semmle.python.pointsto.MRO
private import semmle.python.types.Builtins
private import semmle.python.types.Extensions
/* Use this version for speed */
//library class CfgOrigin extends @py_object {
@@ -125,7 +126,7 @@ module PointsTo {
/* Backwards compatibility */
deprecated predicate
points_to(ControlFlowNode f, PointsToContext context, Object obj, ClassObject cls, ControlFlowNode origin) {
exists(Value value |
exists(ObjectInternal value |
PointsToInternal::pointsTo(f, context, value, origin) and
cls = value.getClass().getSource() |
obj = value.getSource() or
@@ -200,9 +201,8 @@ cached module PointsToInternal {
InterProceduralPointsTo::call_points_to(f, context, value, origin)
or
AttributePointsTo::pointsTo(f, context, value, origin)
// To do... More stuff here :)
// or
// f.(CustomPointsToFact).pointsTo(context, value, origin)
or
f.(PointsToExtension).pointsTo(context, value, origin)
}
/** Holds if the attribute `name` is required for `obj` */

View File

@@ -12,12 +12,26 @@
import python
private import semmle.python.pointsto.PointsTo
private import semmle.python.pointsto.PointsToContext
private import semmle.python.objects.TObject
private import semmle.python.objects.ObjectInternal
abstract class PointsToExtension extends @py_flow_node {
string toString() { none() }
abstract predicate pointsTo(Context context, ObjectInternal value, ControlFlowNode origin);
}
/* Legacy API */
/* Custom Facts. This extension mechanism allows you to add custom
* sources of data to the points-to analysis.
*/
abstract class CustomPointsToFact extends @py_flow_node {
/** DEPRECATED -- Use PointsToExtension instead */
deprecated abstract class CustomPointsToFact extends @py_flow_node {
string toString() { none() }
@@ -28,7 +42,7 @@ abstract class CustomPointsToFact extends @py_flow_node {
/* For backwards compatibility */
class FinalCustomPointsToFact = CustomPointsToFact;
abstract class CustomPointsToOriginFact extends CustomPointsToFact {
deprecated abstract class CustomPointsToOriginFact extends CustomPointsToFact {
abstract predicate pointsTo(Object value, ClassObject cls);
@@ -39,7 +53,7 @@ abstract class CustomPointsToOriginFact extends CustomPointsToFact {
}
/* Custom points-to fact with inferred class */
abstract class CustomPointsToObjectFact extends CustomPointsToFact {
deprecated abstract class CustomPointsToObjectFact extends CustomPointsToFact {
abstract predicate pointsTo(Object value);
@@ -50,8 +64,8 @@ abstract class CustomPointsToObjectFact extends CustomPointsToFact {
}
/** INTERNAL -- Do not use */
abstract class CustomPointsToAttribute extends Object {
/** DEPRECATED -- Unsupported; do not use */
deprecated abstract class CustomPointsToAttribute extends Object {
abstract predicate attributePointsTo(string name, Object value, ClassObject cls, ControlFlowNode origin);
@@ -60,40 +74,89 @@ abstract class CustomPointsToAttribute extends Object {
/* An example */
/** Any variable iterating over range or xrange must be an integer */
class RangeIterationVariableFact extends CustomPointsToFact {
class RangeIterationVariableFact extends PointsToExtension {
RangeIterationVariableFact() {
exists(For f, ControlFlowNode iterable |
iterable.getBasicBlock().dominates(this.(ControlFlowNode).getBasicBlock()) and
f.getIter().getAFlowNode() = iterable and
f.getTarget().getAFlowNode() = this and
PointsTo::points_to(iterable, _, theRangeType(), _, _)
exists(ObjectInternal range |
PointsTo::pointsTo(iterable, _, range, _) and
range.getClass() = ObjectInternal::builtin("range")
)
)
}
override predicate pointsTo(Context context, Object value, ClassObject cls, ControlFlowNode origin) {
value = this and
override predicate pointsTo(Context context, ObjectInternal value, ControlFlowNode origin) {
value = TUnknownInstance(ObjectInternal::builtin("int")) and
origin = this and
cls = theIntType() and
context.appliesTo(this)
}
}
/* Python 3.6+ regex module constants */
class ReModulePointToExtension extends CustomPointsToAttribute {
class ReModulePointToExtension extends PointsToExtension {
string name;
ReModulePointToExtension() {
this.(ModuleObject).getName() = "re"
}
override predicate attributePointsTo(string name, Object value, ClassObject cls, ControlFlowNode origin) {
exists(ModuleObject sre_constants |
sre_constants.getName() = "sre_constants" and
sre_constants.attributeRefersTo("SRE_FLAG_" + name, value, cls, origin)
exists(ModuleObjectInternal re | re.getName() = "re" and
PointsTo::pointsTo(this.(AttrNode).getObject(name), _, re, _)
)
}
override predicate pointsTo(Context context, ObjectInternal value, ControlFlowNode origin) {
value = Module::named("sre_constants").attr("SRE_FLAG_" + name) and
exists(ModuleObjectInternal sre_constants |
sre_constants.getName() = "sre_constants" and
sre_constants.attribute(name, value, CfgOrigin::fromCfgNode(origin))
)
and context.appliesTo(this)
}
}
private class BackwardCompatiblePointToExtension extends PointsToExtension {
BackwardCompatiblePointToExtension() {
this instanceof CustomPointsToFact
}
override predicate pointsTo(Context context, ObjectInternal value, ControlFlowNode origin) {
exists(Object obj, ClassObject cls |
this.(CustomPointsToFact).pointsTo(context, obj, cls, origin)
|
value.getBuiltin() = obj
or
obj instanceof ControlFlowNode and
exists(ClassObjectInternal c |
c.getSource() = cls and
value = TUnknownInstance(c)
)
)
or
exists(ObjectInternal owner, string name |
PointsTo::pointsTo(this.(AttrNode).getObject(name), context, owner, _) and
additionalAttribute(owner, name, value, origin)
)
}
}
private predicate additionalAttribute(ObjectInternal owner, string name, ObjectInternal value, ControlFlowNode origin) {
exists(Object obj, ClassObject cls |
owner.getSource().(CustomPointsToAttribute).attributePointsTo(name, obj, cls, origin)
|
value.getBuiltin() = obj
or
obj instanceof ControlFlowNode and
exists(ClassObjectInternal c |
c.getSource() = cls and
value = TUnknownInstance(c)
)
)
}

View File

@@ -508,7 +508,7 @@ class SuperBoundMethod extends Object {
string name;
SuperBoundMethod() {
this.(AttrNode).getObject(name).pointsTo().getClass() = Value::named("super")
this.(AttrNode).getObject(name).inferredValue().getClass() = Value::named("super")
}
override string toString() {
@@ -518,7 +518,7 @@ class SuperBoundMethod extends Object {
Object getFunction(string fname) {
fname = name and
exists(SuperInstance sup, BoundMethodObjectInternal m |
sup = this.(AttrNode).getObject(name).pointsTo() and
sup = this.(AttrNode).getObject(name).inferredValue() and
sup.attribute(name, m, _) and
result = m.getFunction().getSource()
)