Skip to content

Commit 2623c22

Browse files
authored
Merge branch 'main' into rp/fix-796
2 parents 5518a97 + 5c5bb64 commit 2623c22

File tree

47 files changed

+1517
-55
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1517
-55
lines changed

amendments.csv

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ c,MISRA-C-2012,Amendment4,RULE-11-3,Yes,Expand,No,Easy
1515
c,MISRA-C-2012,Amendment4,RULE-11-8,Yes,Expand,No,Easy
1616
c,MISRA-C-2012,Amendment4,RULE-13-2,Yes,Expand,No,Very Hard
1717
c,MISRA-C-2012,Amendment4,RULE-18-6,Yes,Expand,No,Medium
18-
c,MISRA-C-2012,Amendment4,RULE-18-8,Yes,Split,No,Easy
18+
c,MISRA-C-2012,Amendment4,RULE-18-8,Yes,Split,Yes,Easy
1919
c,MISRA-C-2012,Corrigendum2,RULE-2-2,Yes,Clarification,No,Import
2020
c,MISRA-C-2012,Corrigendum2,RULE-2-7,Yes,Clarification,No,Import
2121
c,MISRA-C-2012,Corrigendum2,RULE-3-1,Yes,Refine,No,Easy

c/cert/src/rules/EXP35-C/DoNotModifyObjectsWithTemporaryLifetime.ql

+1-12
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,7 @@
1313

1414
import cpp
1515
import codingstandards.c.cert
16-
17-
/**
18-
* A struct or union type that contains an array type
19-
*/
20-
class StructOrUnionTypeWithArrayField extends Struct {
21-
StructOrUnionTypeWithArrayField() {
22-
this.getAField().getUnspecifiedType() instanceof ArrayType
23-
or
24-
// nested struct or union containing an array type
25-
this.getAField().getUnspecifiedType().(Struct) instanceof StructOrUnionTypeWithArrayField
26-
}
27-
}
16+
import codingstandards.cpp.lifetimes.CLifetimes
2817

2918
// Note: Undefined behavior is possible regardless of whether the accessed field from the returned
3019
// struct is an array or a scalar (i.e. arithmetic and pointer types) member, according to the standard.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* @id c/misra/pointers-to-variably-modified-array-types-used
3+
* @name RULE-18-10: Pointers to variably-modified array types shall not be used
4+
* @description Pointers to variably-modified array types shall not be used, as these pointer types
5+
* are frequently incompatible with other fixed or variably sized arrays, resulting in
6+
* undefined behavior.
7+
* @kind problem
8+
* @precision high
9+
* @problem.severity error
10+
* @tags external/misra/id/rule-18-10
11+
* external/misra/c/2012/amendment4
12+
* correctness
13+
* security
14+
* external/misra/obligation/mandatory
15+
*/
16+
17+
import cpp
18+
import codingstandards.c.misra
19+
import codingstandards.cpp.VariablyModifiedTypes
20+
21+
from VmtDeclarationEntry v, string declstr, string adjuststr, string relationstr
22+
where
23+
not isExcluded(v, InvalidMemory3Package::pointersToVariablyModifiedArrayTypesUsedQuery()) and
24+
// Capture only pointers to VLA types, not raw VLA types.
25+
not v.getVlaType() = v.getType() and
26+
(
27+
if v instanceof ParameterDeclarationEntry
28+
then declstr = "Parameter "
29+
else
30+
if v instanceof VariableDeclarationEntry
31+
then declstr = "Variable "
32+
else declstr = "Declaration "
33+
) and
34+
(
35+
if
36+
v instanceof ParameterDeclarationEntry and
37+
v.getType() instanceof ParameterAdjustedVariablyModifiedType
38+
then adjuststr = "adjusted to"
39+
else adjuststr = "declared with"
40+
) and
41+
(
42+
if v.getType().(PointerType).getBaseType() instanceof CandidateVlaType
43+
then relationstr = "pointer to"
44+
else relationstr = "with inner"
45+
) and
46+
// Remove results that appear to be unreliable, potentially from a macro.
47+
not v.appearsDuplicated()
48+
select v,
49+
declstr + v.getName() + " is " + adjuststr + " variably-modified type, " + relationstr +
50+
" variable length array of non constant size $@ and element type '" +
51+
v.getVlaType().getVariableBaseType() + "'", v.getSizeExpr(), v.getSizeExpr().toString()

c/misra/src/rules/RULE-18-8/VariableLengthArrayTypesUsed.ql

+43-23
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,53 @@ import cpp
1616
import codingstandards.c.misra
1717

