Python: group related predicates

also restore accidentally removed comment
This commit is contained in:
Rasmus Lerchedahl Petersen
2020-06-16 07:30:44 +02:00
parent f8eb5839cd
commit ad04ec554a
2 changed files with 103 additions and 68 deletions

View File

@@ -1,10 +1,13 @@
private import python
private import DataFlowPublic
//--------
// Data flow graph
//--------
//--------
// Nodes
//--------
class DataFlowCall extends Call {
/** Gets the enclosing callable of this call. */
@@ -61,35 +64,11 @@ abstract class OutNode extends Node {
abstract DataFlowCall getCall(ReturnKind kind);
}
/** A node that performs a type cast. */
class CastNode extends Node {
}
class DataFlowCallable = FunctionValue;
class DataFlowExpr = Expr;
newtype TDataFlowType =
TStringFlow()
class DataFlowType extends TDataFlowType {
/**
* No representation yet
*/
string toString() { none() }
}
/** Gets a viable run-time target for the call `call`. */
DataFlowCallable viableCallable(DataFlowCall call) { none() }
/**
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
* a node of type `t1` to a node of type `t2`.
*/
pragma[inline]
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) {
none()
}
//--------
// Local flow
//--------
/**
* This is the local flow predicate that is used as a building block in global
@@ -109,6 +88,57 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
)
}
//--------
// Global flow
//--------
class DataFlowCallable = FunctionValue;
/** Gets a viable run-time target for the call `call`. */
DataFlowCallable viableCallable(DataFlowCall call) { none() }
/**
* Gets a node that can read the value returned from `call` with return kind
* `kind`.
*/
OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { call = result.getCall(kind) }
//--------
// Type pruning
//--------
newtype TDataFlowType =
TStringFlow()
class DataFlowType extends TDataFlowType {
/**
* No representation yet
*/
string toString() { none() }
}
/** A node that performs a type cast. */
class CastNode extends Node {
}
/**
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
* a node of type `t1` to a node of type `t2`.
*/
pragma[inline]
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) {
none()
}
DataFlowType getErasedRepr(DataFlowType t) { result = t }
/** Gets a string representation of a type returned by `getErasedRepr`. */
string ppReprType(DataFlowType t) { result = t.toString() }
//--------
// Extra flow
//--------
/**
* Holds if `pred` can flow to `succ`, by jumping from one callable to
* another. Additional steps specified by the configuration are *not*
@@ -118,6 +148,10 @@ predicate jumpStep(ExprNode pred, ExprNode succ) {
none()
}
//--------
// Field flow
//--------
/**
* Holds if data can flow from `node1` to `node2` via an assignment to
* content `c`.
@@ -133,11 +167,20 @@ predicate readStep(Node node1, Content c, Node node2) {
none()
}
//--------
// Fancy context-sensitive guards
//--------
/**
* Gets a node that can read the value returned from `call` with return kind
* `kind`.
* Holds if the node `n` is unreachable when the call context is `call`.
*/
OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { call = result.getCall(kind) }
predicate isUnreachableInCall(Node n, DataFlowCall call) {
none()
}
//--------
// Fancy dispatch
//--------
/**
* Holds if the call context `ctx` reduces the set of viable run-time
@@ -147,13 +190,6 @@ predicate reducedViableImplInCallContext(DataFlowCall call, DataFlowCallable c,
none()
}
/**
* Holds if the node `n` is unreachable when the call context is `call`.
*/
predicate isUnreachableInCall(Node n, DataFlowCall call) {
none()
}
/**
* Holds if flow returning from callable `c` to call `call` might return
* further and if this path restricts the set of call sites that can be
@@ -185,6 +221,10 @@ DataFlowCallable prunedViableImplInCallContext(DataFlowCall call, DataFlowCall c
// reducedViableImplInCallContext(call, _, ctx)
}
//--------
// Misc
//--------
/**
* Holds if `n` does not require a `PostUpdateNode` as it either cannot be
* modified or its modification cannot be observed, for example if it is a
@@ -194,11 +234,6 @@ DataFlowCallable prunedViableImplInCallContext(DataFlowCall call, DataFlowCall c
*/
predicate isImmutableOrUnobservable(Node n) { none() }
DataFlowType getErasedRepr(DataFlowType t) { result = t }
/** Gets a string representation of a type returned by `getErasedRepr`. */
string ppReprType(DataFlowType t) { result = t.toString() }
int accessPathLimit() { result = 3 }
/** Holds if `n` should be hidden from path explanations. */

View File

@@ -3,34 +3,34 @@
* global (inter-procedural) taint-tracking analyses.
*/
private import python
private import python
private import TaintTrackingPrivate
private import semmle.code.python.dataflow.DataFlow
/**
* Holds if taint propagates from `source` to `sink` in zero or more local
* (intra-procedural) steps.
*/
predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) }
// /**
// * Holds if taint propagates from `source` to `sink` in zero or more local
// * (intra-procedural) steps.
// */
// predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) }
// // /**
// // * Holds if taint can flow from `e1` to `e2` in zero or more
// // * local (intra-procedural) steps.
// // */
// // predicate localExprTaint(Expr e1, Expr e2) {
// // localTaint(DataFlow::exprNode(e1), DataFlow::exprNode(e2))
// // }
// // /** A member (property or field) that is tainted if its containing object is tainted. */
// // abstract class TaintedMember extends AssignableMember { }
// /**
// * Holds if taint can flow from `e1` to `e2` in zero or more
// * local (intra-procedural) steps.
// * Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
// * (intra-procedural) step.
// */
// predicate localExprTaint(Expr e1, Expr e2) {
// localTaint(DataFlow::exprNode(e1), DataFlow::exprNode(e2))
// }
// /** A member (property or field) that is tainted if its containing object is tainted. */
// abstract class TaintedMember extends AssignableMember { }
/**
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
* (intra-procedural) step.
*/
predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
// Ordinary data flow
DataFlow::localFlowStep(nodeFrom, nodeTo)
or
localAdditionalTaintStep(nodeFrom, nodeTo)
}
// predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
// // Ordinary data flow
// DataFlow::localFlowStep(nodeFrom, nodeTo)
// or
// localAdditionalTaintStep(nodeFrom, nodeTo)
// }