Skip to content

Commit c82a2f0

Browse files
committed
C#: Refactor data flow predicates to be defined by dispatch
1 parent d30bce4 commit c82a2f0

File tree

2 files changed

+104
-117
lines changed

2 files changed

+104
-117
lines changed

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

Lines changed: 80 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,14 @@ module DataFlowPrivateCached {
228228
or
229229
any(ArgumentNode n).argumentOf(_, _)
230230
or
231+
exists(any(Node n).getEnclosingCallable())
232+
or
233+
exists(any(Node n).getControlFlowNode())
234+
or
235+
exists(any(Node n).getType())
236+
or
237+
exists(any(Node n).getLocation())
238+
or
231239
exists(any(Node n).toString())
232240
or
233241
exists(any(OutNode n).getCall())
@@ -257,118 +265,6 @@ module DataFlowPrivateCached {
257265
} or
258266
TMallocNode(ControlFlow::Nodes::ElementNode cfn) { cfn.getElement() instanceof ObjectCreation }
259267

260-
cached
261-
DotNet::Callable getEnclosingCallable(Node node) {
262-
result = node.(ExprNode).getExpr().getEnclosingCallable()
263-
or
264-
result = node.(SsaDefinitionNode).getDefinition().getEnclosingCallable()
265-
or
266-
node = TInstanceParameterNode(result)
267-
or
268-
exists(CIL::Parameter p | node = TCilParameterNode(p) | result = p.getCallable())
269-
or
270-
result = getEnclosingCallable(node.(TaintedParameterNode).getUnderlyingNode())
271-
or
272-
result = getEnclosingCallable(node.(TaintedReturnNode).getUnderlyingNode())
273-
or
274-
exists(ControlFlow::Nodes::ElementNode cfn | node = TImplicitCapturedArgumentNode(cfn, _) |
275-
result = cfn.getEnclosingCallable()
276-
)
277-
or
278-
exists(ControlFlow::Nodes::ElementNode cfn | node = TImplicitDelegateOutNode(cfn, _) |
279-
result = cfn.getEnclosingCallable()
280-
)
281-
or
282-
exists(ControlFlow::Nodes::ElementNode cfn | node = TMallocNode(cfn) |
283-
result = cfn.getEnclosingCallable()
284-
)
285-
}
286-
287-
cached
288-
DotNet::Type getType(Node node) {
289-
result = node.(ExprNode).getExpr().getType()
290-
or
291-
result = node.(SsaDefinitionNode).getDefinition().getSourceVariable().getType()
292-
or
293-
exists(Callable c | node = TInstanceParameterNode(c) | result = c.getDeclaringType())
294-
or
295-
exists(CIL::Parameter p | node = TCilParameterNode(p) | result = p.getType())
296-
or
297-
result = getType(node.(TaintedParameterNode).getUnderlyingNode())
298-
or
299-
result = getType(node.(TaintedReturnNode).getUnderlyingNode())
300-
or
301-
exists(LocalScopeVariable v | node = TImplicitCapturedArgumentNode(_, v) | result = v.getType())
302-
or
303-
exists(ControlFlow::Nodes::ElementNode cfn | node = TImplicitDelegateOutNode(cfn, _) |
304-
result = cfn.getElement().(Expr).getType()
305-
)
306-
or
307-
exists(ControlFlow::Nodes::ElementNode cfn | node = TMallocNode(cfn) |
308-
result = cfn.getElement().(Expr).getType()
309-
)
310-
}
311-
312-
cached
313-
Location getLocation(Node node) {
314-
result = node.(ExprNode).getExpr().getLocation()
315-
or
316-
result = node.(SsaDefinitionNode).getDefinition().getLocation()
317-
or
318-
exists(Callable c | node = TInstanceParameterNode(c) | result = c.getLocation())
319-
or
320-
exists(CIL::Parameter p | node = TCilParameterNode(p) | result = p.getLocation())
321-
or
322-
result = getLocation(node.(TaintedParameterNode).getUnderlyingNode())
323-
or
324-
result = getLocation(node.(TaintedReturnNode).getUnderlyingNode())
325-
or
326-
exists(ControlFlow::Nodes::ElementNode cfn | node = TImplicitCapturedArgumentNode(cfn, _) |
327-
result = cfn.getLocation()
328-
)
329-
or
330-
exists(ControlFlow::Nodes::ElementNode cfn | node = TImplicitDelegateOutNode(cfn, _) |
331-
result = cfn.getLocation()
332-
)
333-
or
334-
exists(ControlFlow::Nodes::ElementNode cfn | node = TMallocNode(cfn) |
335-
result = cfn.getLocation()
336-
)
337-
}
338-
339-
cached
340-
string toString(Node node) {
341-
exists(ControlFlow::Nodes::ElementNode cfn | node = TExprNode(cfn) | result = cfn.toString())
342-
or
343-
node = TCilExprNode(_) and
344-
result = "CIL expression"
345-
or
346-
exists(Parameter p | explicitParameterNode(node, p) | result = p.toString())
347-
or
348-
exists(Ssa::Definition def | def = node.(SsaDefinitionNode).getDefinition() |
349-
not explicitParameterNode(node, _) and
350-
result = def.toString()
351-
)
352-
or
353-
node = TInstanceParameterNode(_) and result = "this"
354-
or
355-
exists(CIL::Parameter p | node = TCilParameterNode(p) | result = p.toString())
356-
or
357-
result = toString(node.(TaintedParameterNode).getUnderlyingNode())
358-
or
359-
result = toString(node.(TaintedReturnNode).getUnderlyingNode())
360-
or
361-
exists(LocalScopeVariable v | node = TImplicitCapturedArgumentNode(_, v) |
362-
result = "[implicit argument] " + v
363-
)
364-
or
365-
exists(ControlFlow::Nodes::ElementNode cfn | node = TImplicitDelegateOutNode(cfn, _) |
366-
result = "[output] " + cfn
367-
)
368-
or
369-
node = TMallocNode(_) and result = "malloc"
370-
}
371-
372268
/**
373269
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
374270
* (intra-procedural) step.
@@ -439,6 +335,17 @@ class SsaDefinitionNode extends Node, TSsaDefinitionNode {
439335

440336
/** Gets the underlying SSA definition. */
441337
Ssa::Definition getDefinition() { result = def }
338+
339+
override Callable getEnclosingCallable() { result = def.getEnclosingCallable() }
340+
341+
override Type getType() { result = def.getSourceVariable().getType() }
342+
343+
override Location getLocation() { result = def.getLocation() }
344+
345+
override string toString() {
346+
not explicitParameterNode(this, _) and
347+
result = def.toString()
348+
}
442349
}
443350

