1616
1717import cpp
1818import codingstandards.cpp.autosar
19- import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
20- import codingstandards.cpp.deadcode.UnreachableCode
21- import semmle.code.cpp.controlflow.Guards
22-
23- /**
24- * A "conditional" node in the control flow graph, i.e. one that can potentially have a true and false path.
25- */
26- class ConditionalControlFlowNode extends ControlFlowNode {
27- ConditionalControlFlowNode ( ) {
28- // A conditional node is one with at least one of a true or false successor
29- ( exists ( getATrueSuccessor ( ) ) or exists ( getAFalseSuccessor ( ) ) ) and
30- // Ignore conditions affected by macros, as they may include deliberate infeasible paths, or
31- // paths which are only feasible in certain macro expansions
32- not isAffectedByMacro ( )
33- }
34- }
19+ import codingstandards.cpp.rules.invariantcondition.InvariantCondition
3520
3621/**
3722 * A `Loop` that contains a `break` statement.
@@ -40,132 +25,21 @@ class BreakingLoop extends Loop {
4025 BreakingLoop ( ) { exists ( BreakStmt break | this = break .getBreakable ( ) ) }
4126}
4227
43- /**
44- * Holds if the `ConditionalNode` has an infeasible `path` according to the control flow graph library.
45- */
46- predicate hasCFGDeducedInfeasiblePath (
47- ConditionalControlFlowNode cond , boolean infeasiblePath , string explanation
48- ) {
49- not cond .isFromTemplateInstantiation ( _) and
50- // No true successor, so the true path has already been deduced as infeasible
51- not exists ( cond .getATrueSuccessor ( ) ) and
52- infeasiblePath = true and
53- explanation = "this expression consists of constants which evaluate to false"
54- or
55- // No false successor, so false path has already been deduced as infeasible
56- not exists ( cond .getAFalseSuccessor ( ) ) and
57- not cond .getEnclosingStmt ( ) instanceof BreakingLoop and
58- infeasiblePath = false and
59- explanation = "this expression consists of constants which evaluate to true"
60- }
61-
62- predicate isConstantRelationalOperation (
63- RelationalOperation rel , boolean infeasiblePath , string explanation
64- ) {
65- /*
66- * This predicate identifies a number of a cases where we can conclusive determine that a relational
67- * operation will always return true or false, based on the ranges for each operand as determined
68- * by the SimpleRangeAnalysis library (and any extensions provide in the Coding Standards library).
69- *
70- * Important note: in order to deduce that an relational operation _always_ returns true or false,
71- * we must ensure that it returns true or false for _all_ possible values of the operands. For
72- * example, it may be tempting to look at this relational operation on these ranges:
73- * ```
74- * [0..5] < [0..10]
75- * ```
76- * And say that ub(lesser) < ub(greater) and therefore it is `true`, however this is not the case
77- * for all permutations (e.g. 5 < 0).
78- *
79- * Instead, we look at all four permutations of these two dimensions:
80- * - Equal-to or not equal-to
81- * - Always true or always false
82- */
28+ module AutosarConfig implements InvariantConditionConfigSig {
29+ Query getQuery ( ) { result = DeadCodePackage:: infeasiblePathQuery ( ) }
8330
84- // This restricts the comparison to occur directly within the conditional node
85- // In theory we could also extend this to identify comparisons where the result is stored, then
86- // later read in a conditional control flow node within the same function (using SSA)
87- // Doing so would benefit from path explanations, but would require a more complex analysis
88- rel instanceof ConditionalControlFlowNode and
89- // If at least one operand includes an access of a volatile variable, the range analysis library may
90- // provide inaccurate results, so we ignore this case
91- not rel .getAnOperand ( ) .getAChild * ( ) .( VariableAccess ) .getTarget ( ) .isVolatile ( ) and
92- exists ( boolean isEqual |
93- if
94- rel instanceof GEExpr
95- or
96- rel instanceof LEExpr
97- then isEqual = true
98- else isEqual = false
99- |
100- // Not equal-to/always true
101- // If the largest value of the lesser operand is less than the smallest value of the greater
102- // operand, then the LT/GT comparison is always true
103- // Example: [0..5] < [6..10]
104- upperBound ( rel .getLesserOperand ( ) ) < lowerBound ( rel .getGreaterOperand ( ) ) and
105- explanation =
106- rel .getLesserOperand ( ) + " (max value: " + upperBound ( rel .getLesserOperand ( ) ) +
107- ") is always less than " + rel .getGreaterOperand ( ) + " (minimum value: " +
108- lowerBound ( rel .getGreaterOperand ( ) ) + ")" and
109- isEqual = false and
110- infeasiblePath = false
111- or
112- // Equal-to/always true
113- // If the largest value of the lesser operand is less than or equal to the smallest value of the
114- // greater operand, then the LTE/GTE comparison is always true
115- // Example: [0..6] <= [6..10]
116- upperBound ( rel .getLesserOperand ( ) ) <= lowerBound ( rel .getGreaterOperand ( ) ) and
117- explanation =
118- rel .getLesserOperand ( ) + " (max value: " + upperBound ( rel .getLesserOperand ( ) ) +
119- ") is always less than or equal to " + rel .getGreaterOperand ( ) + " (minimum value: " +
120- lowerBound ( rel .getGreaterOperand ( ) ) + ")" and
121- isEqual = true and
122- infeasiblePath = false
123- or
124- // Equal to/always false
125- // If the largest value of the greater operand is less than the smallest value of the lesser
126- // operand, then the LTE/GTE comparison is always false
127- // Example: [6..10] <= [0..5]
128- upperBound ( rel .getGreaterOperand ( ) ) < lowerBound ( rel .getLesserOperand ( ) ) and
129- explanation =
130- rel .getGreaterOperand ( ) + " (max value: " + upperBound ( rel .getGreaterOperand ( ) ) +
131- ") is always less than " + rel .getLesserOperand ( ) + " (minimum value: " +
132- lowerBound ( rel .getLesserOperand ( ) ) + ")" and
133- isEqual = true and
134- infeasiblePath = true
31+ predicate isException ( ControlFlowNode node ) {
32+ node .getEnclosingElement ( ) instanceof BreakingLoop and
33+ exists ( node .getATrueSuccessor ( ) )
13534 or
136- // Equal to/always true
137- // If the largest value of the greater operand is less than or equal to the smallest value of the
138- // lesser operand, then the LT/GT comparison is always false
139- // Example: [6..10] < [0..6]
140- upperBound ( rel .getGreaterOperand ( ) ) <= lowerBound ( rel .getLesserOperand ( ) ) and
141- explanation =
142- rel .getGreaterOperand ( ) + " (max value: " + upperBound ( rel .getGreaterOperand ( ) ) +
143- ") is always less than or equal to " + rel .getLesserOperand ( ) + " (minimum value: " +
144- lowerBound ( rel .getLesserOperand ( ) ) + ")" and
145- isEqual = false and
146- infeasiblePath = true
147- )
148- }
149-
150- /**
151- * Holds if the `ConditionalNode` has an infeasible `path` for the reason given in `explanation`.
152- */
153- predicate hasInfeasiblePath ( ConditionalControlFlowNode node , string message ) {
154- exists ( boolean infeasiblePath , string explanation |
155- not node .isFromTemplateInstantiation ( _) and
156- if node .isFromUninstantiatedTemplate ( _)
157- then message = "The path is unreachable in a template."
158- else message = "The " + infeasiblePath + " path is infeasible because " + explanation + "."
159- |
160- hasCFGDeducedInfeasiblePath ( node , infeasiblePath , explanation ) and
161- not isConstantRelationalOperation ( node , infeasiblePath , _)
35+ // Ignore conditions affected by macros, as they may include deliberate infeasible paths, or
36+ // paths which are only feasible in certain macro expansions
37+ node .isAffectedByMacro ( )
16238 or
163- isConstantRelationalOperation ( node , infeasiblePath , explanation )
164- )
39+ // Only consider reachability in uninstantiated templates, to avoid false positives
40+ node .isFromTemplateInstantiation ( _)
41+ }
16542}
16643
167- from ConditionalControlFlowNode cond , string explanation
168- where
169- not isExcluded ( cond , DeadCodePackage:: infeasiblePathQuery ( ) ) and
170- hasInfeasiblePath ( cond , explanation )
171- select cond , explanation
44+ // Import the problems query predicate
45+ import InvariantCondition< AutosarConfig >
0 commit comments