mirror of
https://github.com/github/codeql.git
synced 2026-05-03 04:39:29 +02: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()
|
||||
)
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
| 2 | True |
|
||||
| 3 | False |
|
||||
| 6 | True |
|
||||
| 7 | True |
|
||||
| 8 | True |
|
||||
| 9 | False |
|
||||
| 19 | False |
|
||||
| 19 | True |
|
||||
| 20 | False |
|
||||
| 20 | True |
|
||||
| 21 | False |
|
||||
| 21 | True |
|
||||
| 22 | False |
|
||||
| 22 | True |
|
||||
| 25 | False |
|
||||
| 26 | False |
|
||||
| 27 | True |
|
||||
| 28 | True |
|
||||
| 29 | False |
|
||||
| 30 | True |
|
||||
| 33 | False |
|
||||
| 33 | True |
|
||||
| 34 | True |
|
||||
| 35 | False |
|
||||
| 36 | False |
|
||||
| 37 | True |
|
||||
| 38 | True |
|
||||
| 2 | bool True |
|
||||
| 3 | bool False |
|
||||
| 6 | bool True |
|
||||
| 7 | bool True |
|
||||
| 8 | bool True |
|
||||
| 9 | bool False |
|
||||
| 19 | bool False |
|
||||
| 19 | bool True |
|
||||
| 20 | bool False |
|
||||
| 20 | bool True |
|
||||
| 21 | bool False |
|
||||
| 21 | bool True |
|
||||
| 22 | bool False |
|
||||
| 22 | bool True |
|
||||
| 25 | bool False |
|
||||
| 26 | bool False |
|
||||
| 27 | bool True |
|
||||
| 28 | bool True |
|
||||
| 29 | bool False |
|
||||
| 30 | bool True |
|
||||
| 33 | bool False |
|
||||
| 33 | bool True |
|
||||
| 34 | bool True |
|
||||
| 35 | bool False |
|
||||
| 36 | bool False |
|
||||
| 37 | bool True |
|
||||
| 38 | bool True |
|
||||
|
||||
@@ -6,5 +6,5 @@ from int line, ControlFlowNode f, Value v
|
||||
where
|
||||
any(ExprStmt s).getValue() = f.getNode() and
|
||||
line = f.getLocation().getStartLine() and
|
||||
f = v.getAReferent()
|
||||
f.pointsTo(v)
|
||||
select line, v
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
WARNING: Type CustomPointsToOriginFact has been deprecated and may be removed in future (test.ql:8,27-51)
|
||||
| 9 | ControlFlowNode for has_type_int | Function has_type_int | builtin-class function |
|
||||
| 9 | ControlFlowNode for has_type_int() | has_type_int() | builtin-class int |
|
||||
| 9 | ControlFlowNode for x | has_type_int() | builtin-class int |
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
WARNING: Type CustomPointsToAttribute has been deprecated and may be removed in future (Extend.ql:26,35-58)
|
||||
WARNING: Type CustomPointsToObjectFact has been deprecated and may be removed in future (Extend.ql:41,32-56)
|
||||
WARNING: Type CustomPointsToOriginFact has been deprecated and may be removed in future (Extend.ql:8,28-52)
|
||||
| test.py:4:1:4:3 | ControlFlowNode for one | int 1 |
|
||||
| test.py:5:1:5:3 | ControlFlowNode for two | int 2 |
|
||||
| test.py:8:1:8:1 | ControlFlowNode for IntegerLiteral | int 1 |
|
||||
|
||||
Reference in New Issue
Block a user