11/**
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
33 * @name EXP43-C: Do not pass aliased pointers to restrict-qualified parameters
44 * @description Passing an aliased pointer to a restrict-qualified parameter is undefined behavior.
55 * @kind problem
1313import cpp
1414import codingstandards.c.cert
1515import codingstandards.c.Pointers
16- import semmle.code.cpp.dataflow.DataFlow
16+ import codingstandards.c.Variable
17+ import semmle.code.cpp.ir.dataflow.DataFlow
1718import semmle.code.cpp.pointsto.PointsTo
1819import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
1920
@@ -67,10 +68,9 @@ class CallToFunctionWithRestrictParameters extends FunctionCall {
6768/**
6869 * A `PointsToExpr` that is an argument of a pointer-type in a `CallToFunctionWithRestrictParameters`
6970 */
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 ( )
7474 }
7575}
7676
@@ -82,7 +82,7 @@ int getStatedValue(Expr e) {
8282 .minimum ( min ( Expr source | DataFlow:: localExprFlow ( source , e ) | source .getValue ( ) .toInt ( ) ) )
8383}
8484
85- int getPointerArithmeticOperandStatedValue ( ArgPointsToExpr expr ) {
85+ int getPointerArithmeticOperandStatedValue ( CallToFunctionWithRestrictParametersArgExpr expr ) {
8686 result = getStatedValue ( expr .( PointerArithmeticExpr ) .getOperand ( ) )
8787 or
8888 // edge-case: &(array[index]) expressions
@@ -94,18 +94,37 @@ int getPointerArithmeticOperandStatedValue(ArgPointsToExpr expr) {
9494 result = 0
9595}
9696
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+
97109from
98- CallToFunctionWithRestrictParameters call , ArgPointsToExpr arg1 , ArgPointsToExpr arg2 ,
99- int argOffset1 , int argOffset2
110+ CallToFunctionWithRestrictParameters call , CallToFunctionWithRestrictParametersArgExpr arg1 ,
111+ CallToFunctionWithRestrictParametersArgExpr arg2 , int argOffset1 , int argOffset2
100112where
101- not isExcluded ( call , Pointers3Package:: doNotPassAlisedPointerToRestrictQualifiedParameterQuery ( ) ) and
113+ not isExcluded ( call , Pointers3Package:: doNotPassAliasedPointerToRestrictQualifiedParamQuery ( ) ) and
102114 arg1 = call .getARestrictPtrArg ( ) and
103115 arg2 = call .getAPtrArg ( ) and
104- // two arguments that point to the same object
105116 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
109128 // get the offset of the pointer arithmetic operand (or '0' if there is none)
110129 argOffset1 = getPointerArithmeticOperandStatedValue ( arg1 ) and
111130 argOffset2 = getPointerArithmeticOperandStatedValue ( arg2 ) and
0 commit comments