@@ -15,6 +15,7 @@ import cpp
1515import codingstandards.c.cert
1616import codingstandards.cpp.Alignment
1717import semmle.code.cpp.dataflow.DataFlow
18+ import semmle.code.cpp.dataflow.DataFlow2
1819import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
1920import DataFlow:: PathGraph
2021
@@ -40,14 +41,14 @@ abstract class ExprWithAlignment extends Expr {
4041class 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
167184select sink , source , sink ,
168185 "Cast from pointer with " + alignmentFrom +
0 commit comments