Skip to content

Commit b142113

Browse files
authored
Merge pull request github#2087 from calumgrant/cs/localexprflow
C#: Implement localExprFlow and localExprTaint
2 parents 3f17014 + d6bbc51 commit b142113

File tree

11 files changed

+27
-15
lines changed

11 files changed

+27
-15
lines changed

change-notes/1.23/analysis-csharp.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,8 @@ The following changes in version 1.23 affect C# analysis in all applications.
4040
overriding `int explorationLimit()`.
4141
* `foreach` statements where the body is guaranteed to be executed at least once, such as `foreach (var x in new string[]{ "a", "b", "c" }) { ... }`, are now recognized by all analyses based on the control flow graph (such as SSA, data flow and taint tracking).
4242
* Fixed the control flow graph for `switch` statements where the `default` case was not the last case. This had caused the remaining cases to be unreachable. `SwitchStmt.getCase(int i)` now puts the `default` case last.
43+
* There is now a `DataFlow::localExprFlow` predicate and a
44+
`TaintTracking::localExprTaint` predicate to make it easy to use the most
45+
common case of local data flow and taint: from one `Expr` to another.
4346

4447
## Changes to autobuilder

csharp/ql/src/Bad Practices/Implementation Hiding/ExposeRepresentation.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ predicate returnsCollection(Callable c, Field f) {
3232
predicate mayWriteToCollection(Expr modified) {
3333
modified instanceof CollectionModificationAccess
3434
or
35-
exists(Expr mid | mayWriteToCollection(mid) | localFlow(exprNode(modified), exprNode(mid)))
35+
exists(Expr mid | mayWriteToCollection(mid) | localExprFlow(modified, mid))
3636
or
3737
exists(MethodCall mid, Callable c | mayWriteToCollection(mid) |
3838
mid.getTarget() = c and

csharp/ql/src/Dead Code/DeadStoreOfLocal.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ predicate nonEscapingCall(Call c) {
6262
predicate mayEscape(LocalVariable v) {
6363
exists(Callable c, Expr e, Expr succ | c = getACapturingCallableAncestor(v) |
6464
e = getADelegateExpr(c) and
65-
DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(succ)) and
65+
DataFlow::localExprFlow(e, succ) and
6666
not succ = any(DelegateCall dc).getDelegateExpr() and
6767
not succ = any(Cast cast).getExpr() and
6868
not succ = any(Call call | nonEscapingCall(call)).getAnArgument() and

csharp/ql/src/Security Features/CWE-119/LocalUnvalidatedArithmetic.ql

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,9 @@ where
2222
// `add` is performing pointer arithmetic
2323
add.getType() instanceof PointerType and
2424
// one of the operands comes, in zero or more steps, from a virtual method call
25-
DataFlow::localFlow(DataFlow::exprNode(taintSrc), DataFlow::exprNode(add.getAnOperand())) and
25+
DataFlow::localExprFlow(taintSrc, add.getAnOperand()) and
2626
// virtual method call result has not been validated
27-
not exists(Expr check, ComparisonOperation cmp |
28-
DataFlow::localFlow(DataFlow::exprNode(taintSrc), DataFlow::exprNode(check))
29-
|
27+
not exists(Expr check, ComparisonOperation cmp | DataFlow::localExprFlow(taintSrc, check) |
3028
cmp.getAnOperand() = check and
3129
add.getAnOperand().(GuardedExpr).isGuardedBy(cmp, check, _)
3230
)

csharp/ql/src/semmle/code/csharp/Property.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ class IndexerProperty extends Property {
520520
pragma[nomagic]
521521
private IndexerCall getAnIndexerCall0() {
522522
exists(Expr qualifier | qualifier = result.getQualifier() |
523-
DataFlow::localFlow(DataFlow::exprNode(this.getAnAccess()), DataFlow::exprNode(qualifier))
523+
DataFlow::localExprFlow(this.getAnAccess(), qualifier)
524524
)
525525
}
526526

csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,12 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) {
164164
*/
165165
predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
166166

167+
/**
168+
* Holds if data can flow from `e1` to `e2` in zero or more
169+
* local (intra-procedural) steps.
170+
*/
171+
predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)) }
172+
167173
/**
168174
* A data flow node that jumps between callables. This can be extended in
169175
* framework code to add additional data flow steps.

csharp/ql/src/semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ private import TaintTrackingPrivate
77
*/
88
predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) }
99

10+
/**
11+
* Holds if taint can flow from `e1` to `e2` in zero or more
12+
* local (intra-procedural) steps.
13+
*/
14+
predicate localExprTaint(Expr e1, Expr e2) {
15+
localTaint(DataFlow::exprNode(e1), DataFlow::exprNode(e2))
16+
}
17+
1018
/** A member (property or field) that is tainted if its containing object is tainted. */
1119
abstract class TaintedMember extends AssignableMember { }
1220

csharp/ql/src/semmle/code/csharp/frameworks/system/Xml.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ class XmlReaderSettingsCreation extends ObjectCreation {
156156
p = this.getType().(RefType).getAProperty() and
157157
exists(PropertyCall set, Expr arg |
158158
set.getTarget() = p.getSetter() and
159-
DataFlow::localFlow(DataFlow::exprNode(this), DataFlow::exprNode(set.getQualifier())) and
159+
DataFlow::localExprFlow(this, set.getQualifier()) and
160160
arg = set.getAnArgument() and
161161
result = getBitwiseOrOperand*(arg)
162162
)

csharp/ql/src/semmle/code/csharp/frameworks/system/text/RegularExpressions.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class RegexOperation extends Call {
7171
|
7272
// e.g. `new Regex(...).Match(...)`
7373
// or `var r = new Regex(...); r.Match(...)`
74-
DataFlow::localFlow(DataFlow::exprNode(this), DataFlow::exprNode(call.getQualifier()))
74+
DataFlow::localExprFlow(this, call.getQualifier())
7575
or
7676
// e.g. `private string r = new Regex(...); public void foo() { r.Match(...); }`
7777
call.getQualifier().(FieldAccess).getTarget().getInitializer() = this

csharp/ql/src/semmle/code/csharp/security/dataflow/ZipSlip.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ module ZipSlip {
142142
// not yet been resolved.
143143
not exists(MethodCall combineCall |
144144
combineCall.getTarget().hasQualifiedName("System.IO.Path", "Combine") and
145-
DataFlow::localFlow(DataFlow::exprNode(combineCall), DataFlow::exprNode(q))
145+
DataFlow::localExprFlow(combineCall, q)
146146
)
147147
}
148148

0 commit comments

Comments
 (0)