From 59cc35c8bdff43afc9f3479461cfcf1f739b3870 Mon Sep 17 00:00:00 2001 From: Nikita Kraiouchkine Date: Thu, 2 Mar 2023 22:43:31 +0100 Subject: [PATCH 1/4] Implement RULE-9-2, RULE-9-3, RULE-9-4 --- ...acesToMatchAggregateTypeStructure.expected | 7 + ...izerBracesToMatchAggregateTypeStructure.ql | 2 + .../test.c | 55 ++++++++ ...rForAggregateOrUnionNotEnclosedInBraces.ql | 23 ++++ ...nitializedArrayWithExplicitInitializers.ql | 76 ++++++++++ ...dInitializationOfAggregateObjectElement.ql | 130 ++++++++++++++++++ ...ggregateOrUnionNotEnclosedInBraces.testref | 1 + ...izedArrayWithExplicitInitializers.expected | 6 + ...ializedArrayWithExplicitInitializers.qlref | 1 + c/misra/test/rules/RULE-9-3/test.c | 37 +++++ ...alizationOfAggregateObjectElement.expected | 4 + ...itializationOfAggregateObjectElement.qlref | 1 + c/misra/test/rules/RULE-9-4/test.c | 38 +++++ .../UseInitBracesToMatchTypeStructure.ql | 50 +------ .../UseInitBracesToMatchTypeStructure.qlref | 1 - .../UseInitBracesToMatchTypeStructure.testref | 1 + .../cpp/exclusions/c/Memory1.qll | 61 ++++++++ .../cpp/exclusions/c/RuleMetadata.qll | 3 + ...zerBracesToMatchAggregateTypeStructure.qll | 59 ++++++++ ...cesToMatchAggregateTypeStructure.expected} | 0 ...izerBracesToMatchAggregateTypeStructure.ql | 2 + .../test.cpp | 58 ++++++++ rule_packages/c/Memory1.json | 66 +++++++++ rule_packages/cpp/Initialization.json | 1 + 24 files changed, 638 insertions(+), 45 deletions(-) create mode 100644 c/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.expected create mode 100644 c/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.ql create mode 100644 c/common/test/rules/useinitializerbracestomatchaggregatetypestructure/test.c create mode 100644 c/misra/src/rules/RULE-9-2/InitializerForAggregateOrUnionNotEnclosedInBraces.ql create mode 100644 c/misra/src/rules/RULE-9-3/PartiallyInitializedArrayWithExplicitInitializers.ql create mode 100644 c/misra/src/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.ql create mode 100644 c/misra/test/rules/RULE-9-2/InitializerForAggregateOrUnionNotEnclosedInBraces.testref create mode 100644 c/misra/test/rules/RULE-9-3/PartiallyInitializedArrayWithExplicitInitializers.expected create mode 100644 c/misra/test/rules/RULE-9-3/PartiallyInitializedArrayWithExplicitInitializers.qlref create mode 100644 c/misra/test/rules/RULE-9-3/test.c create mode 100644 c/misra/test/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.expected create mode 100644 c/misra/test/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.qlref create mode 100644 c/misra/test/rules/RULE-9-4/test.c delete mode 100644 cpp/autosar/test/rules/M8-5-2/UseInitBracesToMatchTypeStructure.qlref create mode 100644 cpp/autosar/test/rules/M8-5-2/UseInitBracesToMatchTypeStructure.testref create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/c/Memory1.qll create mode 100644 cpp/common/src/codingstandards/cpp/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.qll rename cpp/{autosar/test/rules/M8-5-2/UseInitBracesToMatchTypeStructure.expected => common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.expected} (100%) create mode 100644 cpp/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.ql create mode 100644 cpp/common/test/rules/useinitializerbracestomatchaggregatetypestructure/test.cpp create mode 100644 rule_packages/c/Memory1.json diff --git a/c/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.expected b/c/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.expected new file mode 100644 index 0000000000..c95e3cc881 --- /dev/null +++ b/c/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.expected @@ -0,0 +1,7 @@ +| test.c:35:20:35:23 | {...} | Missing braces on aggregate literal of type int[2]$@ which is assigned to index 0 in $@. | file://:0:0:0:0 | int[2] | int[2] | test.c:35:18:35:42 | {...} | array of type int[4][2] | +| test.c:35:26:35:29 | {...} | Missing braces on aggregate literal of type int[2]$@ which is assigned to index 1 in $@. | file://:0:0:0:0 | int[2] | int[2] | test.c:35:18:35:42 | {...} | array of type int[4][2] | +| test.c:35:32:35:35 | {...} | Missing braces on aggregate literal of type int[2]$@ which is assigned to index 2 in $@. | file://:0:0:0:0 | int[2] | int[2] | test.c:35:18:35:42 | {...} | array of type int[4][2] | +| test.c:35:38:35:41 | {...} | Missing braces on aggregate literal of type int[2]$@ which is assigned to index 3 in $@. | file://:0:0:0:0 | int[2] | int[2] | test.c:35:18:35:42 | {...} | array of type int[4][2] | +| test.c:41:34:41:34 | {...} | Missing braces on aggregate literal of type int[2]$@ which is assigned to index 1 in $@. | file://:0:0:0:0 | int[2] | int[2] | test.c:41:18:41:35 | {...} | array of type int[2][2] | +| test.c:47:26:47:29 | {...} | Missing braces on aggregate literal of type $@ which is assigned to field $@. | test.c:4:10:4:10 | struct | struct | test.c:7:5:7:8 | m_s1 | m_s1 | +| test.c:47:26:47:29 | {...} | Missing braces on aggregate literal of type $@ which is assigned to field $@. | test.c:11:10:11:10 | struct | struct | test.c:7:5:7:8 | m_s1 | m_s1 | diff --git a/c/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.ql b/c/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.ql new file mode 100644 index 0000000000..b24a879bab --- /dev/null +++ b/c/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.useinitializerbracestomatchaggregatetypestructure.UseInitializerBracesToMatchAggregateTypeStructure diff --git a/c/common/test/rules/useinitializerbracestomatchaggregatetypestructure/test.c b/c/common/test/rules/useinitializerbracestomatchaggregatetypestructure/test.c new file mode 100644 index 0000000000..017889e9fa --- /dev/null +++ b/c/common/test/rules/useinitializerbracestomatchaggregatetypestructure/test.c @@ -0,0 +1,55 @@ +struct Foo { + int m_i1; + int m_i2; + struct { + int m_s1_i1; + int m_s1_i2; + } m_s1; +}; + +struct Bar { + struct { + int m_s1_i1; + int m_s1_i2; + } m_s1; + int m_i1; + int m_i2; +}; + +struct Baz { + int m_baz_i1; + int m_baz_i2; + struct Foo f; +}; + +struct StructNested { + int m_nested_i1; + int *m_nested_i2; + struct Baz m_baz; + int m_array[10]; +}; + +void test() { + int l01[4] = {1, 2, 3, 4}; // COMPLIANT + int l02[4][2] = {{1, 2}, {3, 4}, {3, 4}, {3, 4}}; // COMPLIANT + int l03[4][2] = {1, 2, 3, 4, 3, 4, 3, 4}; // NON_COMPLIANT - implied braces + int l04[4][2] = {0}; // COMPLIANT + int l06[4][2] = {{0}, {0}, {0}, {0}}; // COMPLIANT, nested zero initializer + int l08[4] = {1, 2}; // COMPLIANT, but missing explicit init + int l09[2][2] = {{1, 2}}; // COMPLIANT, but missing explicit init + int l10[2][2] = {{1, 2}, [1] = {0}}; // COMPLIANT + int l11[2][2] = {{1, 2}, [1] = 0}; // NON_COMPLIANT - implied braces + int l12[2][2] = {{1, 2}, [1][0] = 0, [1][1] = 0}; // COMPLIANT + int l13[2][2] = {{0}, [1][0] = 0}; // COMPLIANT + int l14[2][2] = { + {0}, [1][0] = 0, 0}; // NON_COMPLIANT[FALSE_NEGATIVE] - not all elements + // initialized with designated initializer + struct Foo f1 = {1, 2, 3, 4}; // NON_COMPLIANT - implied braces + struct Foo f2 = {1, 2, {3, 4}}; // COMPLIANT + struct Foo f3 = {0}; // COMPLIANT + struct Foo f4 = {0, 2}; // COMPLIANT, but missing explicit init + struct Foo f5 = {0, 2, {0}}; // COMPLIANT + struct Bar b1 = {0}; // COMPLIANT + struct Bar b2 = {{0}}; // COMPLIANT, but missing explicit init + struct StructNested n = {0}; // COMPLIANT +} \ No newline at end of file diff --git a/c/misra/src/rules/RULE-9-2/InitializerForAggregateOrUnionNotEnclosedInBraces.ql b/c/misra/src/rules/RULE-9-2/InitializerForAggregateOrUnionNotEnclosedInBraces.ql new file mode 100644 index 0000000000..4999527fc0 --- /dev/null +++ b/c/misra/src/rules/RULE-9-2/InitializerForAggregateOrUnionNotEnclosedInBraces.ql @@ -0,0 +1,23 @@ +/** + * @id c/misra/initializer-for-aggregate-or-union-not-enclosed-in-braces + * @name RULE-9-2: The initializer for an aggregate or union shall be enclosed in braces + * @description Using braces in initializers of objects and subobjects improves code readability and + * clarifies intent. + * @kind problem + * @precision high + * @problem.severity warning + * @tags external/misra/id/rule-9-2 + * maintainability + * readability + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.rules.useinitializerbracestomatchaggregatetypestructure.UseInitializerBracesToMatchAggregateTypeStructure + +class InitializerForAggregateOrUnionNotEnclosedInBracesQuery extends UseInitializerBracesToMatchAggregateTypeStructureSharedQuery { + InitializerForAggregateOrUnionNotEnclosedInBracesQuery() { + this = Memory1Package::initializerForAggregateOrUnionNotEnclosedInBracesQuery() + } +} diff --git a/c/misra/src/rules/RULE-9-3/PartiallyInitializedArrayWithExplicitInitializers.ql b/c/misra/src/rules/RULE-9-3/PartiallyInitializedArrayWithExplicitInitializers.ql new file mode 100644 index 0000000000..231520ce50 --- /dev/null +++ b/c/misra/src/rules/RULE-9-3/PartiallyInitializedArrayWithExplicitInitializers.ql @@ -0,0 +1,76 @@ +/** + * @id c/misra/partially-initialized-array-with-explicit-initializers + * @name RULE-9-3: Arrays shall not be partially initialized + * @description An array object or a subobject of an array shall be explicitly initialized if any + * other object in that array is explicitly initialized. + * @kind problem + * @precision high + * @problem.severity warning + * @tags external/misra/id/rule-9-3 + * maintainability + * readability + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.enhancements.AggregateLiteralEnhancements + +/** + * Holds if the aggregate literal has at least one explicit initializer, and at least one + * _missing_ explicit initializer, and not _only_ designated initializers. + */ +predicate isMissingExplicitInitializers(AggregateLiteral al) { + not al.isCompilerGenerated() and + not al.isAffectedByMacro() and + // Partially initialized, but not initialized with a leading zero (which is permitted) + isPartiallyValueInitialized(al) and + not isLeadingZeroInitialized(al) +} + +// note: this query is similar to M8-5-2: MissingExplicitInitializers.ql +// but, pursuant to Rule 9.3, only covers array initializers rather than all aggregates +from AggregateLiteral al, Type aggType, Element explanationElement, string explanationDescription +where + not isExcluded(al, Memory1Package::partiallyInitializedArrayWithExplicitInitializersQuery()) and + // The aggregate literal is missing at least one explicit initializer + isMissingExplicitInitializers(al) and + // Missing array initializer + exists(int arraySize, int minIndex, int maxIndex | + // Identify the size of the array with a missing initializer + arraySize = al.getType().getUnspecifiedType().(ArrayType).getArraySize() and + // Identify the smallest index missing an initialzer + minIndex = + min(int index | + index = [0 .. arraySize - 1] and ArrayAggregateLiterals::isValueInitialized(al, index) + | + index + ) and + // Identify the largest index missing an initialzer + maxIndex = + max(int index | + index = [0 .. arraySize - 1] and ArrayAggregateLiterals::isValueInitialized(al, index) + | + index + ) and + // Ensure that the maxIndex is the last array entry. If it's not, something is up with this + // database, and so we shouldn't report it (because you can only initialize trailing array + // values) + maxIndex = (arraySize - 1) and + // Nothing useful to point to as the explanation element, so let's just set it to the parent + // array + explanationElement = al and + ( + if minIndex = maxIndex + then + // Only one element missing + explanationDescription = "the element at index " + minIndex + else + // Multiple elements missing + explanationDescription = "the elements in the index range " + minIndex + " to " + maxIndex + ) + ) +select al, + "Aggregate literal for " + getAggregateTypeDescription(al, aggType) + + " is missing an explicit initializer for $@.", aggType, aggType.getName(), explanationElement, + explanationDescription diff --git a/c/misra/src/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.ql b/c/misra/src/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.ql new file mode 100644 index 0000000000..9816f83e75 --- /dev/null +++ b/c/misra/src/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.ql @@ -0,0 +1,130 @@ +/** + * @id c/misra/repeated-initialization-of-aggregate-object-element + * @name RULE-9-4: An element of an object shall not be initialized more than once + * @description Repeated initialization of an element in an object can lead to side-effects or may + * signal a logic error. + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-9-4 + * correctness + * maintainability + * readability + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.enhancements.AggregateLiteralEnhancements + +/** + * Gets the `n`th parent of `e`. + * If `n` is zero, the result is `e`. + */ +Expr getNthParent(Expr e, int n) { + if n = 0 then result = e else result = getNthParent(e.getParent(), n - 1) +} + +/** + * Returns a string representation of the index of `e` relative + * to the nested array aggregate literal structure it is contained in. + */ +string getNestedArrayIndexString(Expr e) { + result = + concat(int depth | + depth = [0 .. getMaxDepth(getRootAggregate(e.getParent()))] + | + "[" + + any(int elementIndex | + exists(ArrayAggregateLiteral parent | + parent = getNthParent(e, pragma[only_bind_into](depth + 1)) and + parent.getElementExpr(elementIndex) = getNthParent(e, pragma[only_bind_into](depth)) + ) + | + elementIndex + ).toString() + "]" + ) +} + +/** + * Returns the number of levels of nested `ArrayAggregateLiteral`s in `al`. + * If there are no nested array aggregate literals, the max depth of the `ArrayAggregateLiteral` is `0`. + */ +language[monotonicAggregates] +int getMaxDepth(ArrayAggregateLiteral al) { + if not exists(al.getElementExpr(_).(ArrayAggregateLiteral)) + then result = 0 + else result = 1 + max(Expr child | child = al.getElementExpr(_) | getMaxDepth(child)) +} + +// internal recursive predicate for `hasMultipleInitializerExprsForSameIndex` +predicate hasMultipleInitializerExprsForSameIndexInternal( + ArrayAggregateLiteral al1, ArrayAggregateLiteral al2, Expr out_al1_expr, Expr out_al2_expr +) { + exists(int shared_index, Expr al1_expr, Expr al2_expr | + // an `Expr` initializing an element of the same index in both `al1` and `al2` + shared_index = [0 .. al1.getArraySize() - 1] and + al1_expr = al1.getElementExpr(shared_index) and + al2_expr = al2.getElementExpr(shared_index) and + // but not the same `Expr` + not al1_expr = al2_expr and + ( + // case A - the children are not aggregate literals + // holds if `al1` and `al2` both hold for .getElement[sharedIndex] + not al1_expr instanceof ArrayAggregateLiteral and + out_al1_expr = al1_expr and + out_al2_expr = al2_expr + or + // case B - `al1` and `al2` both have an aggregate literal child at the same index, so recurse + hasMultipleInitializerExprsForSameIndexInternal(al1_expr, al2_expr, out_al1_expr, out_al2_expr) + ) + ) +} + +/** + * Holds if `expr1` and `expr2` both initialize the same array element of `root`. + */ +predicate hasMultipleInitializerExprsForSameIndex(ArrayAggregateLiteral root, Expr expr1, Expr expr2) { + hasMultipleInitializerExprsForSameIndexInternal(root, root, expr1, expr2) +} + +/** + * Holds if `expr1` and `expr2` both initialize the same field of `root`. + * + * The dbschema keyset for `aggregate_field_init` prevents referencing multiple `Expr` + * that initialize the same Field and are part of the same `ClassAggregateLiteral`. + * This predicate is therefore unable to distinguish the individual duplicate expressions. + */ +predicate hasMultipleInitializerExprsForSameField(ClassAggregateLiteral root, Expr expr, Field f) { + expr = root.getFieldExpr(f) and + count(root.getFieldExpr(f)) > 1 +} + +from + AggregateLiteral root, Expr e1, Expr e2, string elementDescription, string rootType, + string clarification +where + not isExcluded(e1, Memory1Package::repeatedInitializationOfAggregateObjectElementQuery()) and + exists(Initializer init | init.getExpr() = root) and + ( + hasMultipleInitializerExprsForSameIndex(root, e1, e2) and + elementDescription = getNestedArrayIndexString(e1) and + rootType = "Array aggregate literal" and + clarification = ", which is already initialized $@." + or + exists(Field f | + // we cannot distinguish between different aggregate field init expressions. + // therefore, we only report the root aggregate rather than any child init expr. + // see `hasMultipleInitializerExprsForSameField` documentation. + hasMultipleInitializerExprsForSameField(root, _, f) and + e1 = root and + e2 = root and + elementDescription = f.getQualifiedName() and + rootType = "Structure aggregate literal" and + clarification = "." + ) + ) and + // de-duplicate the results by excluding permutations of `e1` and `e2` + e1.getLocation().toString() <= e2.getLocation().toString() +select e1, "$@ repeats initialization of element " + elementDescription + clarification, root, + rootType, e2, "here" diff --git a/c/misra/test/rules/RULE-9-2/InitializerForAggregateOrUnionNotEnclosedInBraces.testref b/c/misra/test/rules/RULE-9-2/InitializerForAggregateOrUnionNotEnclosedInBraces.testref new file mode 100644 index 0000000000..91bc9e1c63 --- /dev/null +++ b/c/misra/test/rules/RULE-9-2/InitializerForAggregateOrUnionNotEnclosedInBraces.testref @@ -0,0 +1 @@ +c/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-9-3/PartiallyInitializedArrayWithExplicitInitializers.expected b/c/misra/test/rules/RULE-9-3/PartiallyInitializedArrayWithExplicitInitializers.expected new file mode 100644 index 0000000000..25774b2d25 --- /dev/null +++ b/c/misra/test/rules/RULE-9-3/PartiallyInitializedArrayWithExplicitInitializers.expected @@ -0,0 +1,6 @@ +| test.c:7:15:7:21 | {...} | Aggregate literal for type int[4]$@ is missing an explicit initializer for $@. | file://:0:0:0:0 | int[4] | int[4] | test.c:7:15:7:21 | {...} | the elements in the index range 2 to 3 | +| test.c:8:18:8:26 | {...} | Aggregate literal for type int[2][2]$@ is missing an explicit initializer for $@. | file://:0:0:0:0 | int[2][2] | int[2][2] | test.c:8:18:8:26 | {...} | the element at index 1 | +| test.c:12:18:12:35 | {...} | Aggregate literal for type int[2][2]$@ is missing an explicit initializer for $@. | file://:0:0:0:0 | int[2][2] | int[2][2] | test.c:12:18:12:35 | {...} | the element at index 1 | +| test.c:14:18:15:25 | {...} | Aggregate literal for type int[2][2]$@ is missing an explicit initializer for $@. | file://:0:0:0:0 | int[2][2] | int[2][2] | test.c:14:18:15:25 | {...} | the element at index 1 | +| test.c:20:18:20:32 | {...} | Aggregate literal for type int[2][2]$@ is missing an explicit initializer for $@. | file://:0:0:0:0 | int[2][2] | int[2][2] | test.c:20:18:20:32 | {...} | the element at index 1 | +| test.c:31:43:31:43 | {...} | Aggregate literal for type int[4]$@ is missing an explicit initializer for $@. | file://:0:0:0:0 | int[4] | int[4] | test.c:31:43:31:43 | {...} | the elements in the index range 1 to 3 | diff --git a/c/misra/test/rules/RULE-9-3/PartiallyInitializedArrayWithExplicitInitializers.qlref b/c/misra/test/rules/RULE-9-3/PartiallyInitializedArrayWithExplicitInitializers.qlref new file mode 100644 index 0000000000..f4892f425c --- /dev/null +++ b/c/misra/test/rules/RULE-9-3/PartiallyInitializedArrayWithExplicitInitializers.qlref @@ -0,0 +1 @@ +rules/RULE-9-3/PartiallyInitializedArrayWithExplicitInitializers.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-9-3/test.c b/c/misra/test/rules/RULE-9-3/test.c new file mode 100644 index 0000000000..21451e6f31 --- /dev/null +++ b/c/misra/test/rules/RULE-9-3/test.c @@ -0,0 +1,37 @@ +void test() { + int l01[4] = {1, 2, 3, 4}; // COMPLIANT + int l02[4][2] = {{1, 2}, {3, 4}, {3, 4}, {3, 4}}; // COMPLIANT + int l03[4][2] = {1, 2, 3, 4, 3, 4, 3, 4}; // COMPLIANT + int l04[4][2] = {0}; // COMPLIANT + int l06[4][2] = {{0}, {0}, {0}, {0}}; // COMPLIANT + int l08[4] = {1, 2}; // NON_COMPLIANT + int l09[2][2] = {{1, 2}}; // NON_COMPLIANT + int l10[2][2] = {{1, 2}, [1] = {0}}; // COMPLIANT + int l11[2][2] = {{1, 2}, [1] = 0}; // COMPLIANT + int l12[2][2] = {{1, 2}, [1][0] = 0, [1][1] = 0}; // COMPLIANT + int l13[2][2] = {{0}, [1][0] = 0}; // NON_COMPLIANT - not all elements + // initialized with designated initializer + int l14[2][2] = { + {0}, [1][0] = 0, 0}; // NON_COMPLIANT - not all elements + // initialized with designated initializer + + int l15[2] = {[1] = 0}; // COMPILANT - sparse matrix initialized with + // designated initializer + int l16[2][2] = {[0] = {0, 1}}; // NON_COMPLIANT - sub-elements not + // initialized with designated initializer + + int l17[4][4] = { + [0][0] = 0, [0][1] = 0, [0][2] = 0, [0][3] = 0, [2][0] = 0, + [2][1] = 0, [2][2] = 0, [2][3] = 0}; // COMPLIANT - sparse matrix + // initialized with designated + // initializer + + int l18[4][4] = { + [0][0] = 0, [0][1] = 0, [0][2] = 0, [0][3] = 0, [2][0] = 0, + [2][1] = 0, [2][2] = 0, [2][3] = 0, 2}; // NON_COMPLIANT - not all + // elements initialized with + // designated initializer + + char str1[4] = "abc"; // COMPLIANT + char str2[5] = "abc"; // COMPLIANT - array initialized by string literal +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.expected b/c/misra/test/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.expected new file mode 100644 index 0000000000..725b5daab7 --- /dev/null +++ b/c/misra/test/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.expected @@ -0,0 +1,4 @@ +| test.c:10:16:10:16 | 1 | $@ repeats initialization of element [0], which is already initialized $@. | test.c:9:14:10:26 | {...} | Array aggregate literal | test.c:10:7:10:7 | 0 | here | +| test.c:12:28:12:28 | 1 | $@ repeats initialization of element [0][0], which is already initialized $@. | test.c:12:17:16:29 | {...} | Array aggregate literal | test.c:16:28:16:28 | 1 | here | +| test.c:24:34:24:34 | 1 | $@ repeats initialization of element [0][0][0], which is already initialized $@. | test.c:24:20:26:35 | {...} | Array aggregate literal | test.c:26:34:26:34 | 1 | here | +| test.c:36:17:37:25 | {...} | $@ repeats initialization of element s1::a. | test.c:36:17:37:25 | {...} | Structure aggregate literal | test.c:36:17:37:25 | {...} | here | diff --git a/c/misra/test/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.qlref b/c/misra/test/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.qlref new file mode 100644 index 0000000000..512ebb1a5a --- /dev/null +++ b/c/misra/test/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.qlref @@ -0,0 +1 @@ +rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-9-4/test.c b/c/misra/test/rules/RULE-9-4/test.c new file mode 100644 index 0000000000..aae73afb67 --- /dev/null +++ b/c/misra/test/rules/RULE-9-4/test.c @@ -0,0 +1,38 @@ +struct s1 { + int a; + int b; +}; + +void test_arrays(void) { + int a1[2] = {1, 2}; // COMPLIANT + int a2[2] = {[0] = 1, [1] = 2}; // COMPLIANT + int a3[2] = { + 0, [0] = 1, [1] = 2}; // NON_COMPLIANT - repeated initialiation of [0] + int a4[2][2] = {[0][0] = 1, [0][1] = 2, [1][0] = 3, [1][1] = 4}; // COMPLIANT + int a5[2][2] = {[0][0] = 1, + [0][1] = 2, + [1][0] = 3, + [1][1] = 4, + [0][0] = 1}; // NON_COMPLIANT + // - repeated + // initialiation + // of [0][0] + int a6[2][2][2] = { + [0][0][0] = 1, [0][0][1] = 2, [0][1][0] = 3, [0][1][1] = 4, + [1][0][0] = 5, [1][0][1] = 6, [1][1][0] = 7, [1][1][1] = 8}; // COMPLIANT + + int a7[2][2][2] = {[0][0][0] = 1, [0][0][1] = 2, [0][1][0] = 3, [0][1][1] = 4, + [1][0][0] = 5, [1][0][1] = 6, [1][1][0] = 7, [1][1][1] = 8, + [0][0][0] = 1}; // NON_COMPLIANT + // - repeated + // initialiation + // of [0][0][0] +} + +void test_structs(void) { + struct s1 s1 = {0}; // COMPLIANT + struct s1 s2 = {0, 1}; // COMPLIANT + struct s1 s3 = {.a = 0, .b = 1}; // COMPLIANT + struct s1 s4 = {.a = 0, + .a = 1}; // NON_COMPLIANT - repeated initialiation of .a +} \ No newline at end of file diff --git a/cpp/autosar/src/rules/M8-5-2/UseInitBracesToMatchTypeStructure.ql b/cpp/autosar/src/rules/M8-5-2/UseInitBracesToMatchTypeStructure.ql index f9de5d549e..a0ad244c15 100644 --- a/cpp/autosar/src/rules/M8-5-2/UseInitBracesToMatchTypeStructure.ql +++ b/cpp/autosar/src/rules/M8-5-2/UseInitBracesToMatchTypeStructure.ql @@ -16,48 +16,10 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.enhancements.AggregateLiteralEnhancements +import codingstandards.cpp.rules.useinitializerbracestomatchaggregatetypestructure.UseInitializerBracesToMatchAggregateTypeStructure -from - InferredAggregateLiteral inferredAggregateLiteral, Type aggType, string parentDescription, - Element explanationElement, string explanationDescription -where - not isExcluded(inferredAggregateLiteral, - InitializationPackage::useInitBracesToMatchTypeStructureQuery()) and - // Not an inferred aggregate literal that acts as a "leading zero" for the root aggregate - // e.g. - // ``` - // int i[2][4] { 0 } - // ``` - // Has an inferred aggregate literal (i.e. it's `{ { 0 } }`), but we shouldn't report it - not isLeadingZeroInitialized(getRootAggregate(inferredAggregateLiteral)) and - // Provide a good message, dependending on the type of the parent - ( - // For class aggergate literal parents, report which field is being assigned to - exists(ClassAggregateLiteral cal, Field field | - cal.getFieldExpr(field) = inferredAggregateLiteral and - parentDescription = "to field $@" and - explanationElement = field - | - explanationDescription = field.getName() - ) - or - // For array aggregate literal parents, report which index is being assigned to - exists(ArrayAggregateLiteral aal, int elementIndex | - aal.getElementExpr(elementIndex) = inferredAggregateLiteral and - parentDescription = "to index " + elementIndex + " in $@" and - explanationElement = aal and - explanationDescription = "array of type " + aal.getType().getName() - ) - or - // In some cases, we seem to have missing link, so provide a basic message - not any(ArrayAggregateLiteral aal).getElementExpr(_) = inferredAggregateLiteral and - not any(ClassAggregateLiteral aal).getFieldExpr(_) = inferredAggregateLiteral and - parentDescription = "to an unnamed field of $@" and - explanationElement = inferredAggregateLiteral.getParent() and - explanationDescription = " " + explanationElement.(Expr).getType().getName() - ) -select inferredAggregateLiteral, - "Missing braces on aggregate literal of " + - getAggregateTypeDescription(inferredAggregateLiteral, aggType) + " which is assigned " + - parentDescription + ".", aggType, aggType.getName(), explanationElement, explanationDescription +class UseInitBracesToMatchTypeStructureQuery extends UseInitializerBracesToMatchAggregateTypeStructureSharedQuery { + UseInitBracesToMatchTypeStructureQuery() { + this = InitializationPackage::useInitBracesToMatchTypeStructureQuery() + } +} diff --git a/cpp/autosar/test/rules/M8-5-2/UseInitBracesToMatchTypeStructure.qlref b/cpp/autosar/test/rules/M8-5-2/UseInitBracesToMatchTypeStructure.qlref deleted file mode 100644 index fb3df26b1e..0000000000 --- a/cpp/autosar/test/rules/M8-5-2/UseInitBracesToMatchTypeStructure.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/M8-5-2/UseInitBracesToMatchTypeStructure.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/M8-5-2/UseInitBracesToMatchTypeStructure.testref b/cpp/autosar/test/rules/M8-5-2/UseInitBracesToMatchTypeStructure.testref new file mode 100644 index 0000000000..06c190cf67 --- /dev/null +++ b/cpp/autosar/test/rules/M8-5-2/UseInitBracesToMatchTypeStructure.testref @@ -0,0 +1 @@ +cpp/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.ql \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Memory1.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Memory1.qll new file mode 100644 index 0000000000..061215310c --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Memory1.qll @@ -0,0 +1,61 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype Memory1Query = + TInitializerForAggregateOrUnionNotEnclosedInBracesQuery() or + TPartiallyInitializedArrayWithExplicitInitializersQuery() or + TRepeatedInitializationOfAggregateObjectElementQuery() + +predicate isMemory1QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `initializerForAggregateOrUnionNotEnclosedInBraces` query + Memory1Package::initializerForAggregateOrUnionNotEnclosedInBracesQuery() and + queryId = + // `@id` for the `initializerForAggregateOrUnionNotEnclosedInBraces` query + "c/misra/initializer-for-aggregate-or-union-not-enclosed-in-braces" and + ruleId = "RULE-9-2" and + category = "required" + or + query = + // `Query` instance for the `partiallyInitializedArrayWithExplicitInitializers` query + Memory1Package::partiallyInitializedArrayWithExplicitInitializersQuery() and + queryId = + // `@id` for the `partiallyInitializedArrayWithExplicitInitializers` query + "c/misra/partially-initialized-array-with-explicit-initializers" and + ruleId = "RULE-9-3" and + category = "required" + or + query = + // `Query` instance for the `repeatedInitializationOfAggregateObjectElement` query + Memory1Package::repeatedInitializationOfAggregateObjectElementQuery() and + queryId = + // `@id` for the `repeatedInitializationOfAggregateObjectElement` query + "c/misra/repeated-initialization-of-aggregate-object-element" and + ruleId = "RULE-9-4" and + category = "required" +} + +module Memory1Package { + Query initializerForAggregateOrUnionNotEnclosedInBracesQuery() { + //autogenerate `Query` type + result = + // `Query` type for `initializerForAggregateOrUnionNotEnclosedInBraces` query + TQueryC(TMemory1PackageQuery(TInitializerForAggregateOrUnionNotEnclosedInBracesQuery())) + } + + Query partiallyInitializedArrayWithExplicitInitializersQuery() { + //autogenerate `Query` type + result = + // `Query` type for `partiallyInitializedArrayWithExplicitInitializers` query + TQueryC(TMemory1PackageQuery(TPartiallyInitializedArrayWithExplicitInitializersQuery())) + } + + Query repeatedInitializationOfAggregateObjectElementQuery() { + //autogenerate `Query` type + result = + // `Query` type for `repeatedInitializationOfAggregateObjectElement` query + TQueryC(TMemory1PackageQuery(TRepeatedInitializationOfAggregateObjectElementQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index 1fcdafb5d0..6c3971b7f4 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -30,6 +30,7 @@ import IO4 import InvalidMemory1 import Language1 import Language2 +import Memory1 import Misc import Pointers1 import Pointers2 @@ -76,6 +77,7 @@ newtype TCQuery = TInvalidMemory1PackageQuery(InvalidMemory1Query q) or TLanguage1PackageQuery(Language1Query q) or TLanguage2PackageQuery(Language2Query q) or + TMemory1PackageQuery(Memory1Query q) or TMiscPackageQuery(MiscQuery q) or TPointers1PackageQuery(Pointers1Query q) or TPointers2PackageQuery(Pointers2Query q) or @@ -122,6 +124,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isInvalidMemory1QueryMetadata(query, queryId, ruleId, category) or isLanguage1QueryMetadata(query, queryId, ruleId, category) or isLanguage2QueryMetadata(query, queryId, ruleId, category) or + isMemory1QueryMetadata(query, queryId, ruleId, category) or isMiscQueryMetadata(query, queryId, ruleId, category) or isPointers1QueryMetadata(query, queryId, ruleId, category) or isPointers2QueryMetadata(query, queryId, ruleId, category) or diff --git a/cpp/common/src/codingstandards/cpp/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.qll b/cpp/common/src/codingstandards/cpp/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.qll new file mode 100644 index 0000000000..8aab8849fd --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.qll @@ -0,0 +1,59 @@ +/** + * Provides a library which includes a `problems` predicate for reporting initializers + * with brace structures that do not match the structure of the object being initialized. + */ + +import cpp +import codingstandards.cpp.Customizations +import codingstandards.cpp.Exclusions +import codingstandards.cpp.enhancements.AggregateLiteralEnhancements + +abstract class UseInitializerBracesToMatchAggregateTypeStructureSharedQuery extends Query { } + +Query getQuery() { result instanceof UseInitializerBracesToMatchAggregateTypeStructureSharedQuery } + +query predicate problems( + InferredAggregateLiteral inferredAggregateLiteral, string message, Type aggType, + string aggTypeName, Element explanationElement, string explanationDescription +) { + not isExcluded(inferredAggregateLiteral, getQuery()) and + // Not an inferred aggregate literal that acts as a "leading zero" for the root aggregate + // e.g. + // ``` + // int i[2][4] { 0 } + // ``` + // Has an inferred aggregate literal (i.e. it's `{ { 0 } }`), but we shouldn't report it + not isLeadingZeroInitialized(getRootAggregate(inferredAggregateLiteral)) and + // Provide a good message, dependending on the type of the parent + exists(string parentDescription | + // For class aggergate literal parents, report which field is being assigned to + exists(ClassAggregateLiteral cal, Field field | + cal.getFieldExpr(field) = inferredAggregateLiteral and + parentDescription = "to field $@" and + explanationElement = field + | + explanationDescription = field.getName() + ) + or + // For array aggregate literal parents, report which index is being assigned to + exists(ArrayAggregateLiteral aal, int elementIndex | + aal.getElementExpr(elementIndex) = inferredAggregateLiteral and + parentDescription = "to index " + elementIndex + " in $@" and + explanationElement = aal and + explanationDescription = "array of type " + aal.getType().getName() + ) + or + // In some cases, we seem to have missing link, so provide a basic message + not any(ArrayAggregateLiteral aal).getElementExpr(_) = inferredAggregateLiteral and + not any(ClassAggregateLiteral aal).getFieldExpr(_) = inferredAggregateLiteral and + parentDescription = "to an unnamed field of $@" and + explanationElement = inferredAggregateLiteral.getParent() and + explanationDescription = " " + explanationElement.(Expr).getType().getName() + | + aggTypeName = aggType.getName() and + message = + "Missing braces on aggregate literal of " + + getAggregateTypeDescription(inferredAggregateLiteral, aggType) + " which is assigned " + + parentDescription + "." + ) +} diff --git a/cpp/autosar/test/rules/M8-5-2/UseInitBracesToMatchTypeStructure.expected b/cpp/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.expected similarity index 100% rename from cpp/autosar/test/rules/M8-5-2/UseInitBracesToMatchTypeStructure.expected rename to cpp/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.expected diff --git a/cpp/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.ql b/cpp/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.ql new file mode 100644 index 0000000000..b24a879bab --- /dev/null +++ b/cpp/common/test/rules/useinitializerbracestomatchaggregatetypestructure/UseInitializerBracesToMatchAggregateTypeStructure.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.useinitializerbracestomatchaggregatetypestructure.UseInitializerBracesToMatchAggregateTypeStructure diff --git a/cpp/common/test/rules/useinitializerbracestomatchaggregatetypestructure/test.cpp b/cpp/common/test/rules/useinitializerbracestomatchaggregatetypestructure/test.cpp new file mode 100644 index 0000000000..b3a75e92ee --- /dev/null +++ b/cpp/common/test/rules/useinitializerbracestomatchaggregatetypestructure/test.cpp @@ -0,0 +1,58 @@ +#include + +struct Foo { + int m_i1; + int m_i2; + struct { + int m_s1_i1; + int m_s1_i2; + } m_s1; +}; + +struct Bar { + struct { + int m_s1_i1; + int m_s1_i2; + } m_s1; + int m_i1; + int m_i2; +}; + +struct Baz { + int m_baz_i1; + int m_baz_i2; + std::mutex m_mutex; + Foo f; +}; + +class StructNested { +public: + int m_nested_i1; + int *m_nested_i2; + Baz m_baz; + int m_array[10]; + StructNested() = default; + ~StructNested(); +}; + +void test() { + int l1[4]{1, 2, 3, 4}; // COMPLIANT + int l2[4][2]{{1, 2}, {3, 4}, {3, 4}, {3, 4}}; // COMPLIANT + int l3[4][2]{1, 2, 3, 4, 3, 4, 3, 4}; // NON_COMPLIANT - implied braces + int l4[4][2]{0}; // COMPLIANT + int l5[4][2]{{}, {}, {}, {}}; // NON_COMPLIANT - nested zero initializer + int l6[4][2]{{0}, {0}, {0}, {0}}; // NON_COMPLIANT - nested zero initializer + int l7[4][2]{}; // COMPLIANT + int l8[4]{1, 2}; // NON_COMPLIANT - missing explicit init + int l9[4][2]{{1, 2}}; // NON_COMPLIANT - missing explicit init + Foo f{1, 2, 3, 4}; // NON_COMPLIANT - implied braces + Foo f1{1, 2, {3, 4}}; // COMPLIANT + Foo f3{}; // COMPLIANT + Foo f4{0, 2}; // NON_COMPLIANT - missing explicit init + Foo f5{0, 2, {}}; // NON_COMPLIANT - nested zero initializer + Bar b{}; // COMPLIANT + Bar b1{0}; // COMPLIANT + Bar b2{{0}}; // NON_COMPLIANT - missing explicit init, nested zero init + StructNested n{}; // COMPLIANT + StructNested n1 = {}; // COMPLIANT +} \ No newline at end of file diff --git a/rule_packages/c/Memory1.json b/rule_packages/c/Memory1.json new file mode 100644 index 0000000000..15a9b389a1 --- /dev/null +++ b/rule_packages/c/Memory1.json @@ -0,0 +1,66 @@ +{ + "MISRA-C-2012": { + "RULE-9-2": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Using braces in initializers of objects and subobjects improves code readability and clarifies intent.", + "kind": "problem", + "name": "The initializer for an aggregate or union shall be enclosed in braces", + "precision": "high", + "severity": "warning", + "short_name": "InitializerForAggregateOrUnionNotEnclosedInBraces", + "shared_implementation_short_name": "UseInitializerBracesToMatchAggregateTypeStructure", + "tags": [ + "maintainability", + "readability" + ] + } + ], + "title": "The initializer for an aggregate or union shall be enclosed in braces" + }, + "RULE-9-3": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "An array object or a subobject of an array shall be explicitly initialized if any other object in that array is explicitly initialized.", + "kind": "problem", + "name": "Arrays shall not be partially initialized", + "precision": "high", + "severity": "warning", + "short_name": "PartiallyInitializedArrayWithExplicitInitializers", + "tags": [ + "maintainability", + "readability" + ] + } + ], + "title": "Arrays shall not be partially initialized" + }, + "RULE-9-4": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Repeated initialization of an element in an object can lead to side-effects or may signal a logic error.", + "kind": "problem", + "name": "An element of an object shall not be initialized more than once", + "precision": "high", + "severity": "error", + "short_name": "RepeatedInitializationOfAggregateObjectElement", + "tags": [ + "correctness", + "maintainability", + "readability" + ] + } + ], + "title": "An element of an object shall not be initialized more than once" + } + } +} \ No newline at end of file diff --git a/rule_packages/cpp/Initialization.json b/rule_packages/cpp/Initialization.json index 626ddb3184..da2ed53c98 100644 --- a/rule_packages/cpp/Initialization.json +++ b/rule_packages/cpp/Initialization.json @@ -364,6 +364,7 @@ "precision": "high", "severity": "recommendation", "short_name": "UseInitBracesToMatchTypeStructure", + "shared_implementation_short_name": "UseInitializerBracesToMatchAggregateTypeStructure", "tags": [ "readability", "maintainability" From 321a1e979611068f335bfbafcceb506ec8e7dc13 Mon Sep 17 00:00:00 2001 From: Nikita Kraiouchkine Date: Thu, 2 Mar 2023 23:14:10 +0100 Subject: [PATCH 2/4] Move RULE-9-5 to the Memory2 package RULE-9-5 is currently blocked due to CodeQL extractor non-support for identifying designated initializers in array aggregate literals. --- rules.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules.csv b/rules.csv index ef6fee41d7..75396bf81c 100644 --- a/rules.csv +++ b/rules.csv @@ -664,7 +664,7 @@ c,MISRA-C-2012,RULE-9-1,Yes,Mandatory,,,The value of an object with automatic st c,MISRA-C-2012,RULE-9-2,Yes,Required,,,The initializer for an aggregate or union shall be enclosed in braces,,Memory1,Easy, c,MISRA-C-2012,RULE-9-3,Yes,Required,,,Arrays shall not be partially initialized,,Memory1,Medium, c,MISRA-C-2012,RULE-9-4,Yes,Required,,,An element of an object shall not be initialized more than once,,Memory1,Medium, -c,MISRA-C-2012,RULE-9-5,Yes,Required,,,Where designated initializers are used to initialize an array object the size of the array shall be specified explicitly,,Memory1,Medium, +c,MISRA-C-2012,RULE-9-5,Yes,Required,,,Where designated initializers are used to initialize an array object the size of the array shall be specified explicitly,,Memory2,Medium, c,MISRA-C-2012,RULE-10-1,Yes,Required,,,Operands shall not be of an inappropriate essential type,,Types,Hard, c,MISRA-C-2012,RULE-10-2,Yes,Required,,,Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations,,Types,Medium, c,MISRA-C-2012,RULE-10-3,Yes,Required,,,The value of an expression shall not be assigned to an object with a narrower essential type or of a different essential type category,,Types,Hard, From 20db94f8d412b4cbb0510d1bbf604a9efd4da2ab Mon Sep 17 00:00:00 2001 From: Nikita Kraiouchkine Date: Tue, 7 Mar 2023 10:00:12 +0100 Subject: [PATCH 3/4] Fix RULE-9-4 bug, update test and metadata --- .../RepeatedInitializationOfAggregateObjectElement.ql | 7 ++++--- ...RepeatedInitializationOfAggregateObjectElement.expected | 2 +- c/misra/test/rules/RULE-9-4/test.c | 2 +- rule_packages/c/Memory1.json | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/c/misra/src/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.ql b/c/misra/src/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.ql index 9816f83e75..de0890777f 100644 --- a/c/misra/src/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.ql +++ b/c/misra/src/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.ql @@ -43,6 +43,8 @@ string getNestedArrayIndexString(Expr e) { | elementIndex ).toString() + "]" + order by + depth desc ) } @@ -95,8 +97,7 @@ predicate hasMultipleInitializerExprsForSameIndex(ArrayAggregateLiteral root, Ex * that initialize the same Field and are part of the same `ClassAggregateLiteral`. * This predicate is therefore unable to distinguish the individual duplicate expressions. */ -predicate hasMultipleInitializerExprsForSameField(ClassAggregateLiteral root, Expr expr, Field f) { - expr = root.getFieldExpr(f) and +predicate hasMultipleInitializerExprsForSameField(ClassAggregateLiteral root, Field f) { count(root.getFieldExpr(f)) > 1 } @@ -116,7 +117,7 @@ where // we cannot distinguish between different aggregate field init expressions. // therefore, we only report the root aggregate rather than any child init expr. // see `hasMultipleInitializerExprsForSameField` documentation. - hasMultipleInitializerExprsForSameField(root, _, f) and + hasMultipleInitializerExprsForSameField(root, f) and e1 = root and e2 = root and elementDescription = f.getQualifiedName() and diff --git a/c/misra/test/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.expected b/c/misra/test/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.expected index 725b5daab7..e50cb4d2c7 100644 --- a/c/misra/test/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.expected +++ b/c/misra/test/rules/RULE-9-4/RepeatedInitializationOfAggregateObjectElement.expected @@ -1,4 +1,4 @@ | test.c:10:16:10:16 | 1 | $@ repeats initialization of element [0], which is already initialized $@. | test.c:9:14:10:26 | {...} | Array aggregate literal | test.c:10:7:10:7 | 0 | here | | test.c:12:28:12:28 | 1 | $@ repeats initialization of element [0][0], which is already initialized $@. | test.c:12:17:16:29 | {...} | Array aggregate literal | test.c:16:28:16:28 | 1 | here | -| test.c:24:34:24:34 | 1 | $@ repeats initialization of element [0][0][0], which is already initialized $@. | test.c:24:20:26:35 | {...} | Array aggregate literal | test.c:26:34:26:34 | 1 | here | +| test.c:25:64:25:64 | 7 | $@ repeats initialization of element [1][1][0], which is already initialized $@. | test.c:24:20:26:35 | {...} | Array aggregate literal | test.c:26:34:26:34 | 1 | here | | test.c:36:17:37:25 | {...} | $@ repeats initialization of element s1::a. | test.c:36:17:37:25 | {...} | Structure aggregate literal | test.c:36:17:37:25 | {...} | here | diff --git a/c/misra/test/rules/RULE-9-4/test.c b/c/misra/test/rules/RULE-9-4/test.c index aae73afb67..7510155577 100644 --- a/c/misra/test/rules/RULE-9-4/test.c +++ b/c/misra/test/rules/RULE-9-4/test.c @@ -23,7 +23,7 @@ void test_arrays(void) { int a7[2][2][2] = {[0][0][0] = 1, [0][0][1] = 2, [0][1][0] = 3, [0][1][1] = 4, [1][0][0] = 5, [1][0][1] = 6, [1][1][0] = 7, [1][1][1] = 8, - [0][0][0] = 1}; // NON_COMPLIANT + [1][1][0] = 1}; // NON_COMPLIANT // - repeated // initialiation // of [0][0][0] diff --git a/rule_packages/c/Memory1.json b/rule_packages/c/Memory1.json index 15a9b389a1..7232b18751 100644 --- a/rule_packages/c/Memory1.json +++ b/rule_packages/c/Memory1.json @@ -10,7 +10,7 @@ "kind": "problem", "name": "The initializer for an aggregate or union shall be enclosed in braces", "precision": "high", - "severity": "warning", + "severity": "recommendation", "short_name": "InitializerForAggregateOrUnionNotEnclosedInBraces", "shared_implementation_short_name": "UseInitializerBracesToMatchAggregateTypeStructure", "tags": [ From 56e6ebdd1cadd67b13686268098e31fa5766dcc3 Mon Sep 17 00:00:00 2001 From: Nikita Kraiouchkine Date: Tue, 7 Mar 2023 10:03:32 +0100 Subject: [PATCH 4/4] InitializerForAggregateOrUnionNotEnclosedInBrances.ql: update severity --- .../InitializerForAggregateOrUnionNotEnclosedInBraces.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/misra/src/rules/RULE-9-2/InitializerForAggregateOrUnionNotEnclosedInBraces.ql b/c/misra/src/rules/RULE-9-2/InitializerForAggregateOrUnionNotEnclosedInBraces.ql index 4999527fc0..5d7b7981aa 100644 --- a/c/misra/src/rules/RULE-9-2/InitializerForAggregateOrUnionNotEnclosedInBraces.ql +++ b/c/misra/src/rules/RULE-9-2/InitializerForAggregateOrUnionNotEnclosedInBraces.ql @@ -5,7 +5,7 @@ * clarifies intent. * @kind problem * @precision high - * @problem.severity warning + * @problem.severity recommendation * @tags external/misra/id/rule-9-2 * maintainability * readability