-
Notifications
You must be signed in to change notification settings - Fork 63
/
Copy pathRestrictPointerReferencesOverlappingObject.ql
85 lines (76 loc) · 3.45 KB
/
RestrictPointerReferencesOverlappingObject.ql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/**
* @id c/cert/restrict-pointer-references-overlapping-object
* @name EXP43-C: Do not assign the value of a restrict-qualified pointer to another restrict-qualified pointer
* @description Restrict qualified pointers referencing overlapping objects is undefined behavior.
* @kind problem
* @precision high
* @problem.severity error
* @tags external/cert/id/exp43-c
* correctness
* external/cert/obligation/rule
*/
import cpp
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.controlflow.Dominance
import codingstandards.c.cert
import codingstandards.cpp.Variable
/**
* An `Expr` that is an assignment or initialization to a restrict-qualified pointer-type variable.
*/
class AssignmentOrInitializationToRestrictPtrValueExpr extends Expr {
Variable v;
AssignmentOrInitializationToRestrictPtrValueExpr() {
this = v.getAnAssignedValue() and
v.getType().hasSpecifier("restrict")
}
Variable getVariable() { result = v }
predicate isTargetRestrictQualifiedAndInSameScope() {
this.(VariableAccess).getTarget().getType().hasSpecifier("restrict") and
this.(VariableAccess).getTarget().getParentScope() = this.getVariable().getParentScope()
}
}
/**
* A data-flow configuration for tracking flow from an assignment or initialization to
* an assignment to an `AssignmentOrInitializationToRestrictPtrValueExpr`.
*/
module AssignedValueToRestrictPtrValueConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(Variable v | source.asExpr() = v.getAnAssignedValue())
}
predicate isSink(DataFlow::Node sink) {
sink.asExpr() instanceof AssignmentOrInitializationToRestrictPtrValueExpr
}
}
module AssignedValueToRestrictPtrValueFlow =
DataFlow::Global<AssignedValueToRestrictPtrValueConfig>;
from
AssignmentOrInitializationToRestrictPtrValueExpr expr, DataFlow::Node sourceValue,
string sourceMessage
where
not isExcluded(expr, Pointers3Package::restrictPointerReferencesOverlappingObjectQuery()) and
(
// Two restrict-qualified pointers in the same scope assigned to each other
expr.isTargetRestrictQualifiedAndInSameScope() and
sourceValue.asExpr() = expr and
sourceMessage = "the object pointed to by " + expr.(VariableAccess).getTarget().getName()
or
// If the same expressions flows to two unique `AssignmentOrInitializationToRestrictPtrValueExpr`
// in the same block, then the two variables point to the same (overlapping) object
not expr.isTargetRestrictQualifiedAndInSameScope() and
exists(AssignmentOrInitializationToRestrictPtrValueExpr pre_expr |
expr.getEnclosingBlock() = pre_expr.getEnclosingBlock() and
(
AssignedValueToRestrictPtrValueFlow::flow(sourceValue, DataFlow::exprNode(pre_expr)) and
AssignedValueToRestrictPtrValueFlow::flow(sourceValue, DataFlow::exprNode(expr)) and
sourceMessage = "the same source value"
or
// Expressions referring to the address of the same variable can also result in aliasing
getAddressOfExprTargetBase(expr) = getAddressOfExprTargetBase(pre_expr) and
sourceValue.asExpr() = pre_expr and
sourceMessage = getAddressOfExprTargetBase(expr).getName() + " via address-of"
) and
strictlyDominates(pragma[only_bind_out](pre_expr), pragma[only_bind_out](expr))
)
)
select expr, "Assignment to restrict-qualified pointer $@ results in pointers aliasing $@.",
expr.getVariable(), expr.getVariable().getName(), sourceValue, sourceMessage