1818
/**
19-
* A variable length array (VLA)
20-
* ie an array where the size
21-
* is not an integer constant expression
19+
* Typedefs may be declared as VLAs, eg, `typedef int vla[x];`. This query finds types that refer to
20+
* such typedef types, for instance `vla foo;` or adding a dimension via `vla bar[10];`.
21+
*
22+
* Consts and other specifiers may be added, but `vla *ptr;` is not a VLA any more, and is excluded.
2223
*/
23-
class VariableLengthArray extends VariableDeclarationEntry {
24-
VariableLengthArray() {
25-
//VLAs will not have: static/extern specifiers (compilation error)
26-
not this.hasSpecifier("static") and
27-
not this.hasSpecifier("extern") and
28-
//VLAs are not allowed to be initialized
29-
not this.getDeclaration().hasInitializer() and
30-
exists(ArrayType a |
31-
//a.hasArraySize() does not catch multidimensional VLAs like a[1][]
32-
a.toString().matches("%[]%") and
33-
this.getUnspecifiedType() = a and
34-
//variable length array is one declared in block or function prototype
35-
(
36-
this.getDeclaration().getParentScope() instanceof Function or
37-
this.getDeclaration().getParentScope() instanceof BlockStmt
38-
)
24+
class VlaTypedefType extends Type {
25+
VlaDeclStmt vlaDecl;
26+
ArrayType arrayType;
27+
28+
VlaTypedefType() {
29+
// Holds for direct references to the typedef type:
30+
this = vlaDecl.getType() and
31+
vlaDecl.getType() instanceof TypedefType and
32+
arrayType = vlaDecl.getType().stripTopLevelSpecifiers()
33+
or
34+
// Handle arrays of VLA typedefs, and carefully handle specified VLA typedef types, as
35+
// `stripTopLevelSpecifiers` resolves past the VLA typedef type.
36+
exists(DerivedType dt, VlaTypedefType vlaType |
37+
(dt instanceof ArrayType or dt instanceof SpecifiedType) and
38+
this = dt and
39+
vlaType = dt.getBaseType() and
40+
vlaDecl = vlaType.getVlaDeclStmt() and
41+
arrayType = vlaType.getArrayType()
3942
)
4043
}
44+
45+
VlaDeclStmt getVlaDeclStmt() { result = vlaDecl }
46+
47+
ArrayType getArrayType() { result = arrayType }
4148
}
4249

43-
from VariableLengthArray v
50+
from Variable v, Expr size, ArrayType arrayType, VlaDeclStmt vlaDecl, string typeStr
4451
where
4552
not isExcluded(v, Declarations7Package::variableLengthArrayTypesUsedQuery()) and
46-
//an exception, argv in : int main(int argc, char *argv[])
47-
not v.getDeclaration().getParentScope().(Function).hasName("main")
48-
select v, "Variable length array declared."
53+
size = vlaDecl.getVlaDimensionStmt(0).getDimensionExpr() and
54+
(
55+
// Holds is if v is a variable declaration:
56+
v = vlaDecl.getVariable() and
57+
arrayType = v.getType().stripTopLevelSpecifiers()
58+
or
59+
// Holds is if v is a typedef declaration:
60+
exists(VlaTypedefType typedef |
61+
v.getType() = typedef and
62+
arrayType = typedef.getArrayType() and
63+
vlaDecl = typedef.getVlaDeclStmt()
64+
)
65+
) and
66+
typeStr = arrayType.getBaseType().toString()
67+
select v, "Variable length array of element type '" + typeStr + "' with non-constant size $@.",
68+
size, size.toString()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* @id c/misra/array-to-pointer-conversion-of-temporary-object
3+
* @name RULE-18-9: An object with temporary lifetime shall not undergo array to pointer conversion
4+
* @description Modifying or accessing elements of an array with temporary lifetime that has been
5+
* converted to a pointer will result in undefined behavior.
6+
* @kind problem
7+
* @precision high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-18-9
10+
* external/misra/c/2012/amendment3
11+
* correctness
12+
* security
13+
* external/misra/obligation/required
14+
*/
15+
16+
import cpp
17+
import codingstandards.c.misra
18+
import codingstandards.cpp.lifetimes.CLifetimes
19+
20+
/**
21+
* Holds if the value of an expression is used or stored.
22+
*
23+
* For instance, `(x)` does not use any values, but `x + y` uses `x` and `y`.
24+
*
25+
* A pointer-to-array conversion does not need to be flagged if the result of
26+
* that conversion is not used or stored.
27+
*/
28+
predicate isUsedOrStored(Expr e) {
29+
e = any(Operation o).getAnOperand()
30+
or
31+
e = any(ConditionalExpr c).getCondition()
32+
or
33+
e = any(Call c).getAnArgument()
34+
or
35+
e = any(VariableDeclarationEntry d).getDeclaration().getInitializer().getExpr()
36+
or
37+
e = any(ClassAggregateLiteral l).getAFieldExpr(_)
38+
}
39+
40+
/**
41+
* Find expressions that defer their value directly to an inner expression
42+
* value.
43+
*
44+
* When an array is on the rhs of a comma expr, or in the then/else branch of a
45+
* ternary expr, and the result us used as a pointer, then the ArrayToPointer
46+
* conversion is marked inside comma expr/ternary expr, on the operands. These
47+
* conversions are only non-compliant if they flow into an operation or store.
48+
*
49+
* Full flow analysis with localFlowStep should not be necessary, and may cast a
50+
* wider net than needed for some queries, potentially resulting in false
51+
* positives.
52+
*/
53+
Expr temporaryObjectFlowStep(Expr e) {
54+
e = result.(CommaExpr).getRightOperand()
55+
or
56+
e = result.(ConditionalExpr).getThen()
57+
or
58+
e = result.(ConditionalExpr).getElse()
59+
}
60+
61+
from
62+
TemporaryLifetimeArrayAccess fa, TemporaryLifetimeExpr temporary,
63+
ArrayToPointerConversion conversion
64+
where
65+
not isExcluded(conversion, InvalidMemory3Package::arrayToPointerConversionOfTemporaryObjectQuery()) and
66+
fa.getTemporary() = temporary and
67+
conversion.getExpr() = fa and
68+
isUsedOrStored(temporaryObjectFlowStep*(conversion.getExpr()))
69+
select conversion, "Array to pointer conversion of array $@ from temporary object $@.",
70+
fa.getTarget(), fa.getTarget().getName(), temporary, temporary.toString()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* @id c/misra/modifiable-l-value-subscripted-with-temporary-lifetime
3+
* @name RULE-18-9: Usage of the subscript operator on an object with temporary lifetime shall not return a modifiable value
4+
* @description Modifying elements of an array with temporary lifetime will result in undefined
5+
* behavior.
6+
* @kind problem
7+
* @precision high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-18-9
10+
* external/misra/c/2012/amendment3
11+
* correctness
12+
* security
13+
* external/misra/obligation/required
14+
*/
15+
16+
import cpp
17+
import codingstandards.c.misra
18+
import codingstandards.cpp.lifetimes.CLifetimes
19+
20+
class TemporaryLifetimeArrayExpr extends ArrayExpr {
21+
TemporaryLifetimeArrayAccess member;
22+
Type elementType;
23+
24+
TemporaryLifetimeArrayExpr() {
25+
member = getArrayBase() and
26+
elementType = member.getType().(ArrayType).getBaseType()
27+
or
28+
exists(TemporaryLifetimeArrayExpr inner |
29+
inner = getArrayBase() and
30+
member = inner.getMember() and
31+
elementType = inner.getElementType().(ArrayType).getBaseType()
32+
)
33+
}
34+
35+
TemporaryLifetimeArrayAccess getMember() { result = member }
36+
37+
Type getElementType() { result = elementType }
38+
}
39+
40+
predicate usedAsModifiableLvalue(Expr expr) {
41+
exists(Assignment parent | parent.getLValue() = expr)
42+
or
43+
exists(CrementOperation parent | parent.getOperand() = expr)
44+
or
45+
exists(AddressOfExpr parent | parent.getOperand() = expr)
46+
or
47+
exists(FieldAccess parent | parent.getQualifier() = expr and usedAsModifiableLvalue(parent))
48+
}
49+
50+
from TemporaryLifetimeArrayExpr expr, TemporaryLifetimeArrayAccess member
51+
where
52+
not isExcluded(expr,
53+
InvalidMemory3Package::modifiableLValueSubscriptedWithTemporaryLifetimeQuery()) and
54+
member = expr.getMember() and
55+
not expr.isUnevaluated() and
56+
usedAsModifiableLvalue(expr)
57+
select expr,
58+
"Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ ",
59+
member, member.getTarget().getName(), member.getTemporary(), member.getTemporary().toString()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @id c/misra/redeclaration-of-object-with-unmatched-alignment
3+
* @name RULE-8-15: Alignment should match between all declarations of an object
4+
* @description All declarations of an object with an explicit alignment specification shall specify
5+
* the same alignment.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-8-15
10+
* external/misra/c/2012/amendment3
11+
* readability
12+
* maintainability
13+
* external/misra/obligation/required
14+
*/
15+
16+
import cpp
17+
import codingstandards.c.misra
18+
import semmle.code.cpp.valuenumbering.HashCons
19+
20+
predicate lexicallyEqual(AttributeArgument a, AttributeArgument b) {
21+
hashCons(a.getValueConstant()) = hashCons(b.getValueConstant()) or
22+
a.getValueType() = b.getValueType()
23+
}
24+
25+
from Attribute alignment, Attribute mismatched, string variable
26+
where
27+
not isExcluded(alignment, AlignmentPackage::redeclarationOfObjectWithUnmatchedAlignmentQuery()) and
28+
alignment.hasName("_Alignas") and
29+
mismatched.hasName("_Alignas") and
30+
exists(Variable v |
31+
v.getAnAttribute() = alignment and v.getAnAttribute() = mismatched and v.getName() = variable
32+
) and
33+
not lexicallyEqual(alignment.getArgument(0), mismatched.getArgument(0))
34+
select alignment,
35+
"Variable " + variable + " declared with lexically different _Alignof() values '$@' and '$@'.",
36+
alignment, alignment.getArgument(0).toString(), mismatched, mismatched.getArgument(0).toString()

0 commit comments

Comments
 (0)