Skip to content

Commit 230aa6e

Browse files
authored
Merge branch 'main' into lcartey/m5-3-3
2 parents dc33205 + e204fc4 commit 230aa6e

23 files changed

+500
-154
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
`A4-7-1`: `IntegerExpressionLeadToDataLoss.ql`
2+
- Fix #368: Incorrectly reporting `/=` as a cause for data loss.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
`A16-0-1` - `PreProcessorShallOnlyBeUsedForCertainDirectivesPatterns.ql`:
2+
- Exclude all preprocessor elses and also consider elifs separately (ie do not affect valid ifs) but not valid if not meeting the same criteria as an ifdef etc.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
`A4-5-1`: `EnumUsedInArithmeticContexts.ql`:
2+
- Address incorrect exclusion of the binary operator `&`.
3+
- Address incorrect inclusion of the unary operator `&`.
4+
- Fix FP reported in #366.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
`A7-1-2` - `VariableMissingConstexpr.ql`:
2+
- Fix FP reported in #466. Addresses incorrect assumption that calls to `constexpr` functions are always compile-time evaluated.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- `M7-3-6` - `UsingDeclarationsUsedInHeaderFiles.ql`:
2+
- Address FN reported in #400. Only using-declarations are exempted from class- and function-scope.

cpp/autosar/src/rules/A16-0-1/PreProcessorShallOnlyBeUsedForCertainDirectivesPatterns.ql

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,26 @@ import cpp
2121
import codingstandards.cpp.autosar
2222
import codingstandards.cpp.FunctionLikeMacro
2323

24+
class PermittedInnerDirectiveType extends PreprocessorDirective {
25+
PermittedInnerDirectiveType() {
26+
//permissive listing for directives that can be used in a valid wrapper
27+
this instanceof MacroWrapper or
28+
this instanceof PreprocessorEndif or
29+
this instanceof Include or
30+
this instanceof PermittedMacro or
31+
this instanceof PreprocessorElif or
32+
this instanceof PreprocessorElse
33+
}
34+
}
35+
2436
class PermittedDirectiveType extends PreprocessorDirective {
2537
PermittedDirectiveType() {
2638
//permissive listing in case directive types modelled in ql ever expands (example non valid directives)
2739
this instanceof MacroWrapper or
2840
this instanceof PreprocessorEndif or
2941
this instanceof Include or
30-
this instanceof PermittedMacro
42+
this instanceof PermittedMacro or
43+
this instanceof PreprocessorElse
3144
}
3245
}
3346

