mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
JavaScript: Add test case exposing two bugs in data flow library.
This test case exposes two bugs in our data flow library (fixed by the
two previous commits):
- the charpreds of `SourcePathNode` and `SinkPathNode` only ensured
that they were on a path from a source to a sink, not that they
actually were the source/sink themselves;
- function summarization would allow for non-level paths; in the
test case, this meant that one of the summaries for `source`
represented the path returning from `source` on line 13 and then
flowing back into the call on line 15, in the process transforming
the parity of the flow label and hence causing a spurious flow.
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
| tst5.mjs:13:12:13:20 | source(0) | tst5.mjs:18:6:18:9 | flow |
|
||||
| tst5.mjs:15:8:15:19 | source(flow) | tst5.mjs:16:13:16:16 | flow |
|
||||
@@ -0,0 +1,33 @@
|
||||
import javascript
|
||||
|
||||
class Parity extends DataFlow::FlowLabel {
|
||||
Parity() { this = "even" or this = "odd" }
|
||||
|
||||
Parity flip() { result != this }
|
||||
}
|
||||
|
||||
class Config extends DataFlow::Configuration {
|
||||
Config() { this = "config" }
|
||||
|
||||
override predicate isSource(DataFlow::Node nd, DataFlow::FlowLabel lbl) {
|
||||
nd.(DataFlow::CallNode).getCalleeName() = "source" and
|
||||
lbl = "even"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node nd, DataFlow::FlowLabel lbl) {
|
||||
nd = any(DataFlow::CallNode c | c.getCalleeName() = "sink").getAnArgument() and
|
||||
lbl = "even"
|
||||
}
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel predLabel, DataFlow::FlowLabel succLabel) {
|
||||
exists(DataFlow::CallNode c | c = succ |
|
||||
c.getCalleeName() = "inc" and
|
||||
pred = c.getAnArgument() and
|
||||
succLabel = predLabel.(Parity).flip()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from Config cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink)
|
||||
select source, sink
|
||||
@@ -0,0 +1,18 @@
|
||||
function source(x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
function sink(x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
function inc(x) {
|
||||
return x+1;
|
||||
}
|
||||
|
||||
var flow = source(0); // source
|
||||
flow = inc(flow);
|
||||
flow = source(flow); // source
|
||||
flow = sink(flow); // sink for line 15, but not for line 13 (wrong parity)
|
||||
flow = inc(flow);
|
||||
sink(flow); // sink for line 13, but not for line 15 (wrong parity)
|
||||
Reference in New Issue
Block a user