Skip to content

Commit 5f8eb7b

Browse files
authored
Merge pull request #16110 from hvitved/dataflow/param-flow-no-expects-content
Data flow: Block flow at `expectsContents` nodes in `parameterValueFlow`
2 parents 1048cf7 + 7871fb8 commit 5f8eb7b

File tree

4 files changed

+73
-28
lines changed

4 files changed

+73
-28
lines changed

ruby/ql/test/library-tests/dataflow/regressions/Regressions.expected

Whitespace-only changes.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
private import codeql.ruby.dataflow.FlowSummary
2+
3+
private class ReverseSummary extends SimpleSummarizedCallable {
4+
ReverseSummary() { this = "reverse" }
5+
6+
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
7+
input = "Argument[self].WithElement[any]" and
8+
output = "ReturnValue" and
9+
preservesValue = true
10+
}
11+
}
12+
13+
private module Config implements DataFlow::ConfigSig {
14+
predicate isSource(DataFlow::Node source) {
15+
source
16+
.(DataFlow::PostUpdateNode)
17+
.getPreUpdateNode()
18+
.asExpr()
19+
.getExpr()
20+
.(MethodCall)
21+
.getMethodName() = "reverse"
22+
}
23+
24+
predicate isSink(DataFlow::Node sink) {
25+
exists(MethodCall mc |
26+
mc.getMethodName() = "sink" and
27+
sink.asExpr().getExpr() = mc.getAnArgument()
28+
)
29+
}
30+
}
31+
32+
/**
33+
* This predicate should not have a result. We check that the flow summary for
34+
* `reverse` does not get picked up by the `reverseStepThroughInputOutputAlias`
35+
* logic in `DataFlowImplCommon.qll`.
36+
*/
37+
query predicate noReverseStepThroughInputOutputAlias(DataFlow::Node source, DataFlow::Node sink) {
38+
DataFlow::Global<Config>::flow(source, sink)
39+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
x = foo
2+
x.reverse.bar
3+
sink(x)

shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -863,34 +863,37 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
863863
*/
864864
pragma[nomagic]
865865
private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
866-
p = node and
867-
read = false
868-
or
869-
// local flow
870-
exists(Node mid |
871-
parameterValueFlowCand(p, mid, read) and
872-
simpleLocalFlowStep(mid, node) and
873-
validParameterAliasStep(mid, node)
874-
)
875-
or
876-
// read
877-
exists(Node mid |
878-
parameterValueFlowCand(p, mid, false) and
879-
readSet(mid, _, node) and
880-
read = true
881-
)
882-
or
883-
// flow through: no prior read
884-
exists(ArgNode arg |
885-
parameterValueFlowArgCand(p, arg, false) and
886-
argumentValueFlowsThroughCand(arg, node, read)
887-
)
888-
or
889-
// flow through: no read inside method
890-
exists(ArgNode arg |
891-
parameterValueFlowArgCand(p, arg, read) and
892-
argumentValueFlowsThroughCand(arg, node, false)
893-
)
866+
(
867+
p = node and
868+
read = false
869+
or
870+
// local flow
871+
exists(Node mid |
872+
parameterValueFlowCand(p, mid, read) and
873+
simpleLocalFlowStep(mid, node) and
874+
validParameterAliasStep(mid, node)
875+
)
876+
or
877+
// read
878+
exists(Node mid |
879+
parameterValueFlowCand(p, mid, false) and
880+
readSet(mid, _, node) and
881+
read = true
882+
)
883+
or
884+
// flow through: no prior read
885+
exists(ArgNode arg |
886+
parameterValueFlowArgCand(p, arg, false) and
887+
argumentValueFlowsThroughCand(arg, node, read)
888+
)
889+
or
890+
// flow through: no read inside method
891+
exists(ArgNode arg |
892+
parameterValueFlowArgCand(p, arg, read) and
893+
argumentValueFlowsThroughCand(arg, node, false)
894+
)
895+
) and
896+
not expectsContentCached(node, _)
894897
}
895898

896899
pragma[nomagic]

0 commit comments

Comments
 (0)