mirror of
https://github.com/github/codeql.git
synced 2025-12-18 01:33:15 +01:00
Python points-to: Fix support for backwards compatible extensions.
This commit is contained in:
@@ -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, _)
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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` */
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user