Skip to content

Commit 03bac50

Browse files
author
Nikita Kraiouchkine
committed
Update EXP36-C query and test
1 parent a157089 commit 03bac50

File tree

3 files changed

+132
-100
lines changed

3 files changed

+132
-100
lines changed

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

Lines changed: 65 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import cpp
1515
import codingstandards.c.cert
1616
import codingstandards.cpp.Alignment
1717
import semmle.code.cpp.dataflow.DataFlow
18+
import semmle.code.cpp.dataflow.DataFlow2
1819
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
1920
import DataFlow::PathGraph
2021

@@ -40,14 +41,14 @@ abstract class ExprWithAlignment extends Expr {
4041
class AddressOfAlignedVariableExpr extends AddressOfExpr, ExprWithAlignment {
4142
AddressOfAlignedVariableExpr() { this.getAddressable() instanceof Variable }
4243

43-
AlignAs alignAsAttribute() { result = this.getAddressable().(Variable).getAnAttribute() }
44+
AlignAs getAlignAsAttribute() { result = this.getAddressable().(Variable).getAnAttribute() }
4445

4546
override int getAlignment() {
46-
result = alignAsAttribute().getArgument(0).getValueInt()
47+
result = getAlignAsAttribute().getArgument(0).getValueInt()
4748
or
48-
result = alignAsAttribute().getArgument(0).getValueType().getSize()
49+
result = getAlignAsAttribute().getArgument(0).getValueType().getSize()
4950
or
50-
not exists(alignAsAttribute()) and
51+
not exists(getAlignAsAttribute()) and
5152
result = this.getAddressable().(Variable).getType().getAlignment()
5253
}
5354

@@ -76,40 +77,35 @@ class DefinedAlignmentAllocationExpr extends FunctionCall, ExprWithAlignment {
7677
}
7778

7879
/**
79-
* A class extending `VariableAccess` and `ExprWithAlignment` to reason about the
80-
* alignment of pointers accessed based solely on the pointers' base types.
80+
* An `Expr` of type `PointerType` but not `VoidPointerType`
81+
* which is the unique non-`Conversion` expression of a `Cast`.
8182
*/
82-
class DefaultAlignedPointerAccessExpr extends VariableAccess, ExprWithAlignment {
83-
DefaultAlignedPointerAccessExpr() {
84-
this.getTarget().getUnspecifiedType() instanceof PointerType and
85-
not this.getTarget().getUnspecifiedType() instanceof VoidPointerType
86-
}
87-
88-
override int getAlignment() {
89-
result = this.getTarget().getType().(PointerType).getBaseType().getAlignment()
83+
class UnconvertedCastFromNonVoidPointerExpr extends Expr {
84+
UnconvertedCastFromNonVoidPointerExpr() {
85+
exists(CStyleCast cast |
86+
cast.getUnconverted() = this and
87+
this.getUnspecifiedType() instanceof PointerType and
88+
not this.getUnspecifiedType() instanceof VoidPointerType
89+
)
9090
}
91-
92-
override string getKind() { result = "pointer base type" }
9391
}
9492

9593
/**
96-
* A data-flow configuration for analysing the flow of `ExprWithAlignment` pointer expressions
97-
* to casts which perform pointer type conversions and potentially create pointer alignment issues.
94+
* A class extending `UnconvertedCastFromNonVoidPointerExpr` and `ExprWithAlignment` to reason
95+
* about the alignment of pointers accessed based solely on the pointers' base types.
9896
*/
99-
class ExprWithAlignmentToCStyleCastConfiguration extends DataFlow::Configuration {
100-
ExprWithAlignmentToCStyleCastConfiguration() {
101-
this = "ExprWithAlignmentToCStyleCastConfiguration"
97+
class DefaultAlignedPointerExpr extends UnconvertedCastFromNonVoidPointerExpr, ExprWithAlignment {
98+
DefaultAlignedPointerExpr() {
99+
not any(AllocationOrAddressOfExprToUnconvertedCastFromNonVoidPointerExprConfig config)
100+
.hasFlowTo(DataFlow::exprNode(this))
102101
}
103102

104-
override predicate isSource(DataFlow::Node source) {
105-
source.asExpr() instanceof ExprWithAlignment
106-
}
103+
override int getAlignment() { result = this.getType().(PointerType).getBaseType().getAlignment() }
107104

108-
override predicate isSink(DataFlow::Node sink) {
109-
exists(CStyleCast cast |
110-
cast.getUnderlyingType() instanceof PointerType and
111-
cast.getUnconverted() = sink.asExpr()
112-
)
105+
override string getKind() {
106+
result =
107+
"pointer base type " +
108+
this.getType().(PointerType).getBaseType().getUnspecifiedType().getName()
113109
}
114110
}
115111

@@ -122,9 +118,9 @@ class ExprWithAlignmentToCStyleCastConfiguration extends DataFlow::Configuration
122118
* to exclude an `DefaultAlignedPointerAccessExpr` as a source if a preceding source
123119
* defined by this configuration provides more accurate alignment information.
124120
*/
125-
class AllocationOrAddressOfExprToDefaultAlignedPointerAccessConfig extends DataFlow::Configuration {
126-
AllocationOrAddressOfExprToDefaultAlignedPointerAccessConfig() {
127-
this = "AllocationOrAddressOfExprToDefaultAlignedPointerAccessConfig"
121+
class AllocationOrAddressOfExprToUnconvertedCastFromNonVoidPointerExprConfig extends DataFlow2::Configuration {
122+
AllocationOrAddressOfExprToUnconvertedCastFromNonVoidPointerExprConfig() {
123+
this = "AllocationOrAddressOfExprToUnconvertedCastFromNonVoidPointerExprConfig"
128124
}
129125

130126
override predicate isSource(DataFlow::Node source) {
@@ -133,7 +129,42 @@ class AllocationOrAddressOfExprToDefaultAlignedPointerAccessConfig extends DataF
133129
}
134130

135131
override predicate isSink(DataFlow::Node sink) {
136-
sink.asExpr() instanceof DefaultAlignedPointerAccessExpr
132+
sink.asExpr() instanceof UnconvertedCastFromNonVoidPointerExpr
133+
}
134+
}
135+
136+
/**
137+
* A data-flow configuration for analysing the flow of `ExprWithAlignment` pointer expressions
138+
* to casts which perform pointer type conversions and potentially create pointer alignment issues.
139+
*/
140+
class ExprWithAlignmentToCStyleCastConfiguration extends DataFlow::Configuration {
141+
ExprWithAlignmentToCStyleCastConfiguration() {
142+
this = "ExprWithAlignmentToCStyleCastConfiguration"
143+
}
144+
145+
override predicate isSource(DataFlow::Node source) {
146+
source.asExpr() instanceof ExprWithAlignment
147+
}
148+
149+
override predicate isSink(DataFlow::Node sink) {
150+
exists(CStyleCast cast |
151+
cast.getUnderlyingType() instanceof PointerType and
152+
cast.getUnconverted() = sink.asExpr()
153+
)
154+
}
155+
156+
override predicate isBarrierOut(DataFlow::Node node) {
157+
// the default interprocedural data-flow model flows through any array assignment expressions
158+
// to the qualifier (array base or pointer dereferenced) instead of the individual element
159+
// that the assignment modifies. this default behaviour causes false positives for any future
160+
// cast of the array base, so remove the assignment edge at the expense of false-negatives.
161+
exists(AssignExpr a |
162+
node.asExpr() = a.getRValue() and
163+
(
164+
a.getLValue() instanceof ArrayExpr or
165+
a.getLValue() instanceof PointerDereferenceExpr
166+
)
167+
)
137168
}
138169
}
139170

@@ -145,24 +176,10 @@ where
145176
any(ExprWithAlignmentToCStyleCastConfiguration config).hasFlowPath(source, sink) and
146177
source.getNode().asExpr() = expr and
147178
sink.getNode().asExpr() = cast.getUnconverted() and
148-
(
149-
// possibility 1: the source node (ExprWithAlignment) is NOT a DefaultAlignedPointerAccessExpr
150-
// meaning that its alignment info is accurate regardless of any preceding ExprWithAlignment nodes
151-
expr instanceof DefaultAlignedPointerAccessExpr
152-
implies
153-
(
154-
// possibility 2: the source node (ExprWithAlignment) IS a DefaultAlignedPointerAccessExpr
155-
// meaning that its alignment info is only accurate if no preceding ExprWithAlignment nodes exist
156-
not any(AllocationOrAddressOfExprToDefaultAlignedPointerAccessConfig config)
157-
.hasFlowTo(source.getNode()) and
158-
expr instanceof DefaultAlignedPointerAccessExpr and
159-
cast.getUnconverted() instanceof VariableAccess
160-
)
161-
) and
162179
toBaseType = cast.getActualType().(PointerType).getBaseType() and
163180
alignmentTo = toBaseType.getAlignment() and
164181
alignmentFrom = expr.getAlignment() and
165-
// only flag cases where the cast's target type has stricter alignment requirements than the source
182+
// flag cases where the cast's target type has stricter alignment requirements than the source
166183
alignmentFrom < alignmentTo
167184
select sink, source, sink,
168185
"Cast from pointer with " + alignmentFrom +

0 commit comments

Comments
 (0)