@@ -40,9 +53,9 @@ pragma[noinline]
4053
predicate isPreprocConditionalRange(
4154
PreprocessorBranch pb, string filepath, int startLine, int endLine
4255
) {
43-
exists(PreprocessorEndif end | pb.getEndIf() = end |
44-
isPreprocFileAndLine(pb, filepath, startLine) and
45-
isPreprocFileAndLine(end, filepath, endLine)
56+
isPreprocFileAndLine(pb, filepath, startLine) and
57+
exists(PreprocessorDirective end |
58+
pb.getNext() = end and isPreprocFileAndLine(end, filepath, endLine)
4659
)
4760
}
4861

@@ -73,7 +86,7 @@ class MacroWrapper extends PreprocessorIfndef {
7386
class AcceptableWrapper extends PreprocessorBranch {
7487
AcceptableWrapper() {
7588
forall(Element inner | not inner instanceof Comment and this = getAGuard(inner) |
76-
inner instanceof PermittedDirectiveType
89+
inner instanceof PermittedInnerDirectiveType
7790
)
7891
}
7992
}

cpp/autosar/src/rules/A4-5-1/EnumUsedInArithmeticContexts.ql

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,44 +18,26 @@
1818

1919
import cpp
2020
import codingstandards.cpp.autosar
21+
import codingstandards.cpp.Operator
22+
import codingstandards.cpp.Type
2123

22-
/*
23-
* Get an operand to all overloaded operator member functions, except:
24-
* operator[]
25-
* operator=
26-
* operator==
27-
* operator!=
28-
* operator&
29-
* operator<
30-
* operator<=
31-
* operator>
32-
* operator>=
33-
*/
34-
35-
Expr getAnOperandOfAllowedOverloadedOperator(FunctionCall fc) {
36-
fc.getAnArgument() = result and
37-
fc.getTarget().getName().regexpMatch("operator(?!\\[]$|=$|==$|!=$|&$|<$|<=$|>$|>=$).+")
38-
}
39-
40-
Expr getAnOperandOfAllowedOperation(Operation o) {
41-
o.getAnOperand() = result and
42-
not (
43-
o instanceof AssignExpr or
44-
o instanceof BitwiseAndExpr or
45-
o instanceof ComparisonOperation
46-
)
24+
class AllowedOperatorUse extends OperatorUse {
25+
AllowedOperatorUse() {
26+
this.getOperator() in ["[]", "=", "==", "!=", "<", "<=", ">", ">="]
27+
or
28+
this.(UnaryOperatorUse).getOperator() = "&"
29+
}
4730
}
4831

49-
from Expr e, Expr operand
32+
from OperatorUse operatorUse, Access access, Enum enum
5033
where
51-
not isExcluded(e, ExpressionsPackage::enumUsedInArithmeticContextsQuery()) and
34+
not isExcluded(access, ExpressionsPackage::enumUsedInArithmeticContextsQuery()) and
35+
operatorUse.getAnOperand() = access and
5236
(
53-
operand = getAnOperandOfAllowedOverloadedOperator(e)
54-
or
55-
operand = getAnOperandOfAllowedOperation(e)
37+
access.(EnumConstantAccess).getTarget().getDeclaringEnum() = enum or
38+
access.(VariableAccess).getType() = enum
5639
) and
57-
(
58-
operand instanceof EnumConstantAccess or
59-
operand.(VariableAccess).getType() instanceof Enum
60-
)
61-
select e, "Enum $@ is used as an operand of arithmetic operation.", operand, "expression"
40+
not operatorUse instanceof AllowedOperatorUse and
41+
// Enums that implement the BitmaskType trait are an exception.
42+
not enum instanceof BitmaskType
43+
select access, "Enum $@ is used as an operand of arithmetic operation.", enum, enum.getName()

cpp/autosar/src/rules/A4-7-1/IntegerExpressionLeadToDataLoss.ql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,7 @@ where
3030
not e instanceof MulExpr and
3131
// Not covered by this query - overflow/underflow in division is rare
3232
not e instanceof DivExpr and
33-
not e instanceof RemExpr
33+
not e instanceof AssignDivExpr and
34+
not e instanceof RemExpr and
35+
not e instanceof AssignRemExpr
3436
select e, "Binary expression ..." + e.getOperator() + "... may overflow."

cpp/autosar/src/rules/A7-1-2/VariableMissingConstexpr.ql

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import cpp
1717
import codingstandards.cpp.autosar
1818
import codingstandards.cpp.TrivialType
1919
import codingstandards.cpp.SideEffect
20+
import semmle.code.cpp.controlflow.SSA
2021

2122
predicate isZeroInitializable(Variable v) {
2223
not exists(v.getInitializer().getExpr()) and
@@ -33,6 +34,78 @@ predicate isTypeZeroInitializable(Type t) {
3334
t.getUnderlyingType() instanceof ArrayType
3435
}
3536

37+
/**
38+
* An optimized set of expressions used to determine the flow through constexpr variables.
39+
*/
40+
class VariableAccessOrCallOrLiteral extends Expr {
41+
VariableAccessOrCallOrLiteral() {
42+
this instanceof VariableAccess or
43+
this instanceof Call or
44+
this instanceof Literal
45+
}
46+
}
47+
48+
/**
49+
* Holds if the value of source flows through compile time evaluated variables to target.
50+
*/
51+
predicate flowsThroughConstExprVariables(
52+
VariableAccessOrCallOrLiteral source, VariableAccessOrCallOrLiteral target
53+
) {
54+
(
55+
source = target
56+
or
57+
source != target and
58+
exists(SsaDefinition intermediateDef, StackVariable intermediate |
59+
intermediateDef.getAVariable().getFunction() = source.getEnclosingFunction() and
60+
intermediateDef.getAVariable().getFunction() = target.getEnclosingFunction() and
61+
intermediateDef.getAVariable() = intermediate and
62+
intermediate.isConstexpr()
63+
|
64+
DataFlow::localExprFlow(source, intermediateDef.getDefiningValue(intermediate)) and
65+
flowsThroughConstExprVariables(intermediateDef.getAUse(intermediate), target)
66+
)
67+
)
68+
}
69+
70+
/*
71+
* Returns true if the given call may be evaluated at compile time and is compile time evaluated because
72+
* all its arguments are compile time evaluated and its default values are compile time evaluated.
73+
*/
74+
75+
predicate isCompileTimeEvaluated(Call call) {
76+
// 1. The call may be evaluated at compile time, because it is constexpr, and
77+
call.getTarget().isConstexpr() and
78+
// 2. all its arguments are compile time evaluated, and
79+
forall(DataFlow::Node ultimateArgSource, DataFlow::Node argSource |
80+
argSource = DataFlow::exprNode(call.getAnArgument()) and
81+
DataFlow::localFlow(ultimateArgSource, argSource) and
82+
not DataFlow::localFlowStep(_, ultimateArgSource)
83+
|
84+
(
85+
ultimateArgSource.asExpr() instanceof Literal
86+
or
87+
any(Call c | isCompileTimeEvaluated(c)) = ultimateArgSource.asExpr()
88+
) and
89+
// If the ultimate argument source is not the same as the argument source, then it must flow through
90+
// constexpr variables.
91+
(
92+
ultimateArgSource != argSource
93+
implies
94+
flowsThroughConstExprVariables(ultimateArgSource.asExpr(), argSource.asExpr())
95+
)
96+
) and
97+
// 3. all the default values used are compile time evaluated.
98+
forall(Expr defaultValue, Parameter parameterUsingDefaultValue, int idx |
99+
parameterUsingDefaultValue = call.getTarget().getParameter(idx) and
100+
not exists(call.getArgument(idx)) and
101+
parameterUsingDefaultValue.getAnAssignedValue() = defaultValue
102+
|
103+
defaultValue instanceof Literal
104+
or
105+
any(Call c | isCompileTimeEvaluated(c)) = defaultValue
106+
)
107+
}
108+
36109
from Variable v
37110
where
38111
not isExcluded(v, ConstPackage::variableMissingConstexprQuery()) and
@@ -46,7 +119,7 @@ where
46119
(
47120
v.getInitializer().getExpr().isConstant()
48121
or
49-
v.getInitializer().getExpr().(Call).getTarget().isConstexpr()
122+
any(Call call | isCompileTimeEvaluated(call)) = v.getInitializer().getExpr()
50123
or
51124
isZeroInitializable(v)
52125
or

cpp/autosar/src/rules/M7-3-6/UsingDeclarationsUsedInHeaderFiles.ql

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,13 @@ predicate isInClassScope(UsingEntry u) { exists(Class c | u.getEnclosingElement(
2828
from UsingEntry u
2929
where
3030
not isExcluded(u, BannedSyntaxPackage::usingDeclarationsUsedInHeaderFilesQuery()) and
31-
(isInHeaderFile(u) and not isInFunctionScope(u) and not isInClassScope(u))
31+
isInHeaderFile(u) and
32+
(
33+
u instanceof UsingDeclarationEntry
34+
implies
35+
(
36+
not isInFunctionScope(u) and
37+
not isInClassScope(u)
38+
)
39+
)
3240
select u, "Using directive or declaration used in a header file " + u.getFile() + "."

0 commit comments

Comments
 (0)