444351
private module ParameterNodes {
@@ -469,6 +376,14 @@ private module ParameterNodes {
469376
override DotNet::Parameter getParameter() { result = parameter }
470377

471378
override predicate isParameterOf(DotNet::Callable c, int i) { c.getParameter(i) = parameter }
379+
380+
override DotNet::Callable getEnclosingCallable() { result = parameter.getCallable() }
381+
382+
override DotNet::Type getType() { result = parameter.getType() }
383+
384+
override Location getLocation() { result = parameter.getLocation() }
385+
386+
override string toString() { result = parameter.toString() }
472387
}
473388

474389
/** An implicit instance (`this`) parameter. */
@@ -481,14 +396,22 @@ private module ParameterNodes {
481396
Callable getCallable() { result = callable }
482397

483398
override predicate isParameterOf(DotNet::Callable c, int pos) { callable = c and pos = -1 }
399+
400+
override Callable getEnclosingCallable() { result = callable }
401+
402+
override Type getType() { result = callable.getDeclaringType() }
403+
404+
override Location getLocation() { result = callable.getLocation() }
405+
406+
override string toString() { result = "this" }
484407
}
485408

486409
/**
487410
* A tainted parameter. Tainted parameters are a mere implementation detail, used
488411
* to restrict tainted flow into callables to just taint tracking (just like flow
489412
* out of `TaintedReturnNode`s is restricted to taint tracking).
490413
*/
491-
class TaintedParameterNode extends ParameterNode {
414+
class TaintedParameterNode extends ParameterNode, TTaintedParameterNode {
492415
private Parameter parameter;
493416

494417
TaintedParameterNode() { this = TTaintedParameterNode(parameter) }
@@ -505,6 +428,16 @@ private module ParameterNodes {
505428
// the actual parameters
506429
i = parameter.getPosition() + c.getNumberOfParameters()
507430
}
431+
432+
override Callable getEnclosingCallable() {
433+
result = this.getUnderlyingNode().getEnclosingCallable()
434+
}
435+
436+
override Type getType() { result = this.getUnderlyingNode().getType() }
437+
438+
override Location getLocation() { result = this.getUnderlyingNode().getLocation() }
439+
440+
override string toString() { result = this.getUnderlyingNode().toString() }
508441
}
509442

510443
module ImplicitCapturedParameterNodeImpl {
@@ -746,6 +679,14 @@ private module ArgumentNodes {
746679
)
747680
)
748681
}
682+
683+
override Callable getEnclosingCallable() { result = cfn.getEnclosingCallable() }
684+
685+
override Type getType() { result = v.getType() }
686+
687+
override Location getLocation() { result = cfn.getLocation() }
688+
689+
override string toString() { result = "[implicit argument] " + v }
749690
}
750691

