From 4c873a293e81d5dc91d6ee0181c64d106f5790ba Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 13 Mar 2026 17:13:17 -0700 Subject: [PATCH] Reuse A2-13-4 as an audit query for undefined behavior. --- ...-03-13-make-string-literal-query-shared.md | 2 ++ ...ngLiteralsAssignedToNonConstantPointers.ql | 15 ++++++----- ...iteralsAssignedToNonConstantPointers.qlref | 1 - ...eralsAssignedToNonConstantPointers.testref | 1 + .../cpp/exclusions/cpp/Undefined.qll | 19 ++++++++++++- ...alsAssignedToNonConstantPointersShared.qll | 27 +++++++++++++++++++ ...ignedToNonConstantPointersShared.expected} | 2 +- ...ralsAssignedToNonConstantPointersShared.ql | 8 ++++++ .../test.cpp | 0 .../StringLiteralPossiblyModifiedAudit.ql | 27 +++++++++++++++++++ ...StringLiteralPossiblyModifiedAudit.testref | 1 + rule_packages/cpp/Strings.json | 1 + rule_packages/cpp/Undefined.json | 14 ++++++++++ 13 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 change_notes/2026-03-13-make-string-literal-query-shared.md delete mode 100644 cpp/autosar/test/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.qlref create mode 100644 cpp/autosar/test/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.testref create mode 100644 cpp/common/src/codingstandards/cpp/rules/stringliteralsassignedtononconstantpointersshared/StringLiteralsAssignedToNonConstantPointersShared.qll rename cpp/{autosar/test/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.expected => common/test/rules/stringliteralsassignedtononconstantpointersshared/StringLiteralsAssignedToNonConstantPointersShared.expected} (90%) create mode 100644 cpp/common/test/rules/stringliteralsassignedtononconstantpointersshared/StringLiteralsAssignedToNonConstantPointersShared.ql rename cpp/{autosar/test/rules/A2-13-4 => common/test/rules/stringliteralsassignedtononconstantpointersshared}/test.cpp (100%) create mode 100644 cpp/misra/src/rules/RULE-4-1-3/StringLiteralPossiblyModifiedAudit.ql create mode 100644 cpp/misra/test/rules/RULE-4-1-3/StringLiteralPossiblyModifiedAudit.testref diff --git a/change_notes/2026-03-13-make-string-literal-query-shared.md b/change_notes/2026-03-13-make-string-literal-query-shared.md new file mode 100644 index 0000000000..0a7cbf1d4d --- /dev/null +++ b/change_notes/2026-03-13-make-string-literal-query-shared.md @@ -0,0 +1,2 @@ + - `A2-13-4` - `StringLiteralsAssignedToNonConstantPointers.ql`: + - Refactored query logic into a shared module (`StringLiteralsAssignedToNonConstantPointersShared`) to enable reuse by MISRA C++ `RULE-4-1-3`. The query logic is unchanged. No visible changes to results or performance are expected. diff --git a/cpp/autosar/src/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.ql b/cpp/autosar/src/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.ql index 1e0f297435..549b328713 100644 --- a/cpp/autosar/src/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.ql +++ b/cpp/autosar/src/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.ql @@ -17,11 +17,12 @@ import cpp import codingstandards.cpp.autosar +import codingstandards.cpp.rules.stringliteralsassignedtononconstantpointersshared.StringLiteralsAssignedToNonConstantPointersShared -from ArrayToPointerConversion apc -where - not isExcluded(apc, StringsPackage::stringLiteralsAssignedToNonConstantPointersQuery()) and - apc.getExpr() instanceof StringLiteral and - apc.getExpr().getUnderlyingType().(ArrayType).getBaseType().isConst() and - not apc.getFullyConverted().getType().getUnderlyingType().(PointerType).getBaseType().isConst() -select apc, "String literal assigned to non-const pointer." +module StringLiteralsAssignedToNonConstantPointersConfig implements + StringLiteralsAssignedToNonConstantPointersSharedConfigSig +{ + Query getQuery() { result = StringsPackage::stringLiteralsAssignedToNonConstantPointersQuery() } +} + +import StringLiteralsAssignedToNonConstantPointersShared diff --git a/cpp/autosar/test/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.qlref b/cpp/autosar/test/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.qlref deleted file mode 100644 index a8fb0e3c2a..0000000000 --- a/cpp/autosar/test/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.testref b/cpp/autosar/test/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.testref new file mode 100644 index 0000000000..b620220e6f --- /dev/null +++ b/cpp/autosar/test/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.testref @@ -0,0 +1 @@ +cpp/common/test/rules/stringliteralsassignedtononconstantpointersshared/StringLiteralsAssignedToNonConstantPointersShared.ql \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/Undefined.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Undefined.qll index 37ae63fa53..c96c30611d 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/cpp/Undefined.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Undefined.qll @@ -8,7 +8,8 @@ newtype UndefinedQuery = TCriticalUnspecifiedBehaviorQuery() or TUndefinedBehaviorAuditQuery() or TCriticalUnspecifiedBehaviorAuditQuery() or - TPossibleDataRaceBetweenThreadsQuery() + TPossibleDataRaceBetweenThreadsQuery() or + TStringLiteralPossiblyModifiedAuditQuery() predicate isUndefinedQueryMetadata(Query query, string queryId, string ruleId, string category) { query = @@ -55,6 +56,15 @@ predicate isUndefinedQueryMetadata(Query query, string queryId, string ruleId, s "cpp/misra/possible-data-race-between-threads" and ruleId = "RULE-4-1-3" and category = "required" + or + query = + // `Query` instance for the `stringLiteralPossiblyModifiedAudit` query + UndefinedPackage::stringLiteralPossiblyModifiedAuditQuery() and + queryId = + // `@id` for the `stringLiteralPossiblyModifiedAudit` query + "cpp/misra/string-literal-possibly-modified-audit" and + ruleId = "RULE-4-1-3" and + category = "required" } module UndefinedPackage { @@ -92,4 +102,11 @@ module UndefinedPackage { // `Query` type for `possibleDataRaceBetweenThreads` query TQueryCPP(TUndefinedPackageQuery(TPossibleDataRaceBetweenThreadsQuery())) } + + Query stringLiteralPossiblyModifiedAuditQuery() { + //autogenerate `Query` type + result = + // `Query` type for `stringLiteralPossiblyModifiedAudit` query + TQueryCPP(TUndefinedPackageQuery(TStringLiteralPossiblyModifiedAuditQuery())) + } } diff --git a/cpp/common/src/codingstandards/cpp/rules/stringliteralsassignedtononconstantpointersshared/StringLiteralsAssignedToNonConstantPointersShared.qll b/cpp/common/src/codingstandards/cpp/rules/stringliteralsassignedtononconstantpointersshared/StringLiteralsAssignedToNonConstantPointersShared.qll new file mode 100644 index 0000000000..fa8d09cb4c --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/stringliteralsassignedtononconstantpointersshared/StringLiteralsAssignedToNonConstantPointersShared.qll @@ -0,0 +1,27 @@ +/** + * Provides a configurable module StringLiteralsAssignedToNonConstantPointersShared with a `problems` predicate + * for the following issue: + * The type of string literal as of C++0x was changed from 'array of char' to array of + * const char and therefore assignment to a non-const pointer is considered an error, + * which is reported as a warning by some compliers. + */ + +import cpp +import codingstandards.cpp.Customizations +import codingstandards.cpp.Exclusions + +signature module StringLiteralsAssignedToNonConstantPointersSharedConfigSig { + Query getQuery(); +} + +module StringLiteralsAssignedToNonConstantPointersShared< + StringLiteralsAssignedToNonConstantPointersSharedConfigSig Config> +{ + query predicate problems(ArrayToPointerConversion apc, string message) { + not isExcluded(apc, Config::getQuery()) and + apc.getExpr() instanceof StringLiteral and + apc.getExpr().getUnderlyingType().(ArrayType).getBaseType().isConst() and + not apc.getFullyConverted().getType().getUnderlyingType().(PointerType).getBaseType().isConst() and + message = "String literal assigned to non-const pointer." + } +} diff --git a/cpp/autosar/test/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.expected b/cpp/common/test/rules/stringliteralsassignedtononconstantpointersshared/StringLiteralsAssignedToNonConstantPointersShared.expected similarity index 90% rename from cpp/autosar/test/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.expected rename to cpp/common/test/rules/stringliteralsassignedtononconstantpointersshared/StringLiteralsAssignedToNonConstantPointersShared.expected index 4c8476b1e3..f3a7f7225e 100644 --- a/cpp/autosar/test/rules/A2-13-4/StringLiteralsAssignedToNonConstantPointers.expected +++ b/cpp/common/test/rules/stringliteralsassignedtononconstantpointersshared/StringLiteralsAssignedToNonConstantPointersShared.expected @@ -1,4 +1,4 @@ | test.cpp:2:12:2:19 | array to pointer conversion | String literal assigned to non-const pointer. | | test.cpp:10:15:10:22 | array to pointer conversion | String literal assigned to non-const pointer. | | test.cpp:20:14:20:22 | array to pointer conversion | String literal assigned to non-const pointer. | -| test.cpp:21:8:21:16 | array to pointer conversion | String literal assigned to non-const pointer. | +| test.cpp:21:8:21:16 | array to pointer conversion | String literal assigned to non-const pointer. | \ No newline at end of file diff --git a/cpp/common/test/rules/stringliteralsassignedtononconstantpointersshared/StringLiteralsAssignedToNonConstantPointersShared.ql b/cpp/common/test/rules/stringliteralsassignedtononconstantpointersshared/StringLiteralsAssignedToNonConstantPointersShared.ql new file mode 100644 index 0000000000..b87071b85d --- /dev/null +++ b/cpp/common/test/rules/stringliteralsassignedtononconstantpointersshared/StringLiteralsAssignedToNonConstantPointersShared.ql @@ -0,0 +1,8 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.stringliteralsassignedtononconstantpointersshared.StringLiteralsAssignedToNonConstantPointersShared + +module TestFileConfig implements StringLiteralsAssignedToNonConstantPointersSharedConfigSig { + Query getQuery() { result instanceof TestQuery } +} + +import StringLiteralsAssignedToNonConstantPointersShared diff --git a/cpp/autosar/test/rules/A2-13-4/test.cpp b/cpp/common/test/rules/stringliteralsassignedtononconstantpointersshared/test.cpp similarity index 100% rename from cpp/autosar/test/rules/A2-13-4/test.cpp rename to cpp/common/test/rules/stringliteralsassignedtononconstantpointersshared/test.cpp diff --git a/cpp/misra/src/rules/RULE-4-1-3/StringLiteralPossiblyModifiedAudit.ql b/cpp/misra/src/rules/RULE-4-1-3/StringLiteralPossiblyModifiedAudit.ql new file mode 100644 index 0000000000..d723617cce --- /dev/null +++ b/cpp/misra/src/rules/RULE-4-1-3/StringLiteralPossiblyModifiedAudit.ql @@ -0,0 +1,27 @@ +/** + * @id cpp/misra/string-literal-possibly-modified-audit + * @name RULE-4-1-3: Audit: string literal possibly modified through non-const pointer + * @description Assigning a string literal to a non-const pointer may lead to undefined behaviour if + * the string is modified through that pointer. + * @kind problem + * @precision low + * @problem.severity error + * @tags external/misra/id/rule-4-1-3 + * correctness + * scope/system + * external/misra/audit + * external/misra/enforcement/undecidable + * external/misra/obligation/required + */ + +import cpp +import codingstandards.cpp.misra +import codingstandards.cpp.rules.stringliteralsassignedtononconstantpointersshared.StringLiteralsAssignedToNonConstantPointersShared + +module StringLiteralPossiblyModifiedAuditConfig implements + StringLiteralsAssignedToNonConstantPointersSharedConfigSig +{ + Query getQuery() { result = UndefinedPackage::stringLiteralPossiblyModifiedAuditQuery() } +} + +import StringLiteralsAssignedToNonConstantPointersShared diff --git a/cpp/misra/test/rules/RULE-4-1-3/StringLiteralPossiblyModifiedAudit.testref b/cpp/misra/test/rules/RULE-4-1-3/StringLiteralPossiblyModifiedAudit.testref new file mode 100644 index 0000000000..b620220e6f --- /dev/null +++ b/cpp/misra/test/rules/RULE-4-1-3/StringLiteralPossiblyModifiedAudit.testref @@ -0,0 +1 @@ +cpp/common/test/rules/stringliteralsassignedtononconstantpointersshared/StringLiteralsAssignedToNonConstantPointersShared.ql \ No newline at end of file diff --git a/rule_packages/cpp/Strings.json b/rule_packages/cpp/Strings.json index acccdc7753..422396797b 100644 --- a/rule_packages/cpp/Strings.json +++ b/rule_packages/cpp/Strings.json @@ -17,6 +17,7 @@ "name": "String literals shall not be assigned to non-constant pointers", "precision": "very-high", "severity": "warning", + "shared_implementation_short_name": "StringLiteralsAssignedToNonConstantPointersShared", "short_name": "StringLiteralsAssignedToNonConstantPointers", "tags": [] } diff --git a/rule_packages/cpp/Undefined.json b/rule_packages/cpp/Undefined.json index bc0b10af3d..cb053d06dc 100644 --- a/rule_packages/cpp/Undefined.json +++ b/rule_packages/cpp/Undefined.json @@ -69,6 +69,20 @@ "concurrency", "scope/system" ] + }, + { + "description": "Assigning a string literal to a non-const pointer may lead to undefined behaviour if the string is modified through that pointer.", + "kind": "problem", + "name": "Audit: string literal possibly modified through non-const pointer", + "precision": "low", + "severity": "error", + "shared_implementation_short_name": "StringLiteralsAssignedToNonConstantPointersShared", + "short_name": "StringLiteralPossiblyModifiedAudit", + "tags": [ + "correctness", + "scope/system", + "external/misra/audit" + ] } ], "title": "There shall be no occurrence of undefined or critical unspecified behaviour"