Skip to content

Commit fadd23a

Browse files
authored
Merge pull request github#12443 from jketema/even-more-configsig
C++: Update more queries with `DataFlow::ConfigSig`
2 parents a247a8b + 30cbc91 commit fadd23a

File tree

19 files changed

+263
-161
lines changed

19 files changed

+263
-161
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: deprecated
3+
---
4+
* The `WriteConfig` taint tracking configuration has been deprecated. Please use `WriteFlow`.

cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateCleartextWrite.qll

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ module PrivateCleartextWrite {
3636
}
3737
}
3838

39-
class WriteConfig extends TaintTracking::Configuration {
39+
deprecated class WriteConfig extends TaintTracking::Configuration {
4040
WriteConfig() { this = "Write configuration" }
4141

4242
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -46,6 +46,16 @@ module PrivateCleartextWrite {
4646
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
4747
}
4848

49+
private module WriteConfig implements DataFlow::ConfigSig {
50+
predicate isSource(DataFlow::Node source) { source instanceof Source }
51+
52+
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
53+
54+
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
55+
}
56+
57+
module WriteFlow = TaintTracking::Make<WriteConfig>;
58+
4959
class PrivateDataSource extends Source {
5060
PrivateDataSource() { this.getExpr() instanceof PrivateDataExpr }
5161
}

cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ predicate isNonConst(DataFlow::Node node, boolean isIndirect) {
120120
}
121121

122122
pragma[noinline]
123-
predicate isSanitizerNode(DataFlow::Node node) {
123+
predicate isBarrierNode(DataFlow::Node node) {
124124
underscoreMacro([node.asExpr(), node.asIndirectExpr()])
125125
or
126126
exists(node.asExpr()) and
@@ -132,27 +132,27 @@ predicate isSinkImpl(DataFlow::Node sink, Expr formatString) {
132132
exists(FormattingFunctionCall fc | formatString = fc.getArgument(fc.getFormatParameterIndex()))
133133
}
134134

135-
class NonConstFlow extends TaintTracking::Configuration {
136-
NonConstFlow() { this = "NonConstFlow" }
137-
138-
override predicate isSource(DataFlow::Node source) {
135+
module NonConstFlowConfiguration implements DataFlow::ConfigSig {
136+
predicate isSource(DataFlow::Node source) {
139137
exists(boolean isIndirect, Type t |
140138
isNonConst(source, isIndirect) and
141139
t = source.getType() and
142140
not cannotContainString(t, isIndirect)
143141
)
144142
}
145143

146-
override predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) }
144+
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) }
147145

148-
override predicate isSanitizer(DataFlow::Node node) { isSanitizerNode(node) }
146+
predicate isBarrier(DataFlow::Node node) { isBarrierNode(node) }
149147
}
150148

149+
module NonConstFlow = TaintTracking::Make<NonConstFlowConfiguration>;
150+
151151
from FormattingFunctionCall call, Expr formatString
152152
where
153153
call.getArgument(call.getFormatParameterIndex()) = formatString and
154-
exists(NonConstFlow cf, DataFlow::Node sink |
155-
cf.hasFlowTo(sink) and
154+
exists(DataFlow::Node sink |
155+
NonConstFlow::hasFlowTo(sink) and
156156
isSinkImpl(sink, formatString)
157157
)
158158
select formatString,

cpp/ql/src/Likely Bugs/Leap Year/Adding365DaysPerYear.ql

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
import cpp
1515
import LeapYear
1616

17-
from Expr source, Expr sink, PossibleYearArithmeticOperationCheckConfiguration config
18-
where config.hasFlow(DataFlow::exprNode(source), DataFlow::exprNode(sink))
17+
from Expr source, Expr sink
18+
where
19+
PossibleYearArithmeticOperationCheckFlow::hasFlow(DataFlow::exprNode(source),
20+
DataFlow::exprNode(sink))
1921
select sink,
2022
"An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios.",
2123
source, source.toString()

cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,10 @@ class ChecksForLeapYearFunctionCall extends FunctionCall {
206206
}
207207

208208
/**
209-
* `DataFlow::Configuration` for finding a variable access that would flow into
209+
* Data flow configuration for finding a variable access that would flow into
210210
* a function call that includes an operation to check for leap year.
211211
*/
212-
class LeapYearCheckConfiguration extends DataFlow::Configuration {
212+
deprecated class LeapYearCheckConfiguration extends DataFlow::Configuration {
213213
LeapYearCheckConfiguration() { this = "LeapYearCheckConfiguration" }
214214

215215
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof VariableAccess }
@@ -220,9 +220,24 @@ class LeapYearCheckConfiguration extends DataFlow::Configuration {
220220
}
221221

222222
/**
223-
* `DataFlow::Configuration` for finding an operation with hardcoded 365 that will flow into a `FILEINFO` field.
223+
* Data flow configuration for finding a variable access that would flow into
224+
* a function call that includes an operation to check for leap year.
225+
*/
226+
private module LeapYearCheckConfiguration implements DataFlow::ConfigSig {
227+
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof VariableAccess }
228+
229+
predicate isSink(DataFlow::Node sink) {
230+
exists(ChecksForLeapYearFunctionCall fc | sink.asExpr() = fc.getAnArgument())
231+
}
232+
}
233+
234+
module LeapYearCheckFlow = DataFlow::Make<LeapYearCheckConfiguration>;
235+
236+
/**
237+
* Data flow configuration for finding an operation with hardcoded 365 that will flow into
238+
* a `FILEINFO` field.
224239
*/
225-
class FiletimeYearArithmeticOperationCheckConfiguration extends DataFlow::Configuration {
240+
deprecated class FiletimeYearArithmeticOperationCheckConfiguration extends DataFlow::Configuration {
226241
FiletimeYearArithmeticOperationCheckConfiguration() {
227242
this = "FiletimeYearArithmeticOperationCheckConfiguration"
228243
}
@@ -245,10 +260,36 @@ class FiletimeYearArithmeticOperationCheckConfiguration extends DataFlow::Config
245260
}
246261
}
247262

263+
/**
264+
* Data flow configuration for finding an operation with hardcoded 365 that will flow into
265+
* a `FILEINFO` field.
266+
*/
267+
private module FiletimeYearArithmeticOperationCheckConfiguration implements DataFlow::ConfigSig {
268+
predicate isSource(DataFlow::Node source) {
269+
exists(Expr e, Operation op | e = source.asExpr() |
270+
op.getAChild*().getValue().toInt() = 365 and
271+
op.getAChild*() = e
272+
)
273+
}
274+
275+
predicate isSink(DataFlow::Node sink) {
276+
exists(StructLikeClass dds, FieldAccess fa, AssignExpr aexpr, Expr e | e = sink.asExpr() |
277+
dds instanceof PackedTimeType and
278+
fa.getQualifier().getUnderlyingType() = dds and
279+
fa.isModified() and
280+
aexpr.getAChild() = fa and
281+
aexpr.getChild(1).getAChild*() = e
282+
)
283+
}
284+
}
285+
286+
module FiletimeYearArithmeticOperationCheckFlow =
287+
DataFlow::Make<FiletimeYearArithmeticOperationCheckConfiguration>;
288+
248289
/**
249290
* Taint configuration for finding an operation with hardcoded 365 that will flow into any known date/time field.
250291
*/
251-
class PossibleYearArithmeticOperationCheckConfiguration extends TaintTracking::Configuration {
292+
deprecated class PossibleYearArithmeticOperationCheckConfiguration extends TaintTracking::Configuration {
252293
PossibleYearArithmeticOperationCheckConfiguration() {
253294
this = "PossibleYearArithmeticOperationCheckConfiguration"
254295
}
@@ -288,3 +329,46 @@ class PossibleYearArithmeticOperationCheckConfiguration extends TaintTracking::C
288329
)
289330
}
290331
}
332+
333+
/**
334+
* Taint configuration for finding an operation with hardcoded 365 that will flow into any known date/time field.
335+
*/
336+
private module PossibleYearArithmeticOperationCheckConfiguration implements DataFlow::ConfigSig {
337+
predicate isSource(DataFlow::Node source) {
338+
exists(Operation op | op = source.asConvertedExpr() |
339+
op.getAChild*().getValue().toInt() = 365 and
340+
(
341+
not op.getParent() instanceof Expr or
342+
op.getParent() instanceof Assignment
343+
)
344+
)
345+
}
346+
347+
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
348+
// flow from anything on the RHS of an assignment to a time/date structure to that
349+
// assignment.
350+
exists(StructLikeClass dds, FieldAccess fa, Assignment aexpr, Expr e |
351+
e = node1.asExpr() and
352+
fa = node2.asExpr()
353+
|
354+
(dds instanceof PackedTimeType or dds instanceof UnpackedTimeType) and
355+
fa.getQualifier().getUnderlyingType() = dds and
356+
aexpr.getLValue() = fa and
357+
aexpr.getRValue().getAChild*() = e
358+
)
359+
}
360+
361+
predicate isSink(DataFlow::Node sink) {
362+
exists(StructLikeClass dds, FieldAccess fa, AssignExpr aexpr |
363+
aexpr.getRValue() = sink.asConvertedExpr()
364+
|
365+
(dds instanceof PackedTimeType or dds instanceof UnpackedTimeType) and
366+
fa.getQualifier().getUnderlyingType() = dds and
367+
fa.isModified() and
368+
aexpr.getLValue() = fa
369+
)
370+
}
371+
}
372+
373+
module PossibleYearArithmeticOperationCheckFlow =
374+
TaintTracking::Make<PossibleYearArithmeticOperationCheckConfiguration>;

cpp/ql/src/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification.ql

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,18 @@ where
2929
)
3030
or
3131
// If there is a data flow from the variable that was modified to a function that seems to check for leap year
32-
exists(
33-
VariableAccess source, ChecksForLeapYearFunctionCall fc, LeapYearCheckConfiguration config
34-
|
32+
exists(VariableAccess source, ChecksForLeapYearFunctionCall fc |
3533
source = var.getAnAccess() and
36-
config.hasFlow(DataFlow::exprNode(source), DataFlow::exprNode(fc.getAnArgument()))
34+
LeapYearCheckFlow::hasFlow(DataFlow::exprNode(source),
35+
DataFlow::exprNode(fc.getAnArgument()))
3736
)
3837
or
3938
// If there is a data flow from the field that was modified to a function that seems to check for leap year
40-
exists(
41-
VariableAccess vacheck, YearFieldAccess yfacheck, ChecksForLeapYearFunctionCall fc,
42-
LeapYearCheckConfiguration config
43-
|
39+
exists(VariableAccess vacheck, YearFieldAccess yfacheck, ChecksForLeapYearFunctionCall fc |
4440
vacheck = var.getAnAccess() and
4541
yfacheck.getQualifier() = vacheck and
46-
config.hasFlow(DataFlow::exprNode(yfacheck), DataFlow::exprNode(fc.getAnArgument()))
42+
LeapYearCheckFlow::hasFlow(DataFlow::exprNode(yfacheck),
43+
DataFlow::exprNode(fc.getAnArgument()))
4744
)
4845
or
4946
// If there is a successor or predecessor that sets the month = 1

cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,25 @@
1212
import cpp
1313
import semmle.code.cpp.security.boostorg.asio.protocols
1414

15-
class ExistsAnyFlowConfig extends DataFlow::Configuration {
16-
ExistsAnyFlowConfig() { this = "ExistsAnyFlowConfig" }
17-
18-
override predicate isSource(DataFlow::Node source) {
15+
module ExistsAnyFlowConfig implements DataFlow::ConfigSig {
16+
predicate isSource(DataFlow::Node source) {
1917
exists(BoostorgAsio::SslContextClass c | c.getAContructorCall() = source.asExpr())
2018
}
2119

22-
override predicate isSink(DataFlow::Node sink) {
20+
predicate isSink(DataFlow::Node sink) {
2321
exists(BoostorgAsio::SslSetOptionsFunction f, FunctionCall fcSetOptions |
2422
f.getACallToThisFunction() = fcSetOptions and
2523
fcSetOptions.getQualifier() = sink.asExpr()
2624
)
2725
}
2826
}
2927

28+
module ExistsAnyFlow = DataFlow::Make<ExistsAnyFlowConfig>;
29+
3030
bindingset[flag]
3131
predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) {
32-
exists(ExistsAnyFlowConfig anyFlowConfig, VariableAccess contextSetOptions |
33-
anyFlowConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and
32+
exists(VariableAccess contextSetOptions |
33+
ExistsAnyFlow::hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and
3434
exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions |
3535
contextSetOptions = fcSetOptions.getQualifier() and
3636
forall(

cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
import cpp
1515
import semmle.code.cpp.ir.dataflow.DataFlow
16-
import semmle.code.cpp.ir.dataflow.DataFlow2
1716

1817
predicate isCreateProcessFunction(FunctionCall call, int applicationNameIndex, int commandLineIndex) {
1918
call.getTarget().hasGlobalName("CreateProcessA") and
@@ -55,42 +54,40 @@ class CreateProcessFunctionCall extends FunctionCall {
5554
/**
5655
* Dataflow that detects a call to CreateProcess with a NULL value for lpApplicationName argument
5756
*/
58-
class NullAppNameCreateProcessFunctionConfiguration extends DataFlow::Configuration {
59-
NullAppNameCreateProcessFunctionConfiguration() {
60-
this = "NullAppNameCreateProcessFunctionConfiguration"
61-
}
62-
63-
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue }
57+
module NullAppNameCreateProcessFunctionConfiguration implements DataFlow::ConfigSig {
58+
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue }
6459

65-
override predicate isSink(DataFlow::Node sink) {
60+
predicate isSink(DataFlow::Node sink) {
6661
exists(CreateProcessFunctionCall call, Expr val | val = sink.asExpr() |
6762
val = call.getArgument(call.getApplicationNameArgumentId())
6863
)
6964
}
7065
}
7166

67+
module NullAppNameCreateProcessFunction =
68+
DataFlow::Make<NullAppNameCreateProcessFunctionConfiguration>;
69+
7270
/**
7371
* Dataflow that detects a call to CreateProcess with an unquoted commandLine argument
7472
*/
75-
class QuotedCommandInCreateProcessFunctionConfiguration extends DataFlow2::Configuration {
76-
QuotedCommandInCreateProcessFunctionConfiguration() {
77-
this = "QuotedCommandInCreateProcessFunctionConfiguration"
78-
}
79-
80-
override predicate isSource(DataFlow2::Node source) {
73+
module QuotedCommandInCreateProcessFunctionConfiguration implements DataFlow::ConfigSig {
74+
predicate isSource(DataFlow::Node source) {
8175
exists(string s |
8276
s = source.asExpr().getValue().toString() and
8377
not isQuotedOrNoSpaceApplicationNameOnCmd(s)
8478
)
8579
}
8680

87-
override predicate isSink(DataFlow2::Node sink) {
81+
predicate isSink(DataFlow::Node sink) {
8882
exists(CreateProcessFunctionCall call, Expr val | val = sink.asExpr() |
8983
val = call.getArgument(call.getCommandLineArgumentId())
9084
)
9185
}
9286
}
9387

88+
module QuotedCommandInCreateProcessFunction =
89+
DataFlow::Make<QuotedCommandInCreateProcessFunctionConfiguration>;
90+
9491
bindingset[s]
9592
predicate isQuotedOrNoSpaceApplicationNameOnCmd(string s) {
9693
s.regexpMatch("\"([^\"])*\"[\\s\\S]*") // The first element (path) is quoted
@@ -100,14 +97,14 @@ predicate isQuotedOrNoSpaceApplicationNameOnCmd(string s) {
10097

10198
from CreateProcessFunctionCall call, string msg1, string msg2
10299
where
103-
exists(Expr appName, NullAppNameCreateProcessFunctionConfiguration nullAppConfig |
100+
exists(Expr appName |
104101
appName = call.getArgument(call.getApplicationNameArgumentId()) and
105-
nullAppConfig.hasFlowToExpr(appName) and
102+
NullAppNameCreateProcessFunction::hasFlowToExpr(appName) and
106103
msg1 = call.toString() + " with lpApplicationName == NULL (" + appName + ")"
107104
) and
108-
exists(Expr cmd, QuotedCommandInCreateProcessFunctionConfiguration quotedConfig |
105+
exists(Expr cmd |
109106
cmd = call.getArgument(call.getCommandLineArgumentId()) and
110-
quotedConfig.hasFlowToExpr(cmd) and
107+
QuotedCommandInCreateProcessFunction::hasFlowToExpr(cmd) and
111108
msg2 =
112109
" and with an unquoted lpCommandLine (" + cmd +
113110
") introduces a security vulnerability if the path contains spaces."

cpp/ql/src/Security/CWE/CWE-497/PotentiallyExposedSystemData.ql

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,15 @@ import cpp
2828
import semmle.code.cpp.ir.dataflow.TaintTracking
2929
import semmle.code.cpp.models.interfaces.FlowSource
3030
import semmle.code.cpp.security.OutputWrite
31-
import DataFlow::PathGraph
31+
import PotentiallyExposedSystemData::PathGraph
3232
import SystemData
3333

34-
class PotentiallyExposedSystemDataConfiguration extends TaintTracking::Configuration {
35-
PotentiallyExposedSystemDataConfiguration() { this = "PotentiallyExposedSystemDataConfiguration" }
36-
37-
override predicate isSource(DataFlow::Node source) {
34+
module PotentiallyExposedSystemDataConfiguration implements DataFlow::ConfigSig {
35+
predicate isSource(DataFlow::Node source) {
3836
source = any(SystemData sd | sd.isSensitive()).getAnExpr()
3937
}
4038

41-
override predicate isSink(DataFlow::Node sink) {
39+
predicate isSink(DataFlow::Node sink) {
4240
exists(OutputWrite ow, Expr child | child = ow.getASource().getAChild*() |
4341
// Most sinks receive a pointer as an argument (for example `printf`),
4442
// and we use an indirect sink for those.
@@ -53,9 +51,10 @@ class PotentiallyExposedSystemDataConfiguration extends TaintTracking::Configura
5351
}
5452
}
5553

56-
from
57-
PotentiallyExposedSystemDataConfiguration config, DataFlow::PathNode source,
58-
DataFlow::PathNode sink
59-
where config.hasFlowPath(source, sink)
54+
module PotentiallyExposedSystemData =
55+
TaintTracking::Make<PotentiallyExposedSystemDataConfiguration>;
56+
57+
from PotentiallyExposedSystemData::PathNode source, PotentiallyExposedSystemData::PathNode sink
58+
where PotentiallyExposedSystemData::hasFlowPath(source, sink)
6059
select sink, source, sink, "This operation potentially exposes sensitive system data from $@.",
6160
source, source.getNode().toString()

0 commit comments

Comments
 (0)