Python: Introduce points-to cached stage

With points-to not being used for the call-graph any longer, it's time
to split them.
This commit is contained in:
Rasmus Wriedt Larsen
2022-10-17 10:52:44 +02:00
parent bd46b7deaa
commit fc0545561e
6 changed files with 49 additions and 25 deletions

View File

@@ -125,7 +125,7 @@ class ControlFlowNode extends @py_flow_node {
/** Gets a textual representation of this element. */ /** Gets a textual representation of this element. */
cached cached
string toString() { string toString() {
Stages::DataFlow::ref() and Stages::PointsTo::ref() and
exists(Scope s | s.getEntryNode() = this | result = "Entry node for " + s.toString()) exists(Scope s | s.getEntryNode() = this | result = "Entry node for " + s.toString())
or or
exists(Scope s | s.getANormalExit() = this | result = "Exit node for " + s.toString()) exists(Scope s | s.getANormalExit() = this | result = "Exit node for " + s.toString())

View File

@@ -125,6 +125,48 @@ module Stages {
} }
} }
/**
* The points-to stage.
*/
cached
module PointsTo {
/**
* Always holds.
* Ensures that a predicate is evaluated as part of the points-to stage.
*/
cached
predicate ref() { 1 = 1 }
private import semmle.python.pointsto.Base as PointsToBase
private import semmle.python.types.Object as TypeObject
private import semmle.python.objects.TObject as TObject
private import semmle.python.Flow as Flow
private import semmle.python.objects.ObjectInternal as ObjectInternal
// have to alias since this module is also called PointsTo
private import semmle.python.pointsto.PointsTo as RealPointsTo
/**
* DONT USE!
* Contains references to each predicate that use the above `ref` predicate.
*/
cached
predicate backref() {
1 = 1
or
PointsToBase::BaseFlow::scope_entry_value_transfer_from_earlier(_, _, _, _)
or
exists(TypeObject::Object a)
or
exists(TObject::TObject f)
or
exists(any(Flow::ControlFlowNode c).toString())
or
exists(any(ObjectInternal::ObjectInternal o).toString())
or
RealPointsTo::AttributePointsTo::variableAttributePointsTo(_, _, _, _, _)
}
}
/** /**
* The `dataflow` stage. * The `dataflow` stage.
*/ */
@@ -140,12 +182,6 @@ module Stages {
private import semmle.python.dataflow.new.internal.DataFlowPublic as DataFlowPublic private import semmle.python.dataflow.new.internal.DataFlowPublic as DataFlowPublic
private import semmle.python.dataflow.new.internal.LocalSources as LocalSources private import semmle.python.dataflow.new.internal.LocalSources as LocalSources
private import semmle.python.internal.Awaited as Awaited private import semmle.python.internal.Awaited as Awaited
private import semmle.python.pointsto.Base as PointsToBase
private import semmle.python.types.Object as TypeObject
private import semmle.python.objects.TObject as TObject
private import semmle.python.Flow as Flow
private import semmle.python.objects.ObjectInternal as ObjectInternal
private import semmle.python.pointsto.PointsTo as PointsTo
/** /**
* DONT USE! * DONT USE!
@@ -162,18 +198,6 @@ module Stages {
any(LocalSources::LocalSourceNode n).flowsTo(_) any(LocalSources::LocalSourceNode n).flowsTo(_)
or or
exists(Awaited::awaited(_)) exists(Awaited::awaited(_))
or
PointsToBase::BaseFlow::scope_entry_value_transfer_from_earlier(_, _, _, _)
or
exists(TypeObject::Object a)
or
exists(TObject::TObject f)
or
exists(any(Flow::ControlFlowNode c).toString())
or
exists(any(ObjectInternal::ObjectInternal o).toString())
or
PointsTo::AttributePointsTo::variableAttributePointsTo(_, _, _, _, _)
} }
} }
} }

View File

@@ -216,7 +216,7 @@ class BuiltinOpaqueObjectInternal extends ObjectInternal, TBuiltinOpaqueObject {
override Builtin getBuiltin() { this = TBuiltinOpaqueObject(result) } override Builtin getBuiltin() { this = TBuiltinOpaqueObject(result) }
override string toString() { override string toString() {
Stages::DataFlow::ref() and Stages::PointsTo::ref() and
result = this.getBuiltin().getClass().getName() + " object" result = this.getBuiltin().getClass().getName() + " object"
} }

View File

@@ -318,7 +318,7 @@ module BaseFlow {
predicate scope_entry_value_transfer_from_earlier( predicate scope_entry_value_transfer_from_earlier(
EssaVariable pred_var, Scope pred_scope, ScopeEntryDefinition succ_def, Scope succ_scope EssaVariable pred_var, Scope pred_scope, ScopeEntryDefinition succ_def, Scope succ_scope
) { ) {
Stages::DataFlow::ref() and Stages::PointsTo::ref() and
exists(SsaSourceVariable var | exists(SsaSourceVariable var |
essa_var_scope(var, pred_scope, pred_var) and essa_var_scope(var, pred_scope, pred_var) and
scope_entry_def_scope(var, succ_scope, succ_def) scope_entry_def_scope(var, succ_scope, succ_def)

View File

@@ -2569,7 +2569,7 @@ module AttributePointsTo {
predicate variableAttributePointsTo( predicate variableAttributePointsTo(
EssaVariable var, Context context, string name, ObjectInternal value, CfgOrigin origin EssaVariable var, Context context, string name, ObjectInternal value, CfgOrigin origin
) { ) {
Stages::DataFlow::ref() and Stages::PointsTo::ref() and
definitionAttributePointsTo(var.getDefinition(), context, name, value, origin) definitionAttributePointsTo(var.getDefinition(), context, name, value, origin)
or or
exists(EssaVariable prev | exists(EssaVariable prev |

View File

@@ -5,7 +5,7 @@ private import semmle.python.internal.CachedStages
cached cached
private predicate is_an_object(@py_object obj) { private predicate is_an_object(@py_object obj) {
Stages::DataFlow::ref() and Stages::PointsTo::ref() and
/* CFG nodes for numeric literals, all of which have a @py_cobject for the value of that literal */ /* CFG nodes for numeric literals, all of which have a @py_cobject for the value of that literal */
obj instanceof ControlFlowNode and obj instanceof ControlFlowNode and
not obj.(ControlFlowNode).getNode() instanceof IntegerLiteral and not obj.(ControlFlowNode).getNode() instanceof IntegerLiteral and
@@ -78,7 +78,7 @@ class Object extends @py_object {
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
) { ) {
Stages::DataFlow::ref() and Stages::PointsTo::ref() and
this.hasOrigin() and this.hasOrigin() and
this.getOrigin() this.getOrigin()
.getLocation() .getLocation()
@@ -98,7 +98,7 @@ class Object extends @py_object {
/** Gets a textual representation of this element. */ /** Gets a textual representation of this element. */
cached cached
string toString() { string toString() {
Stages::DataFlow::ref() and Stages::PointsTo::ref() and
not this = undefinedVariable() and not this = undefinedVariable() and
not this = unknownValue() and not this = unknownValue() and
exists(ClassObject type | type.asBuiltin() = this.asBuiltin().getClass() | exists(ClassObject type | type.asBuiltin() = this.asBuiltin().getClass() |