@@ -16,33 +16,53 @@ import cpp
16
16
import codingstandards.c.misra
17
17
18
18
/**
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.
22
23
*/
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 ( )
39
42
)
40
43
}
44
+
45
+ VlaDeclStmt getVlaDeclStmt ( ) { result = vlaDecl }
46
+
47
+ ArrayType getArrayType ( ) { result = arrayType }
41
48
}
42
49
43
- from VariableLengthArray v
50
+ from Variable v , Expr size , ArrayType arrayType , VlaDeclStmt vlaDecl , string typeStr
44
51
where
45
52
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 ( )
0 commit comments