Skip to content

Commit 7d4feac

Browse files
committed
Data flow: Cache ArgumentNode
1 parent ade99c2 commit 7d4feac

File tree

2 files changed

+53
-40
lines changed

2 files changed

+53
-40
lines changed

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

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ private module Stage1 {
385385
*/
386386
pragma[nomagic]
387387
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
388-
exists(ArgumentNode arg |
388+
exists(ArgumentNodeExt arg |
389389
fwdFlow(arg, cc, config) and
390390
viableParamArg(call, _, arg)
391391
)
@@ -512,15 +512,15 @@ private module Stage1 {
512512

513513
pragma[nomagic]
514514
predicate viableParamArgNodeCandFwd1(
515-
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
515+
DataFlowCall call, ParameterNode p, ArgumentNodeExt arg, Configuration config
516516
) {
517517
viableParamArg(call, p, arg) and
518518
fwdFlow(arg, config)
519519
}
520520

521521
pragma[nomagic]
522522
private predicate revFlowIn(
523-
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
523+
DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
524524
) {
525525
exists(ParameterNode p |
526526
revFlow(p, toReturn, config) and
@@ -529,7 +529,7 @@ private module Stage1 {
529529
}
530530

531531
pragma[nomagic]
532-
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
532+
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
533533
revFlowIn(call, arg, true, config)
534534
}
535535

@@ -660,7 +660,7 @@ private predicate flowOutOfCallNodeCand1(
660660

661661
pragma[nomagic]
662662
private predicate viableParamArgNodeCand1(
663-
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
663+
DataFlowCall call, ParameterNode p, ArgumentNodeExt arg, Configuration config
664664
) {
665665
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
666666
Stage1::revFlow(arg, config)
@@ -672,7 +672,7 @@ private predicate viableParamArgNodeCand1(
672672
*/
673673
pragma[nomagic]
674674
private predicate flowIntoCallNodeCand1(
675-
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
675+
DataFlowCall call, ArgumentNodeExt arg, ParameterNode p, Configuration config
676676
) {
677677
viableParamArgNodeCand1(call, p, arg, config) and
678678
Stage1::revFlow(p, config) and
@@ -732,7 +732,7 @@ private predicate flowOutOfCallNodeCand1(
732732
*/
733733
pragma[nomagic]
734734
private predicate flowIntoCallNodeCand1(
735-
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
735+
DataFlowCall call, ArgumentNodeExt arg, ParameterNode p, boolean allowsFieldFlow,
736736
Configuration config
737737
) {
738738
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,7 +944,7 @@ private module Stage2 {
944944
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
945945
Configuration config
946946
) {
947-
exists(ArgumentNode arg, boolean allowsFieldFlow |
947+
exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
948948
fwdFlow(arg, outercc, argAp, ap, config) and
949949
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
950950
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1130,7 +1130,7 @@ private module Stage2 {
11301130

11311131
pragma[nomagic]
11321132
private predicate revFlowIn(
1133-
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
1133+
DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
11341134
Configuration config
11351135
) {
11361136
exists(ParameterNode p, boolean allowsFieldFlow |
@@ -1143,7 +1143,7 @@ private module Stage2 {
11431143

11441144
pragma[nomagic]
11451145
private predicate revFlowInToReturn(
1146-
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
1146+
DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
11471147
) {
11481148
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
11491149
}
@@ -1242,7 +1242,7 @@ private predicate flowOutOfCallNodeCand2(
12421242

12431243
pragma[nomagic]
12441244
private predicate flowIntoCallNodeCand2(
1245-
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
1245+
DataFlowCall call, ArgumentNodeExt node1, ParameterNode node2, boolean allowsFieldFlow,
12461246
Configuration config
12471247
) {
12481248
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1585,7 +1585,7 @@ private module Stage3 {
15851585
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
15861586
Configuration config
15871587
) {
1588-
exists(ArgumentNode arg, boolean allowsFieldFlow |
1588+
exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
15891589
fwdFlow(arg, outercc, argAp, ap, config) and
15901590
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
15911591
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1771,7 +1771,7 @@ private module Stage3 {
17711771

17721772
pragma[nomagic]
17731773
private predicate revFlowIn(
1774-
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
1774+
DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
17751775
Configuration config
17761776
) {
17771777
exists(ParameterNode p, boolean allowsFieldFlow |
@@ -1784,7 +1784,7 @@ private module Stage3 {
17841784

17851785
pragma[nomagic]
17861786
private predicate revFlowInToReturn(
1787-
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
1787+
DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
17881788
) {
17891789
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
17901790
}
@@ -2154,7 +2154,7 @@ private module Stage4 {
21542154

21552155
pragma[nomagic]
21562156
private predicate flowIntoCall(
2157-
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
2157+
DataFlowCall call, ArgumentNodeExt node1, ParameterNode node2, boolean allowsFieldFlow,
21582158
Configuration config
21592159
) {
21602160
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2302,7 +2302,7 @@ private module Stage4 {
23022302
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
23032303
Configuration config
23042304
) {
2305-
exists(ArgumentNode arg, boolean allowsFieldFlow |
2305+
exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
23062306
fwdFlow(arg, outercc, argAp, ap, config) and
23072307
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
23082308
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2488,7 +2488,7 @@ private module Stage4 {
24882488

24892489
pragma[nomagic]
24902490
private predicate revFlowIn(
2491-
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
2491+
DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
24922492
Configuration config
24932493
) {
24942494
exists(ParameterNode p, boolean allowsFieldFlow |
@@ -2501,7 +2501,7 @@ private module Stage4 {
25012501

25022502
pragma[nomagic]
25032503
private predicate revFlowInToReturn(
2504-
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
2504+
DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
25052505
) {
25062506
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
25072507
}
@@ -3234,7 +3234,7 @@ pragma[noinline]
32343234
private predicate pathIntoArg(
32353235
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
32363236
) {
3237-
exists(ArgumentNode arg |
3237+
exists(ArgumentNodeExt arg |
32383238
arg = mid.getNode() and
32393239
cc = mid.getCallContext() and
32403240
arg.argumentOf(call, i) and
@@ -3923,7 +3923,7 @@ private module FlowExploration {
39233923
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
39243924
Configuration config
39253925
) {
3926-
exists(ArgumentNode arg |
3926+
exists(ArgumentNodeExt arg |
39273927
arg = mid.getNode() and
39283928
cc = mid.getCallContext() and
39293929
arg.argumentOf(call, i) and
@@ -4137,7 +4137,7 @@ private module FlowExploration {
41374137

41384138
pragma[nomagic]
41394139
private predicate revPartialPathThroughCallable(
4140-
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
4140+
PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
41414141
) {
41424142
exists(DataFlowCall call, int pos |
41434143
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

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

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@ private module LambdaFlow {
4343
p.isParameterOf(viableCallableLambda(call, _), i)
4444
}
4545

46-
private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
46+
private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNodeExt arg) {
4747
exists(int i |
4848
viableParamNonLambda(call, i, p) and
4949
arg.argumentOf(call, i)
5050
)
5151
}
5252

53-
private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
53+
private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNodeExt arg) {
5454
exists(int i |
5555
viableParamLambda(call, i, p) and
5656
arg.argumentOf(call, i)
@@ -118,7 +118,7 @@ private module LambdaFlow {
118118
boolean toJump, DataFlowCallOption lastCall
119119
) {
120120
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
121-
if castNode(node) or node instanceof ArgumentNode or node instanceof ReturnNode
121+
if castNode(node) or node instanceof ArgumentNodeExt or node instanceof ReturnNode
122122
then compatibleTypes(t, getNodeDataFlowType(node))
123123
else any()
124124
}
@@ -266,14 +266,14 @@ private module Cached {
266266
predicate outNodeExt(Node n) {
267267
n instanceof OutNode
268268
or
269-
n.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
269+
n.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNodeExt
270270
}
271271

272272
cached
273273
OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
274274
result = getAnOutNode(call, k.(ValueReturnKind).getKind())
275275
or
276-
exists(ArgumentNode arg |
276+
exists(ArgumentNodeExt arg |
277277
result.(PostUpdateNode).getPreUpdateNode() = arg and
278278
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
279279
)
@@ -304,6 +304,11 @@ private module Cached {
304304
read(_, _, n)
305305
}
306306

307+
cached
308+
predicate argumentNode(Node n, DataFlowCall call, int pos) {
309+
n.(ArgumentNode).argumentOf(call, pos)
310+
}
311+
307312
/**
308313
* Gets a viable target for the lambda call `call`.
309314
*
@@ -332,7 +337,7 @@ private module Cached {
332337
* dispatch into account.
333338
*/
334339
cached
335-
predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
340+
predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNodeExt arg) {
336341
exists(int i |
337342
viableParam(call, i, p) and
338343
arg.argumentOf(call, i) and
@@ -392,20 +397,20 @@ private module Cached {
392397
)
393398
or
394399
// flow through: no prior read
395-
exists(ArgumentNode arg |
400+
exists(ArgumentNodeExt arg |
396401
parameterValueFlowArgCand(p, arg, false) and
397402
argumentValueFlowsThroughCand(arg, node, read)
398403
)
399404
or
400405
// flow through: no read inside method
401-
exists(ArgumentNode arg |
406+
exists(ArgumentNodeExt arg |
402407
parameterValueFlowArgCand(p, arg, read) and
403408
argumentValueFlowsThroughCand(arg, node, false)
404409
)
405410
}
406411

407412
pragma[nomagic]
408-
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
413+
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNodeExt arg, boolean read) {
409414
parameterValueFlowCand(p, arg, read)
410415
}
411416

@@ -431,7 +436,7 @@ private module Cached {
431436

432437
pragma[nomagic]
433438
private predicate argumentValueFlowsThroughCand0(
434-
DataFlowCall call, ArgumentNode arg, ReturnKind kind, boolean read
439+
DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, boolean read
435440
) {
436441
exists(ParameterNode param | viableParamArg(call, param, arg) |
437442
parameterValueFlowReturnCand(param, kind, read)
@@ -444,7 +449,7 @@ private module Cached {
444449
*
445450
* `read` indicates whether it is contents of `arg` that can flow to `out`.
446451
*/
447-
predicate argumentValueFlowsThroughCand(ArgumentNode arg, Node out, boolean read) {
452+
predicate argumentValueFlowsThroughCand(ArgumentNodeExt arg, Node out, boolean read) {
448453
exists(DataFlowCall call, ReturnKind kind |
449454
argumentValueFlowsThroughCand0(call, arg, kind, read) and
450455
out = getAnOutNode(call, kind)
@@ -520,29 +525,29 @@ private module Cached {
520525
ReadStepTypesOption mustBeNone, ParameterNode p, Node node, ReadStepTypesOption read
521526
) {
522527
// flow through: no prior read
523-
exists(ArgumentNode arg |
528+
exists(ArgumentNodeExt arg |
524529
parameterValueFlowArg(p, arg, mustBeNone) and
525530
argumentValueFlowsThrough(arg, read, node)
526531
)
527532
or
528533
// flow through: no read inside method
529-
exists(ArgumentNode arg |
534+
exists(ArgumentNodeExt arg |
530535
parameterValueFlowArg(p, arg, read) and
531536
argumentValueFlowsThrough(arg, mustBeNone, node)
532537
)
533538
}
534539

535540
pragma[nomagic]
536541
private predicate parameterValueFlowArg(
537-
ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
542+
ParameterNode p, ArgumentNodeExt arg, ReadStepTypesOption read
538543
) {
539544
parameterValueFlow(p, arg, read) and
540545
Cand::argumentValueFlowsThroughCand(arg, _, _)
541546
}
542547

543548
pragma[nomagic]
544549
private predicate argumentValueFlowsThrough0(
545-
DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read
550+
DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, ReadStepTypesOption read
546551
) {
547552
exists(ParameterNode param | viableParamArg(call, param, arg) |
548553
parameterValueFlowReturn(param, kind, read)
@@ -558,7 +563,7 @@ private module Cached {
558563
* container type, and the content type.
559564
*/
560565
pragma[nomagic]
561-
predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
566+
predicate argumentValueFlowsThrough(ArgumentNodeExt arg, ReadStepTypesOption read, Node out) {
562567
exists(DataFlowCall call, ReturnKind kind |
563568
argumentValueFlowsThrough0(call, arg, kind, read) and
564569
out = getAnOutNode(call, kind)
@@ -578,7 +583,7 @@ private module Cached {
578583
* value-preserving steps and a single read step, not taking call
579584
* contexts into account, thus representing a getter-step.
580585
*/
581-
predicate getterStep(ArgumentNode arg, Content c, Node out) {
586+
predicate getterStep(ArgumentNodeExt arg, Content c, Node out) {
582587
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
583588
}
584589

@@ -753,8 +758,8 @@ private module Cached {
753758
// Does the language-specific simpleLocalFlowStep already model flow
754759
// from function input to output?
755760
fromPre = getAnOutNode(c, _) and
756-
toPre.(ArgumentNode).argumentOf(c, _) and
757-
simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
761+
toPre.(ArgumentNodeExt).argumentOf(c, _) and
762+
simpleLocalFlowStep(toPre.(ArgumentNodeExt), fromPre)
758763
)
759764
or
760765
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
@@ -976,6 +981,14 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
976981
else result instanceof LocalCallContextAny
977982
}
978983

984+
/** A data-flow node that represents a call argument. */
985+
class ArgumentNodeExt extends Node {
986+
ArgumentNodeExt() { argumentNode(this, _, _) }
987+
988+
/** Holds if this argument occurs at the given position in the given call. */
989+
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
990+
}
991+
979992
/**
980993
* A node from which flow can return to the caller. This is either a regular
981994
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.

0 commit comments

Comments
 (0)