751692
/**
@@ -763,6 +704,14 @@ private module ArgumentNodes {
763704
}
764705

765706
override ControlFlow::Node getControlFlowNode() { result = cfn }
707+
708+
override Callable getEnclosingCallable() { result = cfn.getEnclosingCallable() }
709+
710+
override Type getType() { result = cfn.getElement().(Expr).getType() }
711+
712+
override Location getLocation() { result = cfn.getLocation() }
713+
714+
override string toString() { result = "malloc" }
766715
}
767716
}
768717
import ArgumentNodes
@@ -826,6 +775,16 @@ private module ReturnNodes {
826775
ExprReturnNode getUnderlyingNode() { result.getControlFlowNode() = cfn }
827776

828777
override YieldReturnKind getKind() { any() }
778+
779+
override Callable getEnclosingCallable() {
780+
result = this.getUnderlyingNode().getEnclosingCallable()
781+
}
782+
783+
override Type getType() { result = this.getUnderlyingNode().getType() }
784+
785+
override Location getLocation() { result = this.getUnderlyingNode().getLocation() }
786+
787+
override string toString() { result = this.getUnderlyingNode().toString() }
829788
}
830789

831790
/**
@@ -963,6 +922,14 @@ private module OutNodes {
963922
override ControlFlow::Nodes::ElementNode getControlFlowNode() { result = cfn }
964923

965924
override ImplicitDelegateDataFlowCall getCall() { result.getNode() = this }
925+
926+
override Callable getEnclosingCallable() { result = cfn.getEnclosingCallable() }
927+
928+
override Type getType() { result = cfn.getElement().(Expr).getType() }
929+
930+
override Location getLocation() { result = cfn.getLocation() }
931+
932+
override string toString() { result = "[output] " + cfn }
966933
}
967934
}
968935
import OutNodes

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

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,27 @@ class Node extends C::TNode {
2525
DotNet::Parameter asParameter() { result = this.(ParameterNode).getParameter() }
2626

2727
/** Gets the type of this node. */
28-
final DotNet::Type getType() { result = C::getType(this) }
28+
cached
29+
DotNet::Type getType() { none() }
2930

3031
/** Gets an upper bound on the type of this node. */
3132
DotNet::Type getTypeBound() { result = this.getType() } // stub implementation
3233

3334
/** Gets the enclosing callable of this node. */
34-
final DotNet::Callable getEnclosingCallable() { result = C::getEnclosingCallable(this) }
35+
cached
36+
DotNet::Callable getEnclosingCallable() { none() }
3537

3638
/** Gets the control flow node corresponding to this node, if any. */
39+
cached
3740
ControlFlow::Node getControlFlowNode() { none() }
3841

3942
/** Gets a textual representation of this node. */
40-
final string toString() { result = C::toString(this) }
43+
cached
44+
string toString() { none() }
4145

4246
/** Gets the location of this node. */
43-
final Location getLocation() { result = C::getLocation(this) }
47+
cached
48+
Location getLocation() { none() }
4449
}
4550

4651
/**
@@ -69,7 +74,22 @@ class ExprNode extends Node {
6974
result = cfn.getElement()
7075
}
7176

77+
override DotNet::Callable getEnclosingCallable() {
78+
result = this.getExpr().getEnclosingCallable()
79+
}
80+
7281
override ControlFlow::Nodes::ElementNode getControlFlowNode() { this = C::TExprNode(result) }
82+
83+
override DotNet::Type getType() { result = this.getExpr().getType() }
84+
85+
override Location getLocation() { result = this.getExpr().getLocation() }
86+
87+
override string toString() {
88+
result = this.getControlFlowNode().toString()
89+
or
90+
this = C::TCilExprNode(_) and
91+
result = "CIL expression"
92+
}
7393
}
7494

7595
/**

0 commit comments

Comments
 (0)