Skip to content

Commit 1658a17

Browse files
authored
Merge pull request #468 from jketema/config-update
Modernize dataflow configurations
2 parents 5e17d21 + 27e9e81 commit 1658a17

File tree

54 files changed

+511
-502
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+511
-502
lines changed

c/cert/src/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,14 @@
1414
import cpp
1515
import codingstandards.c.cert
1616
import codingstandards.cpp.dataflow.DataFlow
17-
import DataFlow::PathGraph
17+
import NonArrayPointerToArrayIndexingExprFlow::PathGraph
1818

1919
/**
2020
* A data-flow configuration that tracks flow from an `AddressOfExpr` of a variable
2121
* of `PointerType` that is not also an `ArrayType` to a `PointerArithmeticOrArrayExpr`
2222
*/
23-
class NonArrayPointerToArrayIndexingExprConfig extends DataFlow::Configuration {
24-
NonArrayPointerToArrayIndexingExprConfig() { this = "ArrayToArrayIndexConfig" }
25-
26-
override predicate isSource(DataFlow::Node source) {
23+
module NonArrayPointerToArrayIndexingExprConfig implements DataFlow::ConfigSig {
24+
predicate isSource(DataFlow::Node source) {
2725
exists(AddressOfExpr ao, Type t |
2826
source.asExpr() = ao and
2927
not ao.getOperand() instanceof ArrayExpr and
@@ -35,15 +33,15 @@ class NonArrayPointerToArrayIndexingExprConfig extends DataFlow::Configuration {
3533
)
3634
}
3735

38-
override predicate isSink(DataFlow::Node sink) {
36+
predicate isSink(DataFlow::Node sink) {
3937
exists(PointerArithmeticOrArrayExpr ae |
4038
sink.asExpr() = ae.getPointerOperand() and
4139
not sink.asExpr() instanceof Literal and
4240
not ae.isNonPointerOperandZero()
4341
)
4442
}
4543

46-
override predicate isBarrierOut(DataFlow::Node node) {
44+
predicate isBarrierOut(DataFlow::Node node) {
4745
// the default interprocedural data-flow model flows through any field or array assignment
4846
// expressions to the qualifier (array base, pointer dereferenced, or qualifier) instead of the
4947
// individual element or field that the assignment modifies. this default behaviour causes
@@ -63,6 +61,9 @@ class NonArrayPointerToArrayIndexingExprConfig extends DataFlow::Configuration {
6361
}
6462
}
6563

64+
module NonArrayPointerToArrayIndexingExprFlow =
65+
DataFlow::Global<NonArrayPointerToArrayIndexingExprConfig>;
66+
6667
class PointerArithmeticOrArrayExpr extends Expr {
6768
Expr operand;
6869

@@ -101,9 +102,11 @@ class PointerArithmeticOrArrayExpr extends Expr {
101102
predicate isNonPointerOperandZero() { operand.(Literal).getValue().toInt() = 0 }
102103
}
103104

104-
from DataFlow::PathNode source, DataFlow::PathNode sink
105+
from
106+
NonArrayPointerToArrayIndexingExprFlow::PathNode source,
107+
NonArrayPointerToArrayIndexingExprFlow::PathNode sink
105108
where
106109
not isExcluded(sink.getNode().asExpr(),
107110
InvalidMemory2Package::doNotUsePointerArithmeticOnNonArrayObjectPointersQuery()) and
108-
any(NonArrayPointerToArrayIndexingExprConfig cfg).hasFlowPath(source, sink)
111+
NonArrayPointerToArrayIndexingExprFlow::flowPath(source, sink)
109112
select sink, source, sink, "Pointer arithmetic on non-array object pointer."

c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import cpp
1515
import codingstandards.c.cert
1616
import codingstandards.c.Pointers
1717
import codingstandards.cpp.dataflow.TaintTracking
18-
import DataFlow::PathGraph
18+
import ScaledIntegerPointerArithmeticFlow::PathGraph
1919

2020
/**
2121
* An expression which invokes the `offsetof` macro or `__builtin_offsetof` operation.
@@ -69,12 +69,10 @@ class ScaledIntegerExpr extends Expr {
6969
* A data-flow configuration modeling data-flow from a `ScaledIntegerExpr` to a
7070
* `PointerArithmeticExpr` where the pointer does not point to a 1-byte type.
7171
*/
72-
class ScaledIntegerPointerArithmeticConfig extends DataFlow::Configuration {
73-
ScaledIntegerPointerArithmeticConfig() { this = "ScaledIntegerPointerArithmeticConfig" }
72+
module ScaledIntegerPointerArithmeticConfig implements DataFlow::ConfigSig {
73+
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ScaledIntegerExpr }
7474

75-
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ScaledIntegerExpr }
76-
77-
override predicate isSink(DataFlow::Node sink) {
75+
predicate isSink(DataFlow::Node sink) {
7876
exists(PointerArithmeticExpr pa |
7977
// exclude pointers to 1-byte types as they do not scale
8078
pa.getPointer().getFullyConverted().getType().(DerivedType).getBaseType().getSize() != 1 and
@@ -83,9 +81,13 @@ class ScaledIntegerPointerArithmeticConfig extends DataFlow::Configuration {
8381
}
8482
}
8583

86-
from ScaledIntegerPointerArithmeticConfig config, DataFlow::PathNode src, DataFlow::PathNode sink
84+
module ScaledIntegerPointerArithmeticFlow = DataFlow::Global<ScaledIntegerPointerArithmeticConfig>;
85+
86+
from
87+
ScaledIntegerPointerArithmeticFlow::PathNode src,
88+
ScaledIntegerPointerArithmeticFlow::PathNode sink
8789
where
8890
not isExcluded(sink.getNode().asExpr(),
8991
Pointers2Package::doNotAddOrSubtractAScaledIntegerToAPointerQuery()) and
90-
config.hasFlowPath(src, sink)
92+
ScaledIntegerPointerArithmeticFlow::flowPath(src, sink)
9193
select sink, src, sink, "Scaled integer used in pointer arithmetic."

c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,8 @@ import codingstandards.cpp.Concurrency
1818
import codingstandards.cpp.dataflow.TaintTracking
1919
import codingstandards.cpp.dataflow.DataFlow
2020

21-
class TssCreateToTssDeleteDataFlowConfiguration extends DataFlow::Configuration {
22-
TssCreateToTssDeleteDataFlowConfiguration() { this = "TssCreateToTssDeleteDataFlowConfiguration" }
23-
24-
override predicate isSource(DataFlow::Node node) {
21+
module TssCreateToTssDeleteConfig implements DataFlow::ConfigSig {
22+
predicate isSource(DataFlow::Node node) {
2523
exists(TSSCreateFunctionCall tsc, Expr e |
2624
// the only requirement of the source is that at some point
2725
// it refers to the key of a create statement
@@ -30,7 +28,7 @@ class TssCreateToTssDeleteDataFlowConfiguration extends DataFlow::Configuration
3028
)
3129
}
3230

33-
override predicate isSink(DataFlow::Node node) {
31+
predicate isSink(DataFlow::Node node) {
3432
exists(TSSDeleteFunctionCall tsd, Expr e |
3533
// the only requirement of a sink is that at some point
3634
// it references the key of a delete call.
@@ -40,15 +38,17 @@ class TssCreateToTssDeleteDataFlowConfiguration extends DataFlow::Configuration
4038
}
4139
}
4240

41+
module TssCreateToTssDeleteFlow = DataFlow::Global<TssCreateToTssDeleteConfig>;
42+
4343
from TSSCreateFunctionCall tcfc
4444
where
4545
not isExcluded(tcfc, Concurrency4Package::cleanUpThreadSpecificStorageQuery()) and
4646
// all calls to `tss_create` must be bookended by calls to tss_delete
4747
// even if a thread is not created.
48-
not exists(TssCreateToTssDeleteDataFlowConfiguration config |
49-
config.hasFlow(DataFlow::definitionByReferenceNodeFromArgument(tcfc.getKey()), _)
48+
not (
49+
TssCreateToTssDeleteFlow::flow(DataFlow::definitionByReferenceNodeFromArgument(tcfc.getKey()), _)
5050
or
51-
config.hasFlow(DataFlow::exprNode(tcfc.getKey()), _)
51+
TssCreateToTssDeleteFlow::flow(DataFlow::exprNode(tcfc.getKey()), _)
5252
)
5353
or
5454
// if a thread is created, we must check additional items

c/cert/src/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.ql

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@ import cpp
1515
import codingstandards.c.cert
1616
import codingstandards.cpp.Alignment
1717
import codingstandards.cpp.dataflow.DataFlow
18-
import codingstandards.cpp.dataflow.DataFlow2
1918
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
20-
import DataFlow::PathGraph
19+
import ExprWithAlignmentToCStyleCastFlow::PathGraph
2120

2221
/**
2322
* An expression with a type that has defined alignment requirements
@@ -96,8 +95,7 @@ class UnconvertedCastFromNonVoidPointerExpr extends Expr {
9695
*/
9796
class DefaultAlignedPointerExpr extends UnconvertedCastFromNonVoidPointerExpr, ExprWithAlignment {
9897
DefaultAlignedPointerExpr() {
99-
not any(AllocationOrAddressOfExprToUnconvertedCastFromNonVoidPointerExprConfig config)
100-
.hasFlowTo(DataFlow::exprNode(this))
98+
not AllocationOrAddressOfExprToUnconvertedCastFromNonVoidPointerExprFlow::flowTo(DataFlow::exprNode(this))
10199
}
102100

103101
override int getAlignment() { result = this.getType().(PointerType).getBaseType().getAlignment() }
@@ -118,43 +116,37 @@ class DefaultAlignedPointerExpr extends UnconvertedCastFromNonVoidPointerExpr, E
118116
* to exclude an `DefaultAlignedPointerAccessExpr` as a source if a preceding source
119117
* defined by this configuration provides more accurate alignment information.
120118
*/
121-
class AllocationOrAddressOfExprToUnconvertedCastFromNonVoidPointerExprConfig extends DataFlow2::Configuration
119+
module AllocationOrAddressOfExprToUnconvertedCastFromNonVoidPointerExprConfig implements
120+
DataFlow::ConfigSig
122121
{
123-
AllocationOrAddressOfExprToUnconvertedCastFromNonVoidPointerExprConfig() {
124-
this = "AllocationOrAddressOfExprToUnconvertedCastFromNonVoidPointerExprConfig"
125-
}
126-
127-
override predicate isSource(DataFlow::Node source) {
122+
predicate isSource(DataFlow::Node source) {
128123
source.asExpr() instanceof AddressOfAlignedVariableExpr or
129124
source.asExpr() instanceof DefinedAlignmentAllocationExpr
130125
}
131126

132-
override predicate isSink(DataFlow::Node sink) {
127+
predicate isSink(DataFlow::Node sink) {
133128
sink.asExpr() instanceof UnconvertedCastFromNonVoidPointerExpr
134129
}
135130
}
136131

132+
module AllocationOrAddressOfExprToUnconvertedCastFromNonVoidPointerExprFlow =
133+
DataFlow::Global<AllocationOrAddressOfExprToUnconvertedCastFromNonVoidPointerExprConfig>;
134+
137135
/**
138136
* A data-flow configuration for analysing the flow of `ExprWithAlignment` pointer expressions
139137
* to casts which perform pointer type conversions and potentially create pointer alignment issues.
140138
*/
141-
class ExprWithAlignmentToCStyleCastConfiguration extends DataFlow::Configuration {
142-
ExprWithAlignmentToCStyleCastConfiguration() {
143-
this = "ExprWithAlignmentToCStyleCastConfiguration"
144-
}
139+
module ExprWithAlignmentToCStyleCastConfig implements DataFlow::ConfigSig {
140+
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof ExprWithAlignment }
145141

146-
override predicate isSource(DataFlow::Node source) {
147-
source.asExpr() instanceof ExprWithAlignment
148-
}
149-
150-
override predicate isSink(DataFlow::Node sink) {
142+
predicate isSink(DataFlow::Node sink) {
151143
exists(CStyleCast cast |
152144
cast.getUnderlyingType() instanceof PointerType and
153145
cast.getUnconverted() = sink.asExpr()
154146
)
155147
}
156148

157-
override predicate isBarrierOut(DataFlow::Node node) {
149+
predicate isBarrierOut(DataFlow::Node node) {
158150
// the default interprocedural data-flow model flows through any array assignment expressions
159151
// to the qualifier (array base or pointer dereferenced) instead of the individual element
160152
// that the assignment modifies. this default behaviour causes false positives for any future
@@ -169,12 +161,15 @@ class ExprWithAlignmentToCStyleCastConfiguration extends DataFlow::Configuration
169161
}
170162
}
171163

164+
module ExprWithAlignmentToCStyleCastFlow = DataFlow::Global<ExprWithAlignmentToCStyleCastConfig>;
165+
172166
from
173-
DataFlow::PathNode source, DataFlow::PathNode sink, ExprWithAlignment expr, CStyleCast cast,
167+
ExprWithAlignmentToCStyleCastFlow::PathNode source,
168+
ExprWithAlignmentToCStyleCastFlow::PathNode sink, ExprWithAlignment expr, CStyleCast cast,
174169
Type toBaseType, int alignmentFrom, int alignmentTo
175170
where
176171
not isExcluded(cast, Pointers3Package::doNotCastPointerToMoreStrictlyAlignedPointerTypeQuery()) and
177-
any(ExprWithAlignmentToCStyleCastConfiguration config).hasFlowPath(source, sink) and
172+
ExprWithAlignmentToCStyleCastFlow::flowPath(source, sink) and
178173
source.getNode().asExpr() = expr and
179174
sink.getNode().asExpr() = cast.getUnconverted() and
180175
toBaseType = cast.getActualType().(PointerType).getBaseType() and

c/cert/src/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.ql

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import cpp
1515
import codingstandards.c.cert
1616
import codingstandards.cpp.dataflow.DataFlow
17-
import DataFlow::PathGraph
17+
import SuspectFunctionPointerToCallFlow::PathGraph
1818

1919
/**
2020
* An expression of type `FunctionPointer` which is the unconverted expression of a cast
@@ -37,26 +37,26 @@ class SuspiciousFunctionPointerCastExpr extends Expr {
3737
* Data-flow configuration for flow from a `SuspiciousFunctionPointerCastExpr`
3838
* to a call of the function pointer resulting from the function pointer cast
3939
*/
40-
class SuspectFunctionPointerToCallConfig extends DataFlow::Configuration {
41-
SuspectFunctionPointerToCallConfig() { this = "SuspectFunctionPointerToCallConfig" }
42-
43-
override predicate isSource(DataFlow::Node src) {
40+
module SuspectFunctionPointerToCallConfig implements DataFlow::ConfigSig {
41+
predicate isSource(DataFlow::Node src) {
4442
src.asExpr() instanceof SuspiciousFunctionPointerCastExpr
4543
}
4644

47-
override predicate isSink(DataFlow::Node sink) {
45+
predicate isSink(DataFlow::Node sink) {
4846
exists(VariableCall call | sink.asExpr() = call.getExpr().(VariableAccess))
4947
}
5048
}
5149

50+
module SuspectFunctionPointerToCallFlow = DataFlow::Global<SuspectFunctionPointerToCallConfig>;
51+
5252
from
53-
SuspectFunctionPointerToCallConfig config, DataFlow::PathNode src, DataFlow::PathNode sink,
53+
SuspectFunctionPointerToCallFlow::PathNode src, SuspectFunctionPointerToCallFlow::PathNode sink,
5454
Access access
5555
where
5656
not isExcluded(src.getNode().asExpr(),
5757
ExpressionsPackage::doNotCallFunctionPointerWithIncompatibleTypeQuery()) and
5858
access = src.getNode().asExpr() and
59-
config.hasFlowPath(src, sink)
59+
SuspectFunctionPointerToCallFlow::flowPath(src, sink)
6060
select src, src, sink,
6161
"Incompatible function $@ assigned to function pointer is eventually called through the pointer.",
6262
access.getTarget(), access.getTarget().getName()

c/cert/src/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.ql

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import cpp
1515
import codingstandards.c.cert
1616
import codingstandards.cpp.dataflow.DataFlow
1717
import semmle.code.cpp.controlflow.Dominance
18-
import DataFlow::PathGraph
18+
import IndirectCastFlow::PathGraph
1919

2020
/**
2121
* The standard function `memset` and its assorted variants
@@ -62,15 +62,15 @@ class IndirectCastReallocatedFlowState extends DataFlow::FlowState {
6262
* other cast expressions or to dereferences of pointers reallocated with a call
6363
* to `realloc` but not cleared via a function call to `memset`.
6464
*/
65-
class IndirectCastConfiguration extends DataFlow::Configuration {
66-
IndirectCastConfiguration() { this = "CastToIncompatibleTypeConfiguration" }
65+
module IndirectCastConfig implements DataFlow::StateConfigSig {
66+
class FlowState = DataFlow::FlowState;
6767

68-
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
68+
predicate isSource(DataFlow::Node source, FlowState state) {
6969
state instanceof IndirectCastDefaultFlowState and
7070
source.asExpr() instanceof IndirectCastAnalysisUnconvertedCastExpr
7171
}
7272

73-
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
73+
predicate isSink(DataFlow::Node sink, FlowState state) {
7474
sink.asExpr() instanceof IndirectCastAnalysisUnconvertedCastExpr and
7575
state instanceof IndirectCastDefaultFlowState
7676
or
@@ -103,17 +103,16 @@ class IndirectCastConfiguration extends DataFlow::Configuration {
103103
)
104104
}
105105

106-
override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) {
106+
predicate isBarrier(DataFlow::Node node, FlowState state) {
107107
state instanceof IndirectCastReallocatedFlowState and
108108
exists(FunctionCall fc |
109109
fc.getTarget() instanceof MemsetFunction and
110110
fc.getArgument(0) = node.asExpr()
111111
)
112112
}
113113

114-
override predicate isAdditionalFlowStep(
115-
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
116-
DataFlow::FlowState state2
114+
predicate isAdditionalFlowStep(
115+
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
117116
) {
118117
// track pointer flow through realloc calls and update state to `IndirectCastReallocatedFlowState`
119118
state1 instanceof IndirectCastDefaultFlowState and
@@ -135,6 +134,8 @@ class IndirectCastConfiguration extends DataFlow::Configuration {
135134
}
136135
}
137136

137+
module IndirectCastFlow = DataFlow::GlobalWithState<IndirectCastConfig>;
138+
138139
pragma[inline]
139140
predicate areTypesSameExceptForConstSpecifiers(Type a, Type b) {
140141
a.stripType() = b.stripType() and
@@ -190,12 +191,14 @@ Type compatibleTypes(Type type) {
190191
)
191192
}
192193

193-
from DataFlow::PathNode source, DataFlow::PathNode sink, Cast cast, Type fromType, Type toType
194+
from
195+
IndirectCastFlow::PathNode source, IndirectCastFlow::PathNode sink, Cast cast, Type fromType,
196+
Type toType
194197
where
195198
not isExcluded(sink.getNode().asExpr(),
196199
Pointers3Package::doNotAccessVariableViaPointerOfIncompatibleTypeQuery()) and
197200
cast.getFile().compiledAsC() and
198-
any(IndirectCastConfiguration config).hasFlowPath(source, sink) and
201+
IndirectCastFlow::flowPath(source, sink) and
199202
// include only sinks which are not a compatible type to the associated source
200203
source.getNode().asExpr() = cast.getUnconverted() and
201204
fromType = cast.getUnconverted().getType().(PointerType).getBaseType() and

c/cert/src/rules/EXP40-C/DoNotModifyConstantObjects.ql

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import cpp
1414
import codingstandards.c.cert
1515
import codingstandards.cpp.dataflow.DataFlow
16-
import DataFlow::PathGraph
16+
import CastFlow::PathGraph
1717
import codingstandards.cpp.SideEffect
1818

1919
class ConstRemovingCast extends Cast {
@@ -32,23 +32,23 @@ class MaybeReturnsStringLiteralFunctionCall extends FunctionCall {
3232
}
3333
}
3434

35-
class MyDataFlowConfCast extends DataFlow::Configuration {
36-
MyDataFlowConfCast() { this = "MyDataFlowConfCast" }
37-
38-
override predicate isSource(DataFlow::Node source) {
35+
module CastConfig implements DataFlow::ConfigSig {
36+
predicate isSource(DataFlow::Node source) {
3937
source.asExpr().getFullyConverted() instanceof ConstRemovingCast
4038
or
4139
source.asExpr().getFullyConverted() = any(MaybeReturnsStringLiteralFunctionCall c)
4240
}
4341

44-
override predicate isSink(DataFlow::Node sink) {
42+
predicate isSink(DataFlow::Node sink) {
4543
sink.asExpr() = any(Assignment a).getLValue().(PointerDereferenceExpr).getOperand()
4644
}
4745
}
4846

49-
from MyDataFlowConfCast conf, DataFlow::PathNode src, DataFlow::PathNode sink
47+
module CastFlow = DataFlow::Global<CastConfig>;
48+
49+
from CastFlow::PathNode src, CastFlow::PathNode sink
5050
where
51-
conf.hasFlowPath(src, sink)
51+
CastFlow::flowPath(src, sink)
5252
or
5353
sink.getNode()
5454
.asExpr()

0 commit comments

Comments
 (0)