1
1
/**
2
- * @id c/cert/do-not-pass-alised -pointer-to-restrict-qualified-parameter
2
+ * @id c/cert/do-not-pass-aliased -pointer-to-restrict-qualified-param
3
3
* @name EXP43-C: Do not pass aliased pointers to restrict-qualified parameters
4
4
* @description Passing an aliased pointer to a restrict-qualified parameter is undefined behavior.
5
5
* @kind problem
13
13
import cpp
14
14
import codingstandards.c.cert
15
15
import codingstandards.c.Pointers
16
- import semmle.code.cpp.dataflow.DataFlow
16
+ import codingstandards.c.Variable
17
+ import semmle.code.cpp.ir.dataflow.DataFlow
17
18
import semmle.code.cpp.pointsto.PointsTo
18
19
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
19
20
@@ -67,10 +68,9 @@ class CallToFunctionWithRestrictParameters extends FunctionCall {
67
68
/**
68
69
* A `PointsToExpr` that is an argument of a pointer-type in a `CallToFunctionWithRestrictParameters`
69
70
*/
70
- class ArgPointsToExpr extends PointsToExpr {
71
- override predicate interesting ( ) {
72
- any ( CallToFunctionWithRestrictParameters call ) .getAnArgument ( ) = this and
73
- pointerValue ( this )
71
+ class CallToFunctionWithRestrictParametersArgExpr extends Expr {
72
+ CallToFunctionWithRestrictParametersArgExpr ( ) {
73
+ this = any ( CallToFunctionWithRestrictParameters call ) .getAPtrArg ( )
74
74
}
75
75
}
76
76
@@ -82,7 +82,7 @@ int getStatedValue(Expr e) {
82
82
.minimum ( min ( Expr source | DataFlow:: localExprFlow ( source , e ) | source .getValue ( ) .toInt ( ) ) )
83
83
}
84
84
85
- int getPointerArithmeticOperandStatedValue ( ArgPointsToExpr expr ) {
85
+ int getPointerArithmeticOperandStatedValue ( CallToFunctionWithRestrictParametersArgExpr expr ) {
86
86
result = getStatedValue ( expr .( PointerArithmeticExpr ) .getOperand ( ) )
87
87
or
88
88
// edge-case: &(array[index]) expressions
@@ -94,18 +94,37 @@ int getPointerArithmeticOperandStatedValue(ArgPointsToExpr expr) {
94
94
result = 0
95
95
}
96
96
97
+ class PointerValueToRestrictArgConfig extends DataFlow:: Configuration {
98
+ PointerValueToRestrictArgConfig ( ) { this = "PointerValueToRestrictArgConfig" }
99
+
100
+ override predicate isSource ( DataFlow:: Node source ) { pointerValue ( source .asExpr ( ) ) }
101
+
102
+ override predicate isSink ( DataFlow:: Node sink ) {
103
+ exists ( CallToFunctionWithRestrictParameters call |
104
+ sink .asExpr ( ) = call .getAPtrArg ( ) .getAChild * ( )
105
+ )
106
+ }
107
+ }
108
+
97
109
from
98
- CallToFunctionWithRestrictParameters call , ArgPointsToExpr arg1 , ArgPointsToExpr arg2 ,
99
- int argOffset1 , int argOffset2
110
+ CallToFunctionWithRestrictParameters call , CallToFunctionWithRestrictParametersArgExpr arg1 ,
111
+ CallToFunctionWithRestrictParametersArgExpr arg2 , int argOffset1 , int argOffset2
100
112
where
101
- not isExcluded ( call , Pointers3Package:: doNotPassAlisedPointerToRestrictQualifiedParameterQuery ( ) ) and
113
+ not isExcluded ( call , Pointers3Package:: doNotPassAliasedPointerToRestrictQualifiedParamQuery ( ) ) and
102
114
arg1 = call .getARestrictPtrArg ( ) and
103
115
arg2 = call .getAPtrArg ( ) and
104
- // two arguments that point to the same object
105
116
arg1 != arg2 and
106
- arg1 .pointsTo ( ) = arg2 .pointsTo ( ) and
107
- arg1 .confidence ( ) = 1.0 and
108
- arg2 .confidence ( ) = 1.0 and
117
+ exists ( PointerValueToRestrictArgConfig config , Expr source1 , Expr source2 |
118
+ config .hasFlow ( DataFlow:: exprNode ( source1 ) , DataFlow:: exprNode ( arg1 .getAChild * ( ) ) ) and
119
+ (
120
+ // one pointer value flows to both args
121
+ config .hasFlow ( DataFlow:: exprNode ( source1 ) , DataFlow:: exprNode ( arg2 .getAChild * ( ) ) )
122
+ or
123
+ // there are two separate values that flow from an AddressOfExpr of the same target
124
+ getAddressOfExprTargetBase ( source1 ) = getAddressOfExprTargetBase ( source2 ) and
125
+ config .hasFlow ( DataFlow:: exprNode ( source2 ) , DataFlow:: exprNode ( arg2 .getAChild * ( ) ) )
126
+ )
127
+ ) and
109
128
// get the offset of the pointer arithmetic operand (or '0' if there is none)
110
129
argOffset1 = getPointerArithmeticOperandStatedValue ( arg1 ) and
111
130
argOffset2 = getPointerArithmeticOperandStatedValue ( arg2 ) and
0 commit comments