Skip to content

Commit 574b220

Browse files
authored
Merge pull request github#12608 from jketema/configsig
C++: Use `DataFlow::ConfigSig` in more places
2 parents 5260d98 + 2fdfa08 commit 574b220

File tree

6 files changed

+65
-75
lines changed

6 files changed

+65
-75
lines changed

cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ import experimental.semmle.code.cpp.semantic.SemanticBound
1515
import experimental.semmle.code.cpp.semantic.SemanticExprSpecific
1616
import semmle.code.cpp.ir.IR
1717
import semmle.code.cpp.ir.dataflow.DataFlow
18-
import semmle.code.cpp.ir.dataflow.DataFlow2
19-
import DataFlow2::PathGraph
18+
import PointerArithmeticToDerefFlow::PathGraph
2019

2120
pragma[nomagic]
2221
Instruction getABoundIn(SemBound b, IRFunction func) {
@@ -36,16 +35,16 @@ predicate bounded(Instruction i, Instruction b, int delta) {
3635
)
3736
}
3837

39-
class FieldAddressToPointerArithmeticConf extends DataFlow::Configuration {
40-
FieldAddressToPointerArithmeticConf() { this = "FieldAddressToPointerArithmeticConf" }
38+
module FieldAddressToPointerArithmeticConfig implements DataFlow::ConfigSig {
39+
predicate isSource(DataFlow::Node source) { isFieldAddressSource(_, source) }
4140

42-
override predicate isSource(DataFlow::Node source) { isFieldAddressSource(_, source) }
43-
44-
override predicate isSink(DataFlow::Node sink) {
41+
predicate isSink(DataFlow::Node sink) {
4542
exists(PointerAddInstruction pai | pai.getLeft() = sink.asInstruction())
4643
}
4744
}
4845

46+
module FieldAddressToPointerArithmeticFlow = DataFlow::Make<FieldAddressToPointerArithmeticConfig>;
47+
4948
predicate isFieldAddressSource(Field f, DataFlow::Node source) {
5049
source.asInstruction().(FieldAddressInstruction).getField() = f
5150
}
@@ -70,11 +69,8 @@ predicate isInvalidPointerDerefSink(DataFlow::Node sink, Instruction i, string o
7069
}
7170

7271
predicate isConstantSizeOverflowSource(Field f, PointerAddInstruction pai, int delta) {
73-
exists(
74-
int size, int bound, FieldAddressToPointerArithmeticConf conf, DataFlow::Node source,
75-
DataFlow::InstructionNode sink
76-
|
77-
conf.hasFlow(source, sink) and
72+
exists(int size, int bound, DataFlow::Node source, DataFlow::InstructionNode sink |
73+
FieldAddressToPointerArithmeticFlow::hasFlow(source, sink) and
7874
isFieldAddressSource(f, source) and
7975
pai.getLeft() = sink.asInstruction() and
8076
f.getUnspecifiedType().(ArrayType).getArraySize() = size and
@@ -86,21 +82,21 @@ predicate isConstantSizeOverflowSource(Field f, PointerAddInstruction pai, int d
8682
)
8783
}
8884

89-
class PointerArithmeticToDerefConf extends DataFlow2::Configuration {
90-
PointerArithmeticToDerefConf() { this = "PointerArithmeticToDerefConf" }
91-
92-
override predicate isSource(DataFlow::Node source) {
85+
module PointerArithmeticToDerefConfig implements DataFlow::ConfigSig {
86+
predicate isSource(DataFlow::Node source) {
9387
isConstantSizeOverflowSource(_, source.asInstruction(), _)
9488
}
9589

96-
override predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _) }
90+
predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _) }
9791
}
9892

93+
module PointerArithmeticToDerefFlow = DataFlow::Make<PointerArithmeticToDerefConfig>;
94+
9995
from
100-
Field f, DataFlow2::PathNode source, DataFlow2::PathNode sink, Instruction deref,
101-
PointerArithmeticToDerefConf conf, string operation, int delta
96+
Field f, PointerArithmeticToDerefFlow::PathNode source,
97+
PointerArithmeticToDerefFlow::PathNode sink, Instruction deref, string operation, int delta
10298
where
103-
conf.hasFlowPath(source, sink) and
99+
PointerArithmeticToDerefFlow::hasFlowPath(source, sink) and
104100
isInvalidPointerDerefSink(sink.getNode(), deref, operation) and
105101
isConstantSizeOverflowSource(f, source.getNode().asInstruction(), delta)
106102
select source, source, sink,

cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
import cpp
1919
import experimental.semmle.code.cpp.dataflow.ProductFlow
20-
import semmle.code.cpp.ir.dataflow.DataFlow3
2120
import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysis
2221
import experimental.semmle.code.cpp.semantic.SemanticBound
2322
import experimental.semmle.code.cpp.semantic.SemanticExprSpecific
@@ -204,14 +203,14 @@ predicate isInvalidPointerDerefSink(DataFlow::Node sink, Instruction i, string o
204203
* A configuration to track flow from a pointer-arithmetic operation found
205204
* by `AllocToInvalidPointerConf` to a dereference of the pointer.
206205
*/
207-
class InvalidPointerToDerefConf extends DataFlow3::Configuration {
208-
InvalidPointerToDerefConf() { this = "InvalidPointerToDerefConf" }
206+
module InvalidPointerToDerefConfig implements DataFlow::ConfigSig {
207+
predicate isSource(DataFlow::Node source) { invalidPointerToDerefSource(_, source, _) }
209208

210-
override predicate isSource(DataFlow::Node source) { invalidPointerToDerefSource(_, source, _) }
211-
212-
override predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _) }
209+
predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _) }
213210
}
214211

212+
module InvalidPointerToDerefFlow = DataFlow::Make<InvalidPointerToDerefConfig>;
213+
215214
/**
216215
* Holds if `pai` is a pointer-arithmetic operation and `source` is a dataflow node with a
217216
* pointer-value that is non-strictly upper bounded by `pai + delta`.
@@ -236,13 +235,13 @@ newtype TMergedPathNode =
236235
// The path nodes computed by the first projection of `AllocToInvalidPointerConf`
237236
TPathNode1(DataFlow::PathNode p) or
238237
// The path nodes computed by `InvalidPointerToDerefConf`
239-
TPathNode3(DataFlow3::PathNode p) or
238+
TPathNode3(InvalidPointerToDerefFlow::PathNode p) or
240239
// The read/write that uses the invalid pointer identified by `InvalidPointerToDerefConf`.
241240
// This one is needed because the sink identified by `InvalidPointerToDerefConf` is the
242241
// pointer, but we want to raise an alert at the dereference.
243242
TPathNodeSink(Instruction i) {
244243
exists(DataFlow::Node n |
245-
any(InvalidPointerToDerefConf conf).hasFlow(_, n) and
244+
InvalidPointerToDerefFlow::hasFlow(_, n) and
246245
isInvalidPointerDerefSink(n, i, _)
247246
)
248247
}
@@ -252,7 +251,7 @@ class MergedPathNode extends TMergedPathNode {
252251

253252
final DataFlow::PathNode asPathNode1() { this = TPathNode1(result) }
254253

255-
final DataFlow3::PathNode asPathNode3() { this = TPathNode3(result) }
254+
final InvalidPointerToDerefFlow::PathNode asPathNode3() { this = TPathNode3(result) }
256255

257256
final Instruction asSinkNode() { this = TPathNodeSink(result) }
258257

@@ -280,7 +279,7 @@ class PathNode1 extends MergedPathNode, TPathNode1 {
280279

281280
class PathNode3 extends MergedPathNode, TPathNode3 {
282281
override string toString() {
283-
exists(DataFlow3::PathNode p |
282+
exists(InvalidPointerToDerefFlow::PathNode p |
284283
this = TPathNode3(p) and
285284
result = p.toString()
286285
)
@@ -324,7 +323,9 @@ query predicate edges(MergedPathNode node1, MergedPathNode node2) {
324323
* Holds if `p1` is a sink of `AllocToInvalidPointerConf` and `p2` is a source
325324
* of `InvalidPointerToDerefConf`, and they are connected through `pai`.
326325
*/
327-
predicate joinOn1(PointerArithmeticInstruction pai, DataFlow::PathNode p1, DataFlow3::PathNode p2) {
326+
predicate joinOn1(
327+
PointerArithmeticInstruction pai, DataFlow::PathNode p1, InvalidPointerToDerefFlow::PathNode p2
328+
) {
328329
isSinkImpl(pai, p1.getNode(), _, _) and
329330
invalidPointerToDerefSource(pai, p2.getNode(), _)
330331
}
@@ -334,28 +335,29 @@ predicate joinOn1(PointerArithmeticInstruction pai, DataFlow::PathNode p1, DataF
334335
* that dereferences `p1`. The string `operation` describes whether the `i` is
335336
* a `StoreInstruction` or `LoadInstruction`.
336337
*/
337-
predicate joinOn2(DataFlow3::PathNode p1, Instruction i, string operation) {
338+
predicate joinOn2(InvalidPointerToDerefFlow::PathNode p1, Instruction i, string operation) {
338339
isInvalidPointerDerefSink(p1.getNode(), i, operation)
339340
}
340341

341342
predicate hasFlowPath(
342-
MergedPathNode source1, MergedPathNode sink, DataFlow3::PathNode source3,
343+
MergedPathNode source1, MergedPathNode sink, InvalidPointerToDerefFlow::PathNode source3,
343344
PointerArithmeticInstruction pai, string operation
344345
) {
345346
exists(
346-
AllocToInvalidPointerConf conf1, InvalidPointerToDerefConf conf2, DataFlow3::PathNode sink3,
347+
AllocToInvalidPointerConf conf1, InvalidPointerToDerefFlow::PathNode sink3,
347348
DataFlow::PathNode sink1
348349
|
349350
conf1.hasFlowPath(source1.asPathNode1(), _, sink1, _) and
350351
joinOn1(pai, sink1, source3) and
351-
conf2.hasFlowPath(source3, sink3) and
352+
InvalidPointerToDerefFlow::hasFlowPath(source3, sink3) and
352353
joinOn2(sink3, sink.asSinkNode(), operation)
353354
)
354355
}
355356

356357
from
357-
MergedPathNode source, MergedPathNode sink, int k, string kstr, DataFlow3::PathNode source3,
358-
PointerArithmeticInstruction pai, string operation, Expr offset, DataFlow::Node n
358+
MergedPathNode source, MergedPathNode sink, int k, string kstr,
359+
InvalidPointerToDerefFlow::PathNode source3, PointerArithmeticInstruction pai, string operation,
360+
Expr offset, DataFlow::Node n
359361
where
360362
hasFlowPath(source, sink, source3, pai, operation) and
361363
invalidPointerToDerefSource(pai, source3.getNode(), k) and
Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
11
import cpp
22
import semmle.code.cpp.dataflow.new.DataFlow
33

4-
class LiteralToGethostbynameConfiguration extends DataFlow::Configuration {
5-
LiteralToGethostbynameConfiguration() { this = "LiteralToGethostbynameConfiguration" }
4+
module LiteralToGethostbynameConfig implements DataFlow::ConfigSig {
5+
predicate isSource(DataFlow::Node source) { source.asIndirectExpr(1) instanceof StringLiteral }
66

7-
override predicate isSource(DataFlow::Node source) {
8-
source.asIndirectExpr(1) instanceof StringLiteral
9-
}
10-
11-
override predicate isSink(DataFlow::Node sink) {
7+
predicate isSink(DataFlow::Node sink) {
128
exists(FunctionCall fc |
139
sink.asIndirectExpr(1) = fc.getArgument(0) and
1410
fc.getTarget().hasName("gethostbyname")
1511
)
1612
}
1713
}
1814

19-
from
20-
StringLiteral sl, FunctionCall fc, LiteralToGethostbynameConfiguration cfg, DataFlow::Node source,
21-
DataFlow::Node sink
15+
module LiteralToGethostbynameFlow = DataFlow::Make<LiteralToGethostbynameConfig>;
16+
17+
from StringLiteral sl, FunctionCall fc, DataFlow::Node source, DataFlow::Node sink
2218
where
2319
source.asIndirectExpr(1) = sl and
2420
sink.asIndirectExpr(1) = fc.getArgument(0) and
25-
cfg.hasFlow(source, sink)
21+
LiteralToGethostbynameFlow::hasFlow(source, sink)
2622
select sl, fc

cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise4.ql

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,22 @@ class GetenvSource extends DataFlow::Node {
55
GetenvSource() { this.asIndirectExpr(1).(FunctionCall).getTarget().hasGlobalName("getenv") }
66
}
77

8-
class GetenvToGethostbynameConfiguration extends DataFlow::Configuration {
9-
GetenvToGethostbynameConfiguration() { this = "GetenvToGethostbynameConfiguration" }
8+
module GetenvToGethostbynameConfig implements DataFlow::ConfigSig {
9+
predicate isSource(DataFlow::Node source) { source instanceof GetenvSource }
1010

11-
override predicate isSource(DataFlow::Node source) { source instanceof GetenvSource }
12-
13-
override predicate isSink(DataFlow::Node sink) {
11+
predicate isSink(DataFlow::Node sink) {
1412
exists(FunctionCall fc |
1513
sink.asIndirectExpr(1) = fc.getArgument(0) and
1614
fc.getTarget().hasName("gethostbyname")
1715
)
1816
}
1917
}
2018

21-
from
22-
Expr getenv, FunctionCall fc, GetenvToGethostbynameConfiguration cfg, DataFlow::Node source,
23-
DataFlow::Node sink
19+
module GetenvToGethostbynameFlow = DataFlow::Make<GetenvToGethostbynameConfig>;
20+
21+
from Expr getenv, FunctionCall fc, DataFlow::Node source, DataFlow::Node sink
2422
where
2523
source.asIndirectExpr(1) = getenv and
2624
sink.asIndirectExpr(1) = fc.getArgument(0) and
27-
cfg.hasFlow(source, sink)
25+
GetenvToGethostbynameFlow::hasFlow(source, sink)
2826
select getenv, fc
Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,27 @@
11
import cpp
22
import semmle.code.cpp.dataflow.new.DataFlow
33

4-
class EnvironmentToFileConfiguration extends DataFlow::Configuration {
5-
EnvironmentToFileConfiguration() { this = "EnvironmentToFileConfiguration" }
6-
7-
override predicate isSource(DataFlow::Node source) {
4+
module EnvironmentToFileConfig implements DataFlow::ConfigSig {
5+
predicate isSource(DataFlow::Node source) {
86
exists(Function getenv |
97
source.asIndirectExpr(1).(FunctionCall).getTarget() = getenv and
108
getenv.hasGlobalName("getenv")
119
)
1210
}
1311

14-
override predicate isSink(DataFlow::Node sink) {
12+
predicate isSink(DataFlow::Node sink) {
1513
exists(FunctionCall fc |
1614
sink.asIndirectExpr(1) = fc.getArgument(0) and
1715
fc.getTarget().hasGlobalName("fopen")
1816
)
1917
}
2018
}
2119

22-
from
23-
Expr getenv, Expr fopen, EnvironmentToFileConfiguration config, DataFlow::Node source,
24-
DataFlow::Node sink
20+
module EnvironmentToFileFlow = DataFlow::Make<EnvironmentToFileConfig>;
21+
22+
from Expr getenv, Expr fopen, DataFlow::Node source, DataFlow::Node sink
2523
where
2624
source.asIndirectExpr(1) = getenv and
2725
sink.asIndirectExpr(1) = fopen and
28-
config.hasFlow(source, sink)
26+
EnvironmentToFileFlow::hasFlow(source, sink)
2927
select fopen, "This 'fopen' uses data from $@.", getenv, "call to 'getenv'"

cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/index-flow-from-ntohl.ql

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,16 @@ import cpp
22
import semmle.code.cpp.controlflow.Guards
33
import semmle.code.cpp.dataflow.new.TaintTracking
44

5-
class NetworkToBufferSizeConfiguration extends TaintTracking::Configuration {
6-
NetworkToBufferSizeConfiguration() { this = "NetworkToBufferSizeConfiguration" }
7-
8-
override predicate isSource(DataFlow::Node node) {
5+
module NetworkToBufferSizeConfig implements DataFlow::ConfigSig {
6+
predicate isSource(DataFlow::Node node) {
97
node.asExpr().(FunctionCall).getTarget().hasGlobalName("ntohl")
108
}
119

12-
override predicate isSink(DataFlow::Node node) {
10+
predicate isSink(DataFlow::Node node) {
1311
exists(ArrayExpr ae | node.asExpr() = ae.getArrayOffset())
1412
}
1513

16-
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
14+
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
1715
exists(Loop loop, LoopCounter lc |
1816
loop = lc.getALoop() and
1917
loop.getControllingExpr().(RelationalOperation).getGreaterOperand() = pred.asExpr()
@@ -22,7 +20,7 @@ class NetworkToBufferSizeConfiguration extends TaintTracking::Configuration {
2220
)
2321
}
2422

25-
override predicate isSanitizer(DataFlow::Node node) {
23+
predicate isBarrier(DataFlow::Node node) {
2624
exists(GuardCondition gc, Variable v |
2725
gc.getAChild*() = v.getAnAccess() and
2826
node.asExpr() = v.getAnAccess() and
@@ -32,7 +30,9 @@ class NetworkToBufferSizeConfiguration extends TaintTracking::Configuration {
3230
}
3331
}
3432

35-
from DataFlow::Node ntohl, DataFlow::Node offset, NetworkToBufferSizeConfiguration conf
36-
where conf.hasFlow(ntohl, offset)
33+
module NetworkToBufferSizeFlow = TaintTracking::Make<NetworkToBufferSizeConfig>;
34+
35+
from DataFlow::Node ntohl, DataFlow::Node offset
36+
where NetworkToBufferSizeFlow::hasFlow(ntohl, offset)
3737
select offset, "This array offset may be influenced by $@.", ntohl,
3838
"converted data from the network"

0 commit comments

Comments
 (0)