From 84f007e427f3112442deeb7772f7cdcf2d694ce6 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 30 Jan 2024 09:23:41 +0000 Subject: [PATCH 001/370] Contracts: add metadata. --- .../cpp/exclusions/c/Contracts.qll | 61 +++++++++++++++++ .../cpp/exclusions/c/RuleMetadata.qll | 3 + rule_packages/c/Contracts.json | 65 +++++++++++++++++++ rule_packages/cpp/Expressions.json | 1 + 4 files changed, 130 insertions(+) create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/c/Contracts.qll create mode 100644 rule_packages/c/Contracts.json diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Contracts.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Contracts.qll new file mode 100644 index 0000000000..32a44a4355 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Contracts.qll @@ -0,0 +1,61 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype ContractsQuery = + TDoNotViolateInLineLinkageConstraintsQuery() or + TCheckMathLibraryFunctionParametersQuery() or + TFunctionErrorInformationUntestedQuery() + +predicate isContractsQueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `doNotViolateInLineLinkageConstraints` query + ContractsPackage::doNotViolateInLineLinkageConstraintsQuery() and + queryId = + // `@id` for the `doNotViolateInLineLinkageConstraints` query + "c/cert/do-not-violate-in-line-linkage-constraints" and + ruleId = "MSC40-C" and + category = "rule" + or + query = + // `Query` instance for the `checkMathLibraryFunctionParameters` query + ContractsPackage::checkMathLibraryFunctionParametersQuery() and + queryId = + // `@id` for the `checkMathLibraryFunctionParameters` query + "c/misra/check-math-library-function-parameters" and + ruleId = "DIR-4-11" and + category = "required" + or + query = + // `Query` instance for the `functionErrorInformationUntested` query + ContractsPackage::functionErrorInformationUntestedQuery() and + queryId = + // `@id` for the `functionErrorInformationUntested` query + "c/misra/function-error-information-untested" and + ruleId = "DIR-4-7" and + category = "required" +} + +module ContractsPackage { + Query doNotViolateInLineLinkageConstraintsQuery() { + //autogenerate `Query` type + result = + // `Query` type for `doNotViolateInLineLinkageConstraints` query + TQueryC(TContractsPackageQuery(TDoNotViolateInLineLinkageConstraintsQuery())) + } + + Query checkMathLibraryFunctionParametersQuery() { + //autogenerate `Query` type + result = + // `Query` type for `checkMathLibraryFunctionParameters` query + TQueryC(TContractsPackageQuery(TCheckMathLibraryFunctionParametersQuery())) + } + + Query functionErrorInformationUntestedQuery() { + //autogenerate `Query` type + result = + // `Query` type for `functionErrorInformationUntested` query + TQueryC(TContractsPackageQuery(TFunctionErrorInformationUntestedQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index c2771f4171..6425f27e28 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -9,6 +9,7 @@ import Concurrency2 import Concurrency3 import Concurrency4 import Concurrency5 +import Contracts import Contracts1 import Contracts2 import Contracts3 @@ -80,6 +81,7 @@ newtype TCQuery = TConcurrency3PackageQuery(Concurrency3Query q) or TConcurrency4PackageQuery(Concurrency4Query q) or TConcurrency5PackageQuery(Concurrency5Query q) or + TContractsPackageQuery(ContractsQuery q) or TContracts1PackageQuery(Contracts1Query q) or TContracts2PackageQuery(Contracts2Query q) or TContracts3PackageQuery(Contracts3Query q) or @@ -151,6 +153,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isConcurrency3QueryMetadata(query, queryId, ruleId, category) or isConcurrency4QueryMetadata(query, queryId, ruleId, category) or isConcurrency5QueryMetadata(query, queryId, ruleId, category) or + isContractsQueryMetadata(query, queryId, ruleId, category) or isContracts1QueryMetadata(query, queryId, ruleId, category) or isContracts2QueryMetadata(query, queryId, ruleId, category) or isContracts3QueryMetadata(query, queryId, ruleId, category) or diff --git a/rule_packages/c/Contracts.json b/rule_packages/c/Contracts.json new file mode 100644 index 0000000000..e2239908f0 --- /dev/null +++ b/rule_packages/c/Contracts.json @@ -0,0 +1,65 @@ +{ + "CERT-C": { + "MSC40-C": { + "properties": { + "obligation": "rule" + }, + "queries": [ + { + "description": "Inlined external functions are prohibited by the language standard from defining modifiable static or thread storage objects, or referencing identifiers with internal linkage.", + "kind": "problem", + "name": "Do not violate inline linkage constraints", + "precision": "very-high", + "severity": "error", + "short_name": "DoNotViolateInLineLinkageConstraints", + "tags": [ + "correctness" + ] + } + ], + "title": "Do not violate constraints" + } + }, + "MISRA-C-2012": { + "DIR-4-11": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Range, domain or pole errors in math functions may return unexpected values, trigger floating-point exceptions or set unexpected error modes.", + "kind": "problem", + "name": "The validity of values passed to `math.h` library functions shall be checked", + "precision": "high", + "severity": "error", + "short_name": "CheckMathLibraryFunctionParameters", + "shared_implementation_short_name": "UncheckedRangeDomainPoleErrors", + "tags": [ + "correctness" + ] + } + ], + "title": "The validity of values passed to library functions shall be checked" + }, + "DIR-4-7": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "A function (whether it is part of the standard library, a third party library or a user defined function) may provide some means of indicating the occurrence of an error. This may be via a global error flag, a parametric error flag, a special return value or some other means. Whenever such a mechanism is provided by a function the calling program shall check for the indication of an error as soon as the function returns.", + "kind": "problem", + "name": "If a function generates error information, then that error information shall be tested", + "precision": "very-high", + "severity": "recommendation", + "short_name": "FunctionErrorInformationUntested", + "shared_implementation_short_name": "FunctionErroneousReturnValueNotTested", + "tags": [ + "maintainability" + ] + } + ], + "title": "If a function returns error information, then that error information shall be tested" + } + } +} \ No newline at end of file diff --git a/rule_packages/cpp/Expressions.json b/rule_packages/cpp/Expressions.json index c0a7b6bb0b..5668c78a0a 100644 --- a/rule_packages/cpp/Expressions.json +++ b/rule_packages/cpp/Expressions.json @@ -86,6 +86,7 @@ "precision": "very-high", "severity": "recommendation", "short_name": "FunctionErroneousReturnValueNotTested", + "shared_implementation_short_name": "FunctionErroneousReturnValueNotTested", "tags": [ "maintainability" ] From 52bdbd7f536c723267489f8822d8c81a99db96e2 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 30 Jan 2024 09:33:15 +0000 Subject: [PATCH 002/370] MSC40-C: Add query for finding inline linkage constraints. Adds a query that finds cases where extern inlined functions reference internal linkage objects, or declare objects which are static or thread local. --- .../DoNotViolateInLineLinkageConstraints.md | 210 ++++++++++++++++++ .../DoNotViolateInLineLinkageConstraints.ql | 59 +++++ ...otViolateInLineLinkageConstraints.expected | 6 + ...DoNotViolateInLineLinkageConstraints.qlref | 1 + c/cert/test/rules/MSC40-C/test.c | 31 +++ 5 files changed, 307 insertions(+) create mode 100644 c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.md create mode 100644 c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.ql create mode 100644 c/cert/test/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.expected create mode 100644 c/cert/test/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.qlref create mode 100644 c/cert/test/rules/MSC40-C/test.c diff --git a/c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.md b/c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.md new file mode 100644 index 0000000000..26545fb812 --- /dev/null +++ b/c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.md @@ -0,0 +1,210 @@ +# MSC40-C: Do not violate inline linkage constraints + +This query implements the CERT-C rule MSC40-C: + +> Do not violate constraints + + +## Description + +According to the C Standard, 3.8 \[[ISO/IEC 9899:2011](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-ISO%2FIEC9899-2011)\], a constraint is a "restriction, either syntactic or semantic, by which the exposition of language elements is to be interpreted." Despite the similarity of the terms, a runtime constraint is not a kind of constraint. + +Violating any *shall* statement within a constraint clause in the C Standard requires an [implementation](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-implementation) to issue a diagnostic message, the C Standard, 5.1.1.3 \[[ISO/IEC 9899:2011](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-ISO%2FIEC9899-2011)\] states + +> A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined. Diagnostic messages need not be produced in other circumstances. + + +The C Standard further explains in a footnote + +> The intent is that an implementation should identify the nature of, and where possible localize, each violation. Of course, an implementation is free to produce any number of diagnostics as long as a valid program is still correctly translated. It may also successfully translate an invalid program. + + +Any constraint violation is a violation of this rule because it can result in an invalid program. + +## Noncompliant Code Example (Inline, Internal Linkage) + +The C Standard, 6.7.4, paragraph 3 \[[ISO/IEC 9899:2011](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-ISO%2FIEC9899-2011)\], states + +> An inline definition of a function with external linkage shall not contain a definition of a modifiable object with static or thread storage duration, and shall not contain a reference to an identifier with internal linkage. + + +The motivation behind this constraint lies in the semantics of inline definitions. Paragraph 7 of subclause 6.7.4 reads, in part: + +> An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition. + + +That is, if a function has an external and inline definition, implementations are free to choose which definition to invoke (two distinct invocations of the function may call different definitions, one the external definition, the other the inline definition). Therefore, issues can arise when these definitions reference internally linked objects or mutable objects with static or thread storage duration. + +This noncompliant code example refers to a static variable with file scope and internal linkage from within an external inline function: + +```cpp +static int I = 12; +extern inline void func(int a) { + int b = a * I; + /* ... */ +} + +``` + +## Compliant Solution (Inline, Internal Linkage) + +This compliant solution omits the `static` qualifier; consequently, the variable `I` has external linkage by default: + +```cpp +int I = 12; +extern inline void func(int a) { + int b = a * I; + /* ... */ +} + +``` + +## Noncompliant Code Example (inline, Modifiable Static) + +This noncompliant code example defines a modifiable `static` variable within an `extern inline` function. + +```cpp +extern inline void func(void) { + static int I = 12; + /* Perform calculations which may modify I */ +} + +``` + +## Compliant Solution (Inline, Modifiable Static) + +This compliant solution removes the `static` keyword from the local variable definition. If the modifications to `I` must be retained between invocations of `func()`, it must be declared at file scope so that it will be defined with external linkage. + +```cpp +extern inline void func(void) { + int I = 12; + /* Perform calculations which may modify I */ +} +``` + +## Noncompliant Code Example (Inline, Modifiable static) + +This noncompliant code example includes two translation units: `file1.c` and `file2.c`. The first file, `file1.c`, defines a pseudorandom number generation function: + +```cpp +/* file1.c */ + +/* Externally linked definition of the function get_random() */ +extern unsigned int get_random(void) { + /* Initialize the seeds */ + static unsigned int m_z = 0xdeadbeef; + static unsigned int m_w = 0xbaddecaf; + + /* Compute the next pseudorandom value and update the seeds */ + m_z = 36969 * (m_z & 65535) + (m_z >> 16); + m_w = 18000 * (m_w & 65535) + (m_w >> 16); + return (m_z << 16) + m_w; +} + +``` +The left-shift operation in the last line may wrap, but this is permitted by exception INT30-C-EX3 to rule [INT30-C. Ensure that unsigned integer operations do not wrap](https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap). + +The second file, `file2.c`, defines an `inline` version of this function that references mutable `static` objects—namely, objects that maintain the state of the pseudorandom number generator. Separate invocations of the `get_random()` function can call different definitions, each operating on separate static objects, resulting in a faulty pseudorandom number generator. + +```cpp +/* file2.c */ + +/* Inline definition of get_random function */ +inline unsigned int get_random(void) { + /* + * Initialize the seeds + * Constraint violation: static duration storage referenced + * in non-static inline definition + */ + static unsigned int m_z = 0xdeadbeef; + static unsigned int m_w = 0xbaddecaf; + + /* Compute the next pseudorandom value and update the seeds */ + m_z = 36969 * (m_z & 65535) + (m_z >> 16); + m_w = 18000 * (m_w & 65535) + (m_w >> 16); + return (m_z << 16) + m_w; +} + +int main(void) { + unsigned int rand_no; + for (int ii = 0; ii < 100; ii++) { + /* + * Get a pseudorandom number. Implementation defined whether the + * inline definition in this file or the external definition + * in file2.c is called. + */ + rand_no = get_random(); + /* Use rand_no... */ + } + + /* ... */ + + /* + * Get another pseudorandom number. Behavior is + * implementation defined. + */ + rand_no = get_random(); + /* Use rand_no... */ + return 0; +} + +``` + +## Compliant Solution (Inline, Modifiable static) + +This compliant solution adds the `static` modifier to the `inline` function definition in `file2.c`, giving it internal linkage. All references to `get_random()` in `file.2.c` will now reference the internally linked definition. The first file, which was not changed, is not shown here. + +```cpp +/* file2.c */ + +/* Static inline definition of get_random function */ +static inline unsigned int get_random(void) { + /* + * Initialize the seeds. + * No more constraint violation; the inline function is now + * internally linked. + */ + static unsigned int m_z = 0xdeadbeef; + static unsigned int m_w = 0xbaddecaf; + + /* Compute the next pseudorandom value and update the seeds */ + m_z = 36969 * (m_z & 65535) + (m_z >> 16); + m_w = 18000 * (m_w & 65535) + (m_w >> 16); + return (m_z << 16) + m_w; +} + +int main(void) { + /* Generate pseudorandom numbers using get_random()... */ + return 0; +} + +``` + +## Risk Assessment + +Constraint violations are a broad category of error that can result in unexpected control flow and corrupted data. + +
Rule Severity Likelihood Remediation Cost Priority Level
MSC40-C Low Unlikely Medium P2 L3
+ + +## Automated Detection + +
Tool Version Checker Description
Astrée 23.04 alignas-extended assignment-to-non-modifiable-lvalue cast-pointer-void-arithmetic-implicit element-type-incomplete function-pointer-integer-cast-implicit function-return-type inappropriate-pointer-cast-implicit incompatible-function-pointer-conversion incompatible-object-pointer-conversion initializer-excess invalid-array-size non-constant-static-assert parameter-match-type pointer-integral-cast-implicit pointer-qualifier-cast-const-implicit pointer-qualifier-cast-volatile-implicit redeclaration return-empty return-non-empty static-assert type-compatibility type-compatibility-link type-specifier undeclared-parameter unnamed-parameter Partially checked
Helix QAC 2023.4 C0232, C0233, C0244, C0268, C0321, C0322, C0338, C0422, C0423, C0426, C0427, C0429, C0430, C0431, C0432, C0435, C0436, C0437, C0446, C0447, C0448, C0449, C0451, C0452, C0453, C0454, C0456, C0457, C0458, C0460, C0461, C0462, C0463, C0466, C0467, C0468, C0469, C0476, C0477, C0478, C0481, C0482, C0483, C0484, C0485, C0486, C0487, C0493, C0494, C0495, C0496, C0497, C0513, C0514, C0515, C0536, C0537, C0540, C0541, C0542, C0546, C0547, C0550, C0554, C0555, C0556, C0557, C0558, C0559, C0560, C0561, C0562, C0563, C0564, C0565, C0580, C0588, C0589, C0590, C0591, C0605, C0616, C0619, C0620, C0621, C0622, C0627, C0628, C0629, C0631, C0638, C0640, C0641, C0642, C0643, C0644, C0645, C0646, C0649, C0650, C0651, C0653, C0655, C0656, C0657, C0659, C0664, C0665, C0669, C0671, C0673, C0674, C0675, C0677, C0682, C0683, C0684, C0685, C0690, C0698, C0699, C0708, C0709, C0736, C0737, C0738, C0746, C0747, C0755, C0756, C0757, C0758, C0766, C0767, C0768, C0774, C0775, C0801, C0802, C0803, C0804, C0811, C0821, C0834, C0835, C0844, C0845, C0851, C0852, C0866, C0873, C0877, C0940, C0941, C0943, C0944, C1023, C1024, C1025, C1033, C1047, C1048, C1050, C1061, C1062, C3236, C3237, C3238, C3244 C++4122
Klocwork 2023.4 MISRA.FUNC.STATIC.REDECL
LDRA tool suite 9.7.1 21 S, 145 S, 323 S, 345 S, 387 S, 404 S, 481 S, 580 S, 612 S, 615 S, 646 S
Parasoft C/C++test 2023.1 CERT_C-MSC40-a An inline definition of a function with external linkage shall not contain definitions and uses of static objects
Polyspace Bug Finder CERT C: Rule MSC40-C Checks for inline constraint not respected (rule partially covered)
RuleChecker 23.04 alignas-extended assignment-to-non-modifiable-lvalue cast-pointer-void-arithmetic-implicit element-type-incomplete function-pointer-integer-cast-implicit function-return-type inappropriate-pointer-cast-implicit incompatible-function-pointer-conversion incompatible-object-pointer-conversion initializer-excess invalid-array-size non-constant-static-assert parameter-match-type pointer-integral-cast-implicit pointer-qualifier-cast-const-implicit pointer-qualifier-cast-volatile-implicit redeclaration return-empty return-non-empty static-assert type-compatibility type-compatibility-link type-specifier undeclared-parameter unnamed-parameter Partially checked
+ + +## Related Vulnerabilities + +Search for [vulnerabilities](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-vulnerability) resulting from the violation of this rule on the [CERT website](https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+MSC40-C). + +## Bibliography + +
\[ ISO/IEC 9899:2011 \] 4, "Conformance" 5.1.1.3, "Diagnostics" 6.7.4, "Function Specifiers"
+ + +## Implementation notes + +None + +## References + +* CERT-C: [MSC40-C: Do not violate constraints](https://wiki.sei.cmu.edu/confluence/display/c) diff --git a/c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.ql b/c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.ql new file mode 100644 index 0000000000..63dec179c6 --- /dev/null +++ b/c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.ql @@ -0,0 +1,59 @@ +/** + * @id c/cert/do-not-violate-in-line-linkage-constraints + * @name MSC40-C: Do not violate inline linkage constraints + * @description Inlined external functions are prohibited by the language standard from defining + * modifiable static or thread storage objects, or referencing identifiers with + * internal linkage. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/cert/id/msc40-c + * correctness + * external/cert/obligation/rule + */ + +import cpp +import codingstandards.c.cert +import codingstandards.cpp.Linkage + +/* + * This is C specific, because in C++ all extern function definitions must be identical. + * Only in C is it permitted for an extern function to be defined in multiple translation + * units with different implementations, when using the inline keyword. + */ + +from Element accessOrDecl, Variable v, Function f, string message +where + not isExcluded(f, ContractsPackage::doNotViolateInLineLinkageConstraintsQuery()) and + f.isInline() and + hasExternalLinkage(f) and + // Pre-emptively exclude compiler generated functions + not f.isCompilerGenerated() and + // This rule does not apply to C++, but exclude C++ specific cases anyway + not f instanceof MemberFunction and + not f.isFromUninstantiatedTemplate(_) and + ( + // There exists a modifiable local variable which is static or thread local + exists(LocalVariable lsv, string storageModifier | + lsv.isStatic() and storageModifier = "Static" + or + lsv.isThreadLocal() and storageModifier = "Thread-local" + | + lsv.getFunction() = f and + not lsv.isConst() and + accessOrDecl = lsv and + message = storageModifier + " local variable $@ declared" and + v = lsv + ) + or + // References an identifier with internal linkage + exists(GlobalOrNamespaceVariable gv | + accessOrDecl = v.getAnAccess() and + accessOrDecl.(VariableAccess).getEnclosingFunction() = f and + hasInternalLinkage(v) and + message = "Identifier $@ with internal linkage referenced" and + v = gv + ) + ) +select accessOrDecl, message + " in the extern inlined function $@.", v, v.getName(), f, + f.getQualifiedName() diff --git a/c/cert/test/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.expected b/c/cert/test/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.expected new file mode 100644 index 0000000000..f258d4adef --- /dev/null +++ b/c/cert/test/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.expected @@ -0,0 +1,6 @@ +| test.c:6:14:6:14 | i | Static local variable $@ declared in the extern inlined function $@. | test.c:6:14:6:14 | i | i | test.c:5:20:5:24 | test1 | test1 | +| test.c:7:3:7:4 | g1 | Identifier $@ with internal linkage referenced in the extern inlined function $@. | test.c:1:12:1:13 | g1 | g1 | test.c:5:20:5:24 | test1 | test1 | +| test.c:9:3:9:4 | g3 | Identifier $@ with internal linkage referenced in the extern inlined function $@. | test.c:3:11:3:12 | g3 | g3 | test.c:5:20:5:24 | test1 | test1 | +| test.c:27:14:27:14 | i | Static local variable $@ declared in the extern inlined function $@. | test.c:27:14:27:14 | i | i | test.c:26:13:26:17 | test4 | test4 | +| test.c:28:3:28:4 | g1 | Identifier $@ with internal linkage referenced in the extern inlined function $@. | test.c:1:12:1:13 | g1 | g1 | test.c:26:13:26:17 | test4 | test4 | +| test.c:30:3:30:4 | g3 | Identifier $@ with internal linkage referenced in the extern inlined function $@. | test.c:3:11:3:12 | g3 | g3 | test.c:26:13:26:17 | test4 | test4 | diff --git a/c/cert/test/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.qlref b/c/cert/test/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.qlref new file mode 100644 index 0000000000..f14d4270cc --- /dev/null +++ b/c/cert/test/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.qlref @@ -0,0 +1 @@ +rules/MSC40-C/DoNotViolateInLineLinkageConstraints.ql \ No newline at end of file diff --git a/c/cert/test/rules/MSC40-C/test.c b/c/cert/test/rules/MSC40-C/test.c new file mode 100644 index 0000000000..3ca4afff4a --- /dev/null +++ b/c/cert/test/rules/MSC40-C/test.c @@ -0,0 +1,31 @@ +static int g1 = 0; +extern int g2 = 1; +const int g3 = 1; // defaults to internal linkage + +extern inline void test1() { + static int i = 0; // NON_COMPLIANT + g1++; // NON_COMPLIANT + g2++; // COMPLIANT + g3; // NON_COMPLIANT +} + +extern void test2() { + static int i = 0; // COMPLIANT + g1++; // COMPLIANT + g2++; // COMPLIANT + g3; // COMPLIANT +} + +void test3() { + static int i = 0; // COMPLIANT + g1++; // COMPLIANT + g2++; // COMPLIANT + g3; // COMPLIANT +} + +inline void test4() { + static int i = 0; // NON_COMPLIANT + g1++; // NON_COMPLIANT + g2++; // COMPLIANT + g3; // NON_COMPLIANT +} \ No newline at end of file From dcb32c1a017b50a1602a8d3e2e8afbf35ef0e534 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 30 Jan 2024 09:44:43 +0000 Subject: [PATCH 003/370] DIR-4-11: Add query for checking math.h functions Add query which detects domain and pole errors for math.h functions. --- .../CheckMathLibraryFunctionParameters.ql | 22 +++++++++++++++++++ ...CheckMathLibraryFunctionParameters.testref | 1 + 2 files changed, 23 insertions(+) create mode 100644 c/misra/src/rules/DIR-4-11/CheckMathLibraryFunctionParameters.ql create mode 100644 c/misra/test/rules/DIR-4-11/CheckMathLibraryFunctionParameters.testref diff --git a/c/misra/src/rules/DIR-4-11/CheckMathLibraryFunctionParameters.ql b/c/misra/src/rules/DIR-4-11/CheckMathLibraryFunctionParameters.ql new file mode 100644 index 0000000000..6810784a0e --- /dev/null +++ b/c/misra/src/rules/DIR-4-11/CheckMathLibraryFunctionParameters.ql @@ -0,0 +1,22 @@ +/** + * @id c/misra/check-math-library-function-parameters + * @name DIR-4-11: The validity of values passed to `math.h` library functions shall be checked + * @description Range, domain or pole errors in math functions may return unexpected values, trigger + * floating-point exceptions or set unexpected error modes. + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/dir-4-11 + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.rules.uncheckedrangedomainpoleerrors.UncheckedRangeDomainPoleErrors + +class CheckMathLibraryFunctionParametersQuery extends UncheckedRangeDomainPoleErrorsSharedQuery { + CheckMathLibraryFunctionParametersQuery() { + this = ContractsPackage::checkMathLibraryFunctionParametersQuery() + } +} diff --git a/c/misra/test/rules/DIR-4-11/CheckMathLibraryFunctionParameters.testref b/c/misra/test/rules/DIR-4-11/CheckMathLibraryFunctionParameters.testref new file mode 100644 index 0000000000..50cf3fcb51 --- /dev/null +++ b/c/misra/test/rules/DIR-4-11/CheckMathLibraryFunctionParameters.testref @@ -0,0 +1 @@ +c/common/test/rules/uncheckedrangedomainpoleerrors/UncheckedRangeDomainPoleErrors.ql \ No newline at end of file From 377124004116573572197eabd39ceb905e8b5e30 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 30 Jan 2024 09:47:55 +0000 Subject: [PATCH 004/370] DIR-4-7: Create shared query for unchecked return values Create a new shared query from the implementation of M0-3-2, which detects cases where error checking has not occurred after a call to a standard C library function. --- ...tionErroneousReturnValueNotTested.expected | 1 + .../FunctionErroneousReturnValueNotTested.ql | 4 ++ .../test.c | 0 .../FunctionErrorInformationUntested.ql | 26 ++++++++ .../FunctionErrorInformationUntested.testref | 1 + .../FunctionErroneousReturnValueNotTested.ql | 57 +++-------------- ...unctionErroneousReturnValueNotTested.qlref | 1 - .../FunctionErroneousReturnValueNotTested.qll | 62 +++++++++++++++++++ ...tionErroneousReturnValueNotTested.expected | 0 .../FunctionErroneousReturnValueNotTested.ql | 4 ++ .../test.cpp | 17 +++++ 11 files changed, 122 insertions(+), 51 deletions(-) create mode 100644 c/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.expected create mode 100644 c/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.ql rename cpp/autosar/test/rules/M0-3-2/test.cpp => c/common/test/rules/functionerroneousreturnvaluenottested/test.c (100%) create mode 100644 c/misra/src/rules/DIR-4-7/FunctionErrorInformationUntested.ql create mode 100644 c/misra/test/rules/DIR-4-7/FunctionErrorInformationUntested.testref delete mode 100644 cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.qlref create mode 100644 cpp/common/src/codingstandards/cpp/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.qll rename cpp/{autosar/test/rules/M0-3-2 => common/test/rules/functionerroneousreturnvaluenottested}/FunctionErroneousReturnValueNotTested.expected (100%) create mode 100644 cpp/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.ql create mode 100644 cpp/common/test/rules/functionerroneousreturnvaluenottested/test.cpp diff --git a/c/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.expected b/c/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.expected new file mode 100644 index 0000000000..015f52348c --- /dev/null +++ b/c/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.expected @@ -0,0 +1 @@ +| test.c:16:3:16:8 | call to remove | Return value is not tested for errors. | diff --git a/c/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.ql b/c/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.ql new file mode 100644 index 0000000000..12c2196efd --- /dev/null +++ b/c/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.ql @@ -0,0 +1,4 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.functionerroneousreturnvaluenottested.FunctionErroneousReturnValueNotTested + +class TestFileQuery extends FunctionErroneousReturnValueNotTestedSharedQuery, TestQuery { } diff --git a/cpp/autosar/test/rules/M0-3-2/test.cpp b/c/common/test/rules/functionerroneousreturnvaluenottested/test.c similarity index 100% rename from cpp/autosar/test/rules/M0-3-2/test.cpp rename to c/common/test/rules/functionerroneousreturnvaluenottested/test.c diff --git a/c/misra/src/rules/DIR-4-7/FunctionErrorInformationUntested.ql b/c/misra/src/rules/DIR-4-7/FunctionErrorInformationUntested.ql new file mode 100644 index 0000000000..b827e101e3 --- /dev/null +++ b/c/misra/src/rules/DIR-4-7/FunctionErrorInformationUntested.ql @@ -0,0 +1,26 @@ +/** + * @id c/misra/function-error-information-untested + * @name DIR-4-7: If a function generates error information, then that error information shall be tested + * @description A function (whether it is part of the standard library, a third party library or a + * user defined function) may provide some means of indicating the occurrence of an + * error. This may be via a global error flag, a parametric error flag, a special + * return value or some other means. Whenever such a mechanism is provided by a + * function the calling program shall check for the indication of an error as soon as + * the function returns. + * @kind problem + * @precision very-high + * @problem.severity recommendation + * @tags external/misra/id/dir-4-7 + * maintainability + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.rules.functionerroneousreturnvaluenottested.FunctionErroneousReturnValueNotTested + +class FunctionErrorInformationUntestedQuery extends FunctionErroneousReturnValueNotTestedSharedQuery { + FunctionErrorInformationUntestedQuery() { + this = ContractsPackage::functionErrorInformationUntestedQuery() + } +} diff --git a/c/misra/test/rules/DIR-4-7/FunctionErrorInformationUntested.testref b/c/misra/test/rules/DIR-4-7/FunctionErrorInformationUntested.testref new file mode 100644 index 0000000000..51bd5fbefb --- /dev/null +++ b/c/misra/test/rules/DIR-4-7/FunctionErrorInformationUntested.testref @@ -0,0 +1 @@ +c/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.ql \ No newline at end of file diff --git a/cpp/autosar/src/rules/M0-3-2/FunctionErroneousReturnValueNotTested.ql b/cpp/autosar/src/rules/M0-3-2/FunctionErroneousReturnValueNotTested.ql index aee4e40838..77e6278960 100644 --- a/cpp/autosar/src/rules/M0-3-2/FunctionErroneousReturnValueNotTested.ql +++ b/cpp/autosar/src/rules/M0-3-2/FunctionErroneousReturnValueNotTested.ql @@ -19,54 +19,11 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.dataflow.DataFlow -import semmle.code.cpp.controlflow.Guards +import codingstandards.cpp.rules.functionerroneousreturnvaluenottested.FunctionErroneousReturnValueNotTested -from FunctionCall fc -where - not isExcluded(fc, ExpressionsPackage::functionErroneousReturnValueNotTestedQuery()) and - fc.getTarget() - .hasGlobalOrStdName([ - // fcntl.h - "open", "openat", "fcntl", "creat", - // locale.h - "setlocale", - // stdlib.h - "system", "getenv", "getenv_s", - // signal.h - "signal", "raise", - // setjmp.h - "setjmp", - // stdio.h - "fopen", "fopen_s", "freopen", "freopen_s", "fclose", "fcloseall", "fflush", "setvbuf", - "fgetc", "getc", "fgets", "fputc", "getchar", "gets", "gets_s", "putchar", "puts", - "ungetc", "scanf", "fscanf", "sscanf", "scanf_s", "fscanf_s", "sscanf_s", "vscanf", - "vfscanf", "vsscanf", "vscanf_s", "vfscanf_s", "vsscanf_s", "printf", "fprintf", - "sprintf", "snprintf", "printf_s", "fprintf_s", "sprintf_s", "snprintf_s", "vprintf", - "vfprintf", "vsprintf", "vsnprintf", "vprintf_s", "vfprintf_s", "vsprintf_s", - "vsnprintf_s", "ftell", "fgetpos", "fseek", "fsetpos", "remove", "rename", "tmpfile", - "tmpfile_s", "tmpnam", "tmpnam_s", - // string.h - "strcpy_s", "strncpy_s", "strcat_s", "strncat_s", "memset_s", "memcpy_s", "memmove_s", - "strerror_s", - // threads.h - "thrd_create", "thrd_sleep", "thrd_detach", "thrd_join", "mtx_init", "mtx_lock", - "mtx_timedlock", "mtx_trylock", "mtx_unlock", "cnd_init", "cnd_signal", "cnd_broadcast", - "cnd_wait", "cnd_timedwait", "tss_create", "tss_get", "tss_set", - // time.h - "time", "clock", "timespec_get", "asctime_s", "ctime_s", "gmtime", "gmtime_s", - "localtime", "localtime_s", - // unistd.h - "write", "read", "close", "unlink", - // wchar.h - "fgetwc", "getwc", "fgetws", "fputwc", "putwc", "fputws", "getwchar", "putwchar", - "ungetwc", "wscanf", "fwscanf", "swscanf", "wscanf_s", "fwscanf_s", "swscanf_s", - "vwscanf", "vfwscanf", "vswscanf", "vwscanf_s", "vfwscanf_s", "vswscanf_s", "wprintf", - "fwprintf", "swprintf", "wprintf_s", "fwprintf_s", "swprintf_s", "snwprintf_s", - "vwprintf", "vfwprintf", "vswprintf", "vwprintf_s", "vfwprintf_s", "vswprintf_s", - "vsnwprintf_s" - ]) and - forall(GuardCondition gc | - not DataFlow::localFlow(DataFlow::exprNode(fc), DataFlow::exprNode(gc.getAChild*())) - ) -select fc, "Return value is not tested for errors." +class FunctionErrorInformationUntestedQuery extends FunctionErroneousReturnValueNotTestedSharedQuery +{ + FunctionErrorInformationUntestedQuery() { + this = ExpressionsPackage::functionErroneousReturnValueNotTestedQuery() + } +} diff --git a/cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.qlref b/cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.qlref deleted file mode 100644 index 3cfea1dc31..0000000000 --- a/cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/M0-3-2/FunctionErroneousReturnValueNotTested.ql \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.qll b/cpp/common/src/codingstandards/cpp/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.qll new file mode 100644 index 0000000000..fe4f788847 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.qll @@ -0,0 +1,62 @@ +/** + * Provides a library which includes a `problems` predicate for reporting unchecked error values. + */ + +import cpp +import codingstandards.cpp.Customizations +import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.controlflow.Guards +import codingstandards.cpp.Exclusions + +abstract class FunctionErroneousReturnValueNotTestedSharedQuery extends Query { } + +Query getQuery() { result instanceof FunctionErroneousReturnValueNotTestedSharedQuery } + +query predicate problems(FunctionCall fc, string message) { + not isExcluded(fc, getQuery()) and + fc.getTarget() + .hasGlobalOrStdName([ + // fcntl.h + "open", "openat", "fcntl", "creat", + // locale.h + "setlocale", + // stdlib.h + "system", "getenv", "getenv_s", + // signal.h + "signal", "raise", + // setjmp.h + "setjmp", + // stdio.h + "fopen", "fopen_s", "freopen", "freopen_s", "fclose", "fcloseall", "fflush", "setvbuf", + "fgetc", "getc", "fgets", "fputc", "getchar", "gets", "gets_s", "putchar", "puts", + "ungetc", "scanf", "fscanf", "sscanf", "scanf_s", "fscanf_s", "sscanf_s", "vscanf", + "vfscanf", "vsscanf", "vscanf_s", "vfscanf_s", "vsscanf_s", "printf", "fprintf", + "sprintf", "snprintf", "printf_s", "fprintf_s", "sprintf_s", "snprintf_s", "vprintf", + "vfprintf", "vsprintf", "vsnprintf", "vprintf_s", "vfprintf_s", "vsprintf_s", + "vsnprintf_s", "ftell", "fgetpos", "fseek", "fsetpos", "remove", "rename", "tmpfile", + "tmpfile_s", "tmpnam", "tmpnam_s", + // string.h + "strcpy_s", "strncpy_s", "strcat_s", "strncat_s", "memset_s", "memcpy_s", "memmove_s", + "strerror_s", + // threads.h + "thrd_create", "thrd_sleep", "thrd_detach", "thrd_join", "mtx_init", "mtx_lock", + "mtx_timedlock", "mtx_trylock", "mtx_unlock", "cnd_init", "cnd_signal", "cnd_broadcast", + "cnd_wait", "cnd_timedwait", "tss_create", "tss_get", "tss_set", + // time.h + "time", "clock", "timespec_get", "asctime_s", "ctime_s", "gmtime", "gmtime_s", + "localtime", "localtime_s", + // unistd.h + "write", "read", "close", "unlink", + // wchar.h + "fgetwc", "getwc", "fgetws", "fputwc", "putwc", "fputws", "getwchar", "putwchar", + "ungetwc", "wscanf", "fwscanf", "swscanf", "wscanf_s", "fwscanf_s", "swscanf_s", + "vwscanf", "vfwscanf", "vswscanf", "vwscanf_s", "vfwscanf_s", "vswscanf_s", "wprintf", + "fwprintf", "swprintf", "wprintf_s", "fwprintf_s", "swprintf_s", "snwprintf_s", + "vwprintf", "vfwprintf", "vswprintf", "vwprintf_s", "vfwprintf_s", "vswprintf_s", + "vsnwprintf_s" + ]) and + forall(GuardCondition gc | + not DataFlow::localFlow(DataFlow::exprNode(fc), DataFlow::exprNode(gc.getAChild*())) + ) and + message = "Return value is not tested for errors." +} diff --git a/cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.expected b/cpp/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.expected similarity index 100% rename from cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.expected rename to cpp/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.expected diff --git a/cpp/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.ql b/cpp/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.ql new file mode 100644 index 0000000000..12c2196efd --- /dev/null +++ b/cpp/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.ql @@ -0,0 +1,4 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.functionerroneousreturnvaluenottested.FunctionErroneousReturnValueNotTested + +class TestFileQuery extends FunctionErroneousReturnValueNotTestedSharedQuery, TestQuery { } diff --git a/cpp/common/test/rules/functionerroneousreturnvaluenottested/test.cpp b/cpp/common/test/rules/functionerroneousreturnvaluenottested/test.cpp new file mode 100644 index 0000000000..08e2f23dec --- /dev/null +++ b/cpp/common/test/rules/functionerroneousreturnvaluenottested/test.cpp @@ -0,0 +1,17 @@ +#include + +void test_compliant() { + // Return value is passed to an lvalue and then tested. + FILE *fh = fopen("/etc/foo", "r"); + if (!fh) { // COMPLIANT + return; + } + + // Return value is tested immediately as an rvalue. + if (fclose(fh)) // COMPLIANT + return; +} + +void test_noncompliant() { + remove("/bin/bash"); // NON_COMPLIANT +} \ No newline at end of file From 81200896b07034ad5120918e91df6295f2d9feb0 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 30 Jan 2024 09:53:23 +0000 Subject: [PATCH 005/370] FunctionErroneousReturnValueNotTested rewritten for clarity --- .../FunctionErroneousReturnValueNotTested.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.qll b/cpp/common/src/codingstandards/cpp/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.qll index fe4f788847..5cd98c05d6 100644 --- a/cpp/common/src/codingstandards/cpp/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.qll +++ b/cpp/common/src/codingstandards/cpp/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.qll @@ -55,8 +55,8 @@ query predicate problems(FunctionCall fc, string message) { "vwprintf", "vfwprintf", "vswprintf", "vwprintf_s", "vfwprintf_s", "vswprintf_s", "vsnwprintf_s" ]) and - forall(GuardCondition gc | - not DataFlow::localFlow(DataFlow::exprNode(fc), DataFlow::exprNode(gc.getAChild*())) + not exists(GuardCondition gc | + DataFlow::localFlow(DataFlow::exprNode(fc), DataFlow::exprNode(gc.getAChild*())) ) and message = "Return value is not tested for errors." } From 7e5ef5f8306fee09522415cfda8cf708d8a32ea0 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 30 Jan 2024 09:55:42 +0000 Subject: [PATCH 006/370] Add name of function to message. --- .../FunctionErroneousReturnValueNotTested.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.qll b/cpp/common/src/codingstandards/cpp/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.qll index 5cd98c05d6..dd2f7d75e0 100644 --- a/cpp/common/src/codingstandards/cpp/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.qll +++ b/cpp/common/src/codingstandards/cpp/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.qll @@ -58,5 +58,5 @@ query predicate problems(FunctionCall fc, string message) { not exists(GuardCondition gc | DataFlow::localFlow(DataFlow::exprNode(fc), DataFlow::exprNode(gc.getAChild*())) ) and - message = "Return value is not tested for errors." + message = "Return value from " + fc.getTarget().getName() + " is not tested for errors." } From a19855bd20ace838d2f7748f45de341e5e7b97ef Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 30 Jan 2024 10:02:11 +0000 Subject: [PATCH 007/370] Add implementation scope properties Specify the scope of each of the newly supported rules. --- rule_packages/c/Contracts.json | 15 ++++++++++++--- rule_packages/c/FloatingTypes.json | 5 ++++- rule_packages/cpp/Expressions.json | 5 ++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/rule_packages/c/Contracts.json b/rule_packages/c/Contracts.json index e2239908f0..735e84d9da 100644 --- a/rule_packages/c/Contracts.json +++ b/rule_packages/c/Contracts.json @@ -14,7 +14,10 @@ "short_name": "DoNotViolateInLineLinkageConstraints", "tags": [ "correctness" - ] + ], + "implementation_scope": { + "description": "This query only considers the constraints related to inline extern functions." + } } ], "title": "Do not violate constraints" @@ -36,7 +39,10 @@ "shared_implementation_short_name": "UncheckedRangeDomainPoleErrors", "tags": [ "correctness" - ] + ], + "implementation_scope": { + "description": "This query identifies possible domain, pole and range errors on a selection of C standard library fuctions from math.h." + } } ], "title": "The validity of values passed to library functions shall be checked" @@ -56,7 +62,10 @@ "shared_implementation_short_name": "FunctionErroneousReturnValueNotTested", "tags": [ "maintainability" - ] + ], + "implementation_scope": { + "description": "This query enforces checking on some C standard library functions that may return error codes." + } } ], "title": "If a function returns error information, then that error information shall be tested" diff --git a/rule_packages/c/FloatingTypes.json b/rule_packages/c/FloatingTypes.json index 1dfd663597..7df2298ad1 100644 --- a/rule_packages/c/FloatingTypes.json +++ b/rule_packages/c/FloatingTypes.json @@ -15,7 +15,10 @@ "shared_implementation_short_name": "UncheckedRangeDomainPoleErrors", "tags": [ "correctness" - ] + ], + "implementation_scope": { + "description": "This query identifies possible domain, pole and range errors on a selection of C standard library fuctions from math.h." + } } ], "title": "Prevent or detect domain and range errors in math functions" diff --git a/rule_packages/cpp/Expressions.json b/rule_packages/cpp/Expressions.json index 5668c78a0a..935c3fa6f1 100644 --- a/rule_packages/cpp/Expressions.json +++ b/rule_packages/cpp/Expressions.json @@ -89,7 +89,10 @@ "shared_implementation_short_name": "FunctionErroneousReturnValueNotTested", "tags": [ "maintainability" - ] + ], + "implementation_scope": { + "description": "The query enforces checking on some C standard library functions that may return error codes." + } } ], "title": "If a function generates error information, then that error information shall be tested." From 9b7102e149ad57a8b45f6b09b5df452d731f1f2c Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 30 Jan 2024 10:03:21 +0000 Subject: [PATCH 008/370] Add change note. --- change_notes/2024-01-30-m0-3-2.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 change_notes/2024-01-30-m0-3-2.md diff --git a/change_notes/2024-01-30-m0-3-2.md b/change_notes/2024-01-30-m0-3-2.md new file mode 100644 index 0000000000..b074f6b2b1 --- /dev/null +++ b/change_notes/2024-01-30-m0-3-2.md @@ -0,0 +1 @@ + * `M0-3-2` - the alert messages now include the name of the called function. \ No newline at end of file From 78d5e793b66136c9ea7eec6c3da011d0af335011 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 30 Jan 2024 11:33:02 +0000 Subject: [PATCH 009/370] Add missing file. --- .../rules/M0-3-2/FunctionErroneousReturnValueNotTested.testref | 1 + 1 file changed, 1 insertion(+) create mode 100644 cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.testref diff --git a/cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.testref b/cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.testref new file mode 100644 index 0000000000..50847523ce --- /dev/null +++ b/cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.testref @@ -0,0 +1 @@ +cpp/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.ql \ No newline at end of file From 9776de1211801f333c827630352daf9bef931455 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 30 Jan 2024 12:58:50 +0000 Subject: [PATCH 010/370] Update expected result files. --- .../FunctionErroneousReturnValueNotTested.expected | 2 +- .../FunctionErroneousReturnValueNotTested.expected | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/c/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.expected b/c/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.expected index 015f52348c..dc72201a8a 100644 --- a/c/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.expected +++ b/c/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.expected @@ -1 +1 @@ -| test.c:16:3:16:8 | call to remove | Return value is not tested for errors. | +| test.c:16:3:16:8 | call to remove | Return value from remove is not tested for errors. | diff --git a/cpp/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.expected b/cpp/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.expected index 76cbcebed0..2f681c9210 100644 --- a/cpp/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.expected +++ b/cpp/common/test/rules/functionerroneousreturnvaluenottested/FunctionErroneousReturnValueNotTested.expected @@ -1 +1 @@ -| test.cpp:16:3:16:8 | call to remove | Return value is not tested for errors. | +| test.cpp:16:3:16:8 | call to remove | Return value from remove is not tested for errors. | From af9226208ee43cb49f0940a36972be3061ca7c01 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 30 Jan 2024 13:00:51 +0000 Subject: [PATCH 011/370] Update rules.csv to exclude unimplemented contracts rules. --- rules.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules.csv b/rules.csv index 20af9fbc01..9f4afac4fa 100644 --- a/rules.csv +++ b/rules.csv @@ -614,8 +614,8 @@ c,MISRA-C-2012,DIR-4-9,Yes,Advisory,,,A function should be used in preference to c,MISRA-C-2012,DIR-4-10,Yes,Required,,,Precautions shall be taken in order to prevent the contents of a header file being included more than once,M16-2-3,Preprocessor2,Medium, c,MISRA-C-2012,DIR-4-11,Yes,Required,,,The validity of values passed to library functions shall be checked,,Contracts,Hard, c,MISRA-C-2012,DIR-4-12,Yes,Required,,,Dynamic memory allocation shall not be used,,Banned,Medium, -c,MISRA-C-2012,DIR-4-13,Yes,Advisory,,,Functions which are designed to provide operations on a resource should be called in an appropriate sequence,,Contracts,Hard, -c,MISRA-C-2012,DIR-4-14,Yes,Required,,,The validity of values received from external sources shall be checked,,Contracts,Hard, +c,MISRA-C-2012,DIR-4-13,No,Advisory,,,Functions which are designed to provide operations on a resource should be called in an appropriate sequence,,,,Rule 22.1, 22.2 and 22.6 cover aspects of this rule. In other cases this is a design issue and needs to be checked manually. +c,MISRA-C-2012,DIR-4-14,Yes,Required,,,The validity of values received from external sources shall be checked,,Contracts9,Hard,This is supported by CodeQLs default C security queries. c,MISRA-C-2012,RULE-1-1,No,Required,,,"The program shall contain no violations of the standard C syntax and constraints, and shall not exceed the implementation's translation limits",,,Easy,"This should be checked via the compiler output, rather than CodeQL, which adds unnecessary steps." c,MISRA-C-2012,RULE-1-2,Yes,Advisory,,,Language extensions should not be used,,Language3,Hard, c,MISRA-C-2012,RULE-1-3,Yes,Required,,,There shall be no occurrence of undefined or critical unspecified behaviour,,Language3,Hard, From 3d2cd94fd92681127dbb38fa0833150a2536eb00 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 30 Jan 2024 13:13:14 +0000 Subject: [PATCH 012/370] Update documentation. --- c/cert/src/rules/FLP32-C/UncheckedRangeDomainPoleErrors.md | 2 +- .../src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/c/cert/src/rules/FLP32-C/UncheckedRangeDomainPoleErrors.md b/c/cert/src/rules/FLP32-C/UncheckedRangeDomainPoleErrors.md index d6427b9081..ca24a02498 100644 --- a/c/cert/src/rules/FLP32-C/UncheckedRangeDomainPoleErrors.md +++ b/c/cert/src/rules/FLP32-C/UncheckedRangeDomainPoleErrors.md @@ -345,7 +345,7 @@ Independent( INT34-C, FLP32-C, INT33-C) CWE-682 = Union( FLP32-C, list) where li ## Implementation notes -None +This query identifies possible domain, pole and range errors on a selection of C standard library fuctions from math.h. ## References diff --git a/c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.md b/c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.md index 26545fb812..f767c91baf 100644 --- a/c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.md +++ b/c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.md @@ -203,7 +203,7 @@ Search for [vulnerabilities](https://wiki.sei.cmu.edu/confluence/display/c/BB.+D ## Implementation notes -None +This query only considers the constraints related to inline extern functions. ## References From bccdb93c2b7b0e2dcbe82feb134c0c0423ae9d81 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 30 Jan 2024 13:13:59 +0000 Subject: [PATCH 013/370] Fix formatting --- c/misra/src/rules/DIR-4-7/FunctionErrorInformationUntested.ql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/c/misra/src/rules/DIR-4-7/FunctionErrorInformationUntested.ql b/c/misra/src/rules/DIR-4-7/FunctionErrorInformationUntested.ql index b827e101e3..63236d422d 100644 --- a/c/misra/src/rules/DIR-4-7/FunctionErrorInformationUntested.ql +++ b/c/misra/src/rules/DIR-4-7/FunctionErrorInformationUntested.ql @@ -19,7 +19,8 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.rules.functionerroneousreturnvaluenottested.FunctionErroneousReturnValueNotTested -class FunctionErrorInformationUntestedQuery extends FunctionErroneousReturnValueNotTestedSharedQuery { +class FunctionErrorInformationUntestedQuery extends FunctionErroneousReturnValueNotTestedSharedQuery +{ FunctionErrorInformationUntestedQuery() { this = ContractsPackage::functionErrorInformationUntestedQuery() } From 337604e56719a36e6098e8b8b41114168e3ab39a Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 30 Jan 2024 13:14:37 +0000 Subject: [PATCH 014/370] Fix test formatting --- c/cert/test/rules/MSC40-C/test.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/c/cert/test/rules/MSC40-C/test.c b/c/cert/test/rules/MSC40-C/test.c index 3ca4afff4a..d892935d41 100644 --- a/c/cert/test/rules/MSC40-C/test.c +++ b/c/cert/test/rules/MSC40-C/test.c @@ -4,28 +4,28 @@ const int g3 = 1; // defaults to internal linkage extern inline void test1() { static int i = 0; // NON_COMPLIANT - g1++; // NON_COMPLIANT - g2++; // COMPLIANT - g3; // NON_COMPLIANT + g1++; // NON_COMPLIANT + g2++; // COMPLIANT + g3; // NON_COMPLIANT } extern void test2() { static int i = 0; // COMPLIANT - g1++; // COMPLIANT - g2++; // COMPLIANT - g3; // COMPLIANT + g1++; // COMPLIANT + g2++; // COMPLIANT + g3; // COMPLIANT } void test3() { static int i = 0; // COMPLIANT - g1++; // COMPLIANT - g2++; // COMPLIANT - g3; // COMPLIANT + g1++; // COMPLIANT + g2++; // COMPLIANT + g3; // COMPLIANT } inline void test4() { static int i = 0; // NON_COMPLIANT - g1++; // NON_COMPLIANT - g2++; // COMPLIANT - g3; // NON_COMPLIANT + g1++; // NON_COMPLIANT + g2++; // COMPLIANT + g3; // NON_COMPLIANT } \ No newline at end of file From 1f9bc6b4445ae3203a7c11e3ff6ecdfe5f16ed4f Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Wed, 13 Mar 2024 15:12:34 +0000 Subject: [PATCH 015/370] Remove the copy of DataFlow that was added in 6aee03ef5ac577d77fbf034a46a6637f31aefbee now that the 'absolute path' problem has been fixed. --- ...interArithmeticOnNonArrayObjectPointers.ql | 2 +- ...otAddOrSubtractAScaledIntegerToAPointer.ql | 2 +- .../CON30-C/CleanUpThreadSpecificStorage.ql | 4 +- ...AppropriateThreadObjectStorageDurations.ql | 4 +- ...eadObjectStorageDurationsNotInitialized.ql | 4 +- ...propriateStorageDurationsFunctionReturn.ql | 2 +- .../ERR30-C/FunctionCallBeforeErrnoCheck.ql | 2 +- ...nOrderOfFunctionArgumentsForSideEffects.ql | 4 +- ...PointerToMoreStrictlyAlignedPointerType.ql | 2 +- ...CallFunctionPointerWithIncompatibleType.ql | 2 +- ...essVariableViaPointerOfIncompatibleType.ql | 2 +- .../EXP40-C/DoNotModifyConstantObjects.ql | 2 +- ...sAliasedPointerToRestrictQualifiedParam.ql | 2 +- ...trictPointerReferencesOverlappingObject.ql | 2 +- ...sfulFgetsOrFgetwsMayReturnAnEmptyString.ql | 2 +- ...uesForFsetposThatAreReturnedFromFgetpos.ql | 2 +- ...ToctouRaceConditionsWhileAccessingFiles.ql | 2 +- .../InsufficientMemoryAllocatedForObject.ql | 2 +- ...DoNotModifyAlignmentOfMemoryWithRealloc.ql | 2 +- ...oNotPassInvalidDataToTheAsctimeFunction.ql | 2 +- ...ArgOnAVaListThatHasAnIndeterminateValue.ql | 2 +- ...yAsyncSafeFunctionsWithinSignalHandlers.ql | 2 +- ...eturnFromAComputationalExceptionHandler.ql | 2 +- .../DoNotAttemptToModifyStringLiterals.ql | 2 +- ...sHasSufficientSpaceForTheNullTerminator.ql | 2 +- ...lTerminatedToFunctionThatExpectsAString.ql | 2 +- c/common/src/codingstandards/c/Errno.qll | 2 +- .../src/codingstandards/c/OutOfBounds.qll | 2 +- c/common/src/codingstandards/c/Signal.qll | 2 +- .../ArrayFunctionArgumentNumberOfElements.ql | 2 +- .../ValueReturnedByAFunctionNotUsed.ql | 2 +- .../ObjectCopiedToAnOverlappingObject.ql | 2 +- ...emcmpUsedToCompareNullTerminatedStrings.ql | 2 +- ...leOpenForReadAndWriteOnDifferentStreams.ql | 2 +- .../AttemptToWriteToAReadOnlyStream.ql | 2 +- ...OnlyPerformConversionOfPassedParameters.ql | 2 +- .../A13-2-1/AssignmentOperatorReturnThis.ql | 2 +- .../A15-1-3/ThrownExceptionsShouldBeUnique.ql | 2 +- ...structorErrorLeavesObjectInInvalidState.ql | 2 +- ...AnElementOfAnArrayPassedToASmartPointer.ql | 2 +- .../rules/A18-5-2/DoNotUseNonPlacementNew.ql | 2 +- .../A18-5-8/UnnecessaryUseOfDynamicStorage.ql | 2 +- .../ArgumentToForwardSubsequentlyUsed.ql | 2 +- ...SharedPointerUsedWithNoOwnershipSharing.ql | 2 +- .../src/rules/A27-0-4/CStyleStringsUsed.ql | 2 +- ...hmeticUsedWithPointersToNonFinalClasses.ql | 2 +- .../rules/A5-1-7/LambdaPassedToDecltype.ql | 2 +- .../src/rules/A5-1-7/LambdaPassedToTypeid.ql | 2 +- .../rules/A7-5-1/InvalidFunctionReturnType.ql | 2 +- ...nterAsParameterWithoutLifetimeSemantics.ql | 2 +- ...trPassedToFunctionWithImproperSemantics.ql | 2 +- .../FunctionReturnMultipleValueCondition.ql | 2 +- ...ersOrReferencesToPrivateOrProtectedData.ql | 2 +- .../FunctionErroneousReturnValueNotTested.ql | 2 +- ...epresentationsOfFloatingPointValuesUsed.ql | 2 +- .../PointerSubtractionOnDifferentArrays.ql | 2 +- ...ointerToAVirtualBaseClassCastToAPointer.ql | 2 +- ...nstMemberFunctionReturnsNonConstPointer.ql | 2 +- ...GenericCppLibraryFunctionsDoNotOverflow.ql | 2 +- ...sePointerArithmeticOnPolymorphicObjects.ql | 2 +- ...fectsInFunctionCallsAsFunctionArguments.ql | 4 +- ...nArrayThroughAPointerOfTheIncorrectType.ql | 2 +- .../DetectAndHandleMemoryAllocationErrors.ql | 2 +- .../MEM53-CPP/ManuallyManagedLifetime.qll | 2 +- ...ConstructorCallForManuallyManagedObject.ql | 2 +- ...gDestructorCallForManuallyManagedObject.ql | 2 +- .../BadlySeededRandomNumberGenerator.ql | 2 +- .../src/codingstandards/cpp/AccessPath.qll | 2 +- .../src/codingstandards/cpp/Allocations.qll | 2 +- .../src/codingstandards/cpp/Concurrency.qll | 2 +- .../src/codingstandards/cpp/ConstHelpers.qll | 2 +- .../cpp/FgetsErrorManagement.qll | 2 +- .../src/codingstandards/cpp/Iterators.qll | 4 +- .../src/codingstandards/cpp/Nullness.qll | 2 +- .../src/codingstandards/cpp/Overflow.qll | 2 +- .../codingstandards/cpp/ReadErrorsAndEOF.qll | 2 +- .../src/codingstandards/cpp/SideEffect.qll | 2 +- .../src/codingstandards/cpp/SmartPointers.qll | 2 +- .../cpp/allocations/PlacementNew.qll | 2 +- .../codingstandards/cpp/dataflow/DataFlow.qll | 36 ------------------ .../cpp/dataflow/DataFlow2.qll | 25 ------------- .../cpp/dataflow/TaintTracking.qll | 37 ------------------- .../tainttracking1/TaintTrackingParameter.qll | 6 --- .../lifetimeprofile/LifetimeProfile.qll | 2 +- .../cpp/resources/ResourceManagement.qll | 2 +- ...onExistingMemberThroughPointerToMember.qll | 2 +- ...essOfUndefinedMemberThroughNullPointer.qll | 2 +- ...emberThroughUninitializedStaticPointer.qll | 2 +- .../BasicStringMayNotBeNullTerminated.qll | 4 +- .../ConstLikeReturnValue.qll | 2 +- .../ContainerAccessWithoutRangeCheck.qll | 2 +- .../DanglingCaptureWhenMovingLambdaObject.qll | 2 +- ...nglingCaptureWhenReturningLambdaObject.qll | 2 +- .../DoNotAccessAClosedFile.qll | 2 +- ...otAllowAMutexToGoOutOfScopeWhileLocked.qll | 2 +- .../DoNotDestroyAMutexWhileItIsLocked.qll | 2 +- ...tractPointersAddressingDifferentArrays.qll | 2 +- ...nterArithmeticToAddressDifferentArrays.qll | 2 +- ...RelationalOperatorsWithDifferingArrays.qll | 2 +- .../InvalidatedEnvStringPointers.qll | 2 +- .../InvalidatedEnvStringPointersWarn.qll | 2 +- .../IOFstreamMissingPositioning.qll | 2 +- .../MovedFromObjectsUnspecifiedState.qll | 2 +- .../nonconstantformat/NonConstantFormat.qll | 2 +- ...lyFreeMemoryAllocatedDynamicallyShared.qll | 2 +- ...nterValueStoredInUnrelatedSmartPointer.qll | 2 +- .../PlacementNewInsufficientStorage.qll | 2 +- .../PlacementNewNotProperlyAligned.qll | 2 +- ...tringNumberConversionMissingErrorCheck.qll | 2 +- .../ThrowingOperatorNewReturnsNull.qll | 2 +- ...eOnlyArrayIndexingForPointerArithmetic.qll | 2 +- .../cpp/standardlibrary/FileStreams.qll | 4 +- .../cpp/trustboundary/UninitializedField.qll | 2 +- .../UnusedReturnValue.ql | 2 +- .../UnusedReturnValue.ql | 2 +- .../UnusedReturnValue.ql | 2 +- 116 files changed, 120 insertions(+), 224 deletions(-) delete mode 100644 cpp/common/src/codingstandards/cpp/dataflow/DataFlow.qll delete mode 100644 cpp/common/src/codingstandards/cpp/dataflow/DataFlow2.qll delete mode 100644 cpp/common/src/codingstandards/cpp/dataflow/TaintTracking.qll delete mode 100644 cpp/common/src/codingstandards/cpp/dataflow/internal/tainttracking1/TaintTrackingParameter.qll diff --git a/c/cert/src/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql b/c/cert/src/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql index 2f8ecec25d..0ddf56150c 100644 --- a/c/cert/src/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql +++ b/c/cert/src/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import NonArrayPointerToArrayIndexingExprFlow::PathGraph /** diff --git a/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql b/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql index c641c17124..d832eb6014 100644 --- a/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql +++ b/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.cert import codingstandards.c.Pointers -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking import ScaledIntegerPointerArithmeticFlow::PathGraph /** diff --git a/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql b/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql index 59fab6e455..d55f1326bf 100644 --- a/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql +++ b/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql @@ -15,8 +15,8 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.Concurrency -import codingstandards.cpp.dataflow.TaintTracking -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.DataFlow module TssCreateToTssDeleteConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node node) { diff --git a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql index e0617c266d..71138f4ff8 100644 --- a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql +++ b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql @@ -15,8 +15,8 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.Concurrency -import codingstandards.cpp.dataflow.TaintTracking -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.commons.Alloc from C11ThreadCreateCall tcc, StackVariable sv, Expr arg, Expr acc diff --git a/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql b/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql index 0fd94911ec..ddcddb8dc5 100644 --- a/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql +++ b/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql @@ -16,8 +16,8 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.Concurrency -import codingstandards.cpp.dataflow.TaintTracking -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.DataFlow from TSSGetFunctionCall tsg, ThreadedFunction tf where diff --git a/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql b/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql index 9097f14297..b5d7e5e378 100644 --- a/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql +++ b/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow class Source extends StackVariable { Source() { not this instanceof Parameter } diff --git a/c/cert/src/rules/ERR30-C/FunctionCallBeforeErrnoCheck.ql b/c/cert/src/rules/ERR30-C/FunctionCallBeforeErrnoCheck.ql index 8d63bb5d06..dd2e2175f7 100644 --- a/c/cert/src/rules/ERR30-C/FunctionCallBeforeErrnoCheck.ql +++ b/c/cert/src/rules/ERR30-C/FunctionCallBeforeErrnoCheck.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.cert import codingstandards.c.Errno -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow /** * A call to an `OutOfBandErrnoSettingFunction` diff --git a/c/cert/src/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.ql b/c/cert/src/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.ql index bf8f99fd27..fb14515c61 100644 --- a/c/cert/src/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.ql +++ b/c/cert/src/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.ql @@ -14,8 +14,8 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.SideEffect -import codingstandards.cpp.dataflow.DataFlow -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.TaintTracking import semmle.code.cpp.valuenumbering.GlobalValueNumbering /** Holds if the function's return value is derived from the `AliasParamter` p. */ diff --git a/c/cert/src/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.ql b/c/cert/src/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.ql index e5735a5fda..f3b3aa364d 100644 --- a/c/cert/src/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.ql +++ b/c/cert/src/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.Alignment -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis import ExprWithAlignmentToCStyleCastFlow::PathGraph diff --git a/c/cert/src/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.ql b/c/cert/src/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.ql index e28dbddaaf..9bbe27aa31 100644 --- a/c/cert/src/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.ql +++ b/c/cert/src/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import SuspectFunctionPointerToCallFlow::PathGraph /** diff --git a/c/cert/src/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.ql b/c/cert/src/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.ql index 825f85b0bd..fde564665c 100644 --- a/c/cert/src/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.ql +++ b/c/cert/src/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.controlflow.Dominance import IndirectCastFlow::PathGraph diff --git a/c/cert/src/rules/EXP40-C/DoNotModifyConstantObjects.ql b/c/cert/src/rules/EXP40-C/DoNotModifyConstantObjects.ql index d79224435f..20c9f1bcc8 100644 --- a/c/cert/src/rules/EXP40-C/DoNotModifyConstantObjects.ql +++ b/c/cert/src/rules/EXP40-C/DoNotModifyConstantObjects.ql @@ -12,7 +12,7 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import CastFlow::PathGraph import codingstandards.cpp.SideEffect diff --git a/c/cert/src/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.ql b/c/cert/src/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.ql index a4cc4e8944..1b792d16d5 100644 --- a/c/cert/src/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.ql +++ b/c/cert/src/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.cert import codingstandards.c.Pointers import codingstandards.c.Variable -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.pointsto.PointsTo import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis diff --git a/c/cert/src/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.ql b/c/cert/src/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.ql index bbe41259b8..f220401c82 100644 --- a/c/cert/src/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.ql +++ b/c/cert/src/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.ql @@ -11,7 +11,7 @@ */ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.controlflow.Dominance import codingstandards.c.cert import codingstandards.c.Variable diff --git a/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql b/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql index 2dce0d465c..54f555d7cb 100644 --- a/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql +++ b/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.FgetsErrorManagement import codingstandards.cpp.Dereferenced -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking /* * CFG nodes that follows a successful call to `fgets` diff --git a/c/cert/src/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql b/c/cert/src/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql index 33a906136f..7ed5887e42 100644 --- a/c/cert/src/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql +++ b/c/cert/src/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql @@ -12,7 +12,7 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow class FgetposCall extends FunctionCall { FgetposCall() { this.getTarget().hasGlobalOrStdName("fgetpos") } diff --git a/c/cert/src/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.ql b/c/cert/src/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.ql index 2ddfa6cf4c..b02ce2f58d 100644 --- a/c/cert/src/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.ql +++ b/c/cert/src/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.standardlibrary.FileAccess -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.valuenumbering.GlobalValueNumbering /** diff --git a/c/cert/src/rules/MEM35-C/InsufficientMemoryAllocatedForObject.ql b/c/cert/src/rules/MEM35-C/InsufficientMemoryAllocatedForObject.ql index 7683140327..5ff1725269 100644 --- a/c/cert/src/rules/MEM35-C/InsufficientMemoryAllocatedForObject.ql +++ b/c/cert/src/rules/MEM35-C/InsufficientMemoryAllocatedForObject.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.Overflow import semmle.code.cpp.controlflow.Guards -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking import semmle.code.cpp.models.Models /** diff --git a/c/cert/src/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.ql b/c/cert/src/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.ql index 512b783030..df0eb3b1e3 100644 --- a/c/cert/src/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.ql +++ b/c/cert/src/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.Alignment -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import AlignedAllocToReallocFlow::PathGraph int getStatedValue(Expr e) { diff --git a/c/cert/src/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.ql b/c/cert/src/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.ql index 52dd0b1046..fa4a29cb3d 100644 --- a/c/cert/src/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.ql +++ b/c/cert/src/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow /** * The argument of a call to `asctime` diff --git a/c/cert/src/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql b/c/cert/src/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql index 821b79c8e4..338dc83308 100644 --- a/c/cert/src/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql +++ b/c/cert/src/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.Macro -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow abstract class VaAccess extends Expr { } diff --git a/c/cert/src/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql b/c/cert/src/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql index 19730b4677..0da48daa70 100644 --- a/c/cert/src/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql +++ b/c/cert/src/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.cert import codingstandards.c.Signal -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow /** * Does not access an external variable except diff --git a/c/cert/src/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.ql b/c/cert/src/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.ql index 5a064c0904..fa3cc3bf14 100644 --- a/c/cert/src/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.ql +++ b/c/cert/src/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.cert import codingstandards.c.Signal -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow /** * CFG nodes preceeding a `ReturnStmt` diff --git a/c/cert/src/rules/STR30-C/DoNotAttemptToModifyStringLiterals.ql b/c/cert/src/rules/STR30-C/DoNotAttemptToModifyStringLiterals.ql index 40f19ed4a0..244fe6d8e5 100644 --- a/c/cert/src/rules/STR30-C/DoNotAttemptToModifyStringLiterals.ql +++ b/c/cert/src/rules/STR30-C/DoNotAttemptToModifyStringLiterals.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.cert import semmle.code.cpp.security.BufferWrite -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow /** * Class that includes into `BufferWrite` functions that will modify their diff --git a/c/cert/src/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.ql b/c/cert/src/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.ql index 4e2e48708a..3742207720 100644 --- a/c/cert/src/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.ql +++ b/c/cert/src/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking import codingstandards.cpp.PossiblyUnsafeStringOperation /** diff --git a/c/cert/src/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.ql b/c/cert/src/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.ql index d661edade5..365136f99d 100644 --- a/c/cert/src/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.ql +++ b/c/cert/src/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.Naming -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking import codingstandards.cpp.PossiblyUnsafeStringOperation /** diff --git a/c/common/src/codingstandards/c/Errno.qll b/c/common/src/codingstandards/c/Errno.qll index 86ecabe8f1..d606593a1e 100644 --- a/c/common/src/codingstandards/c/Errno.qll +++ b/c/common/src/codingstandards/c/Errno.qll @@ -1,7 +1,7 @@ /** Provides a library for errno-setting functions. */ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow /** * An errno-setting function diff --git a/c/common/src/codingstandards/c/OutOfBounds.qll b/c/common/src/codingstandards/c/OutOfBounds.qll index 87c7c17870..92d519699c 100644 --- a/c/common/src/codingstandards/c/OutOfBounds.qll +++ b/c/common/src/codingstandards/c/OutOfBounds.qll @@ -11,7 +11,7 @@ import codingstandards.cpp.Allocations import codingstandards.cpp.Overflow import codingstandards.cpp.PossiblyUnsafeStringOperation import codingstandards.cpp.SimpleRangeAnalysisCustomizations -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.valuenumbering.GlobalValueNumbering module OOB { diff --git a/c/common/src/codingstandards/c/Signal.qll b/c/common/src/codingstandards/c/Signal.qll index 35286be4d9..95b27e2898 100644 --- a/c/common/src/codingstandards/c/Signal.qll +++ b/c/common/src/codingstandards/c/Signal.qll @@ -1,5 +1,5 @@ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow /** * A signal corresponding to a computational exception diff --git a/c/misra/src/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.ql b/c/misra/src/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.ql index 208e8153d6..a6f5f2c1a2 100644 --- a/c/misra/src/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.ql +++ b/c/misra/src/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow /** * Models a function parameter of type array with specified size diff --git a/c/misra/src/rules/RULE-17-7/ValueReturnedByAFunctionNotUsed.ql b/c/misra/src/rules/RULE-17-7/ValueReturnedByAFunctionNotUsed.ql index 02d0a54ec1..3b224544f2 100644 --- a/c/misra/src/rules/RULE-17-7/ValueReturnedByAFunctionNotUsed.ql +++ b/c/misra/src/rules/RULE-17-7/ValueReturnedByAFunctionNotUsed.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow from Call c where diff --git a/c/misra/src/rules/RULE-19-1/ObjectCopiedToAnOverlappingObject.ql b/c/misra/src/rules/RULE-19-1/ObjectCopiedToAnOverlappingObject.ql index bee9b41e2c..fe1226dcea 100644 --- a/c/misra/src/rules/RULE-19-1/ObjectCopiedToAnOverlappingObject.ql +++ b/c/misra/src/rules/RULE-19-1/ObjectCopiedToAnOverlappingObject.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.c.misra import semmle.code.cpp.valuenumbering.GlobalValueNumbering -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow /** * Offset in bytes of a field access diff --git a/c/misra/src/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.ql b/c/misra/src/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.ql index 44e21d14db..ec1470a8ec 100644 --- a/c/misra/src/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.ql +++ b/c/misra/src/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.c.misra import codingstandards.c.misra.EssentialTypes -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking import NullTerminatedStringToMemcmpFlow::PathGraph // Data flow from a StringLiteral or from an array of characters, to a memcmp call diff --git a/c/misra/src/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.ql b/c/misra/src/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.ql index c01afea39f..877fbea9aa 100644 --- a/c/misra/src/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.ql +++ b/c/misra/src/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.standardlibrary.FileAccess -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.valuenumbering.GlobalValueNumbering import semmle.code.cpp.controlflow.SubBasicBlocks diff --git a/c/misra/src/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.ql b/c/misra/src/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.ql index 6dc3b3ee71..8c27b936b8 100644 --- a/c/misra/src/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.ql +++ b/c/misra/src/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.standardlibrary.FileAccess -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow module FileDFConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { diff --git a/cpp/autosar/src/rules/A13-1-3/UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.ql b/cpp/autosar/src/rules/A13-1-3/UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.ql index 840d7423fb..4593065e01 100644 --- a/cpp/autosar/src/rules/A13-1-3/UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.ql +++ b/cpp/autosar/src/rules/A13-1-3/UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.ql @@ -14,7 +14,7 @@ */ import cpp -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking import codingstandards.cpp.autosar import codingstandards.cpp.UserDefinedLiteral as udl import codingstandards.cpp.SideEffect diff --git a/cpp/autosar/src/rules/A13-2-1/AssignmentOperatorReturnThis.ql b/cpp/autosar/src/rules/A13-2-1/AssignmentOperatorReturnThis.ql index ae0acc3bb5..4e6b7d6f0c 100644 --- a/cpp/autosar/src/rules/A13-2-1/AssignmentOperatorReturnThis.ql +++ b/cpp/autosar/src/rules/A13-2-1/AssignmentOperatorReturnThis.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.cpp.autosar import codingstandards.cpp.Operator -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow predicate returnsThisPointer(UserAssignmentOperator o) { exists(PointerDereferenceExpr p, ThisExpr t, ReturnStmt r | diff --git a/cpp/autosar/src/rules/A15-1-3/ThrownExceptionsShouldBeUnique.ql b/cpp/autosar/src/rules/A15-1-3/ThrownExceptionsShouldBeUnique.ql index 1459b79b43..97e9133a7a 100644 --- a/cpp/autosar/src/rules/A15-1-3/ThrownExceptionsShouldBeUnique.ql +++ b/cpp/autosar/src/rules/A15-1-3/ThrownExceptionsShouldBeUnique.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.cpp.autosar import codingstandards.cpp.exceptions.ExceptionFlow -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.valuenumbering.HashCons /** Find a value which defines the exception thrown by the `DirectThrowExpr`, if any. */ diff --git a/cpp/autosar/src/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.ql b/cpp/autosar/src/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.ql index 9fcd8fa609..1b3a3cfed2 100644 --- a/cpp/autosar/src/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.ql +++ b/cpp/autosar/src/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.ql @@ -15,7 +15,7 @@ */ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.autosar import codingstandards.cpp.exceptions.ExceptionFlow import codingstandards.cpp.exceptions.ExceptionSpecifications diff --git a/cpp/autosar/src/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.ql b/cpp/autosar/src/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.ql index 842dc14390..353c985137 100644 --- a/cpp/autosar/src/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.ql +++ b/cpp/autosar/src/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.cpp.autosar import codingstandards.cpp.SmartPointers -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking import SingleObjectSmartPointerArrayConstructionFlow::PathGraph class AutosarSmartPointerArraySpecialisation extends AutosarSmartPointer { diff --git a/cpp/autosar/src/rules/A18-5-2/DoNotUseNonPlacementNew.ql b/cpp/autosar/src/rules/A18-5-2/DoNotUseNonPlacementNew.ql index 082827f5bb..1320d6e486 100644 --- a/cpp/autosar/src/rules/A18-5-2/DoNotUseNonPlacementNew.ql +++ b/cpp/autosar/src/rules/A18-5-2/DoNotUseNonPlacementNew.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow from NewOrNewArrayExpr na where diff --git a/cpp/autosar/src/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.ql b/cpp/autosar/src/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.ql index 979dc0824e..cdf35374f9 100644 --- a/cpp/autosar/src/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.ql +++ b/cpp/autosar/src/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking import codingstandards.cpp.standardlibrary.Utility /* diff --git a/cpp/autosar/src/rules/A18-9-4/ArgumentToForwardSubsequentlyUsed.ql b/cpp/autosar/src/rules/A18-9-4/ArgumentToForwardSubsequentlyUsed.ql index d87366c624..a3acf916ec 100644 --- a/cpp/autosar/src/rules/A18-9-4/ArgumentToForwardSubsequentlyUsed.ql +++ b/cpp/autosar/src/rules/A18-9-4/ArgumentToForwardSubsequentlyUsed.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.cpp.autosar import codingstandards.cpp.standardlibrary.Utility -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow from StdForwardCall f, Access a where diff --git a/cpp/autosar/src/rules/A20-8-4/SharedPointerUsedWithNoOwnershipSharing.ql b/cpp/autosar/src/rules/A20-8-4/SharedPointerUsedWithNoOwnershipSharing.ql index c7ff6f6bf2..0294bfe2e6 100644 --- a/cpp/autosar/src/rules/A20-8-4/SharedPointerUsedWithNoOwnershipSharing.ql +++ b/cpp/autosar/src/rules/A20-8-4/SharedPointerUsedWithNoOwnershipSharing.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.cpp.autosar import codingstandards.cpp.SmartPointers -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow /* * Finds `std::shared_ptr` local variables which are not copy or move initialized, and are not used in diff --git a/cpp/autosar/src/rules/A27-0-4/CStyleStringsUsed.ql b/cpp/autosar/src/rules/A27-0-4/CStyleStringsUsed.ql index b698ecf351..b24a4a96cf 100644 --- a/cpp/autosar/src/rules/A27-0-4/CStyleStringsUsed.ql +++ b/cpp/autosar/src/rules/A27-0-4/CStyleStringsUsed.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow class InstanceOfCStyleString extends Expr { InstanceOfCStyleString() { diff --git a/cpp/autosar/src/rules/A5-0-4/PointerArithmeticUsedWithPointersToNonFinalClasses.ql b/cpp/autosar/src/rules/A5-0-4/PointerArithmeticUsedWithPointersToNonFinalClasses.ql index 34b6660778..ac2375f6aa 100644 --- a/cpp/autosar/src/rules/A5-0-4/PointerArithmeticUsedWithPointersToNonFinalClasses.ql +++ b/cpp/autosar/src/rules/A5-0-4/PointerArithmeticUsedWithPointersToNonFinalClasses.ql @@ -17,7 +17,7 @@ import cpp import codingstandards.cpp.autosar import codingstandards.cpp.Type -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import NonFinalClassToPointerArithmeticExprFlow::PathGraph class ArrayAccessOrPointerArith extends Expr { diff --git a/cpp/autosar/src/rules/A5-1-7/LambdaPassedToDecltype.ql b/cpp/autosar/src/rules/A5-1-7/LambdaPassedToDecltype.ql index afbd809664..971d3b9259 100644 --- a/cpp/autosar/src/rules/A5-1-7/LambdaPassedToDecltype.ql +++ b/cpp/autosar/src/rules/A5-1-7/LambdaPassedToDecltype.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow module LambdaExpressionToInitializerConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source.asExpr() instanceof LambdaExpression } diff --git a/cpp/autosar/src/rules/A5-1-7/LambdaPassedToTypeid.ql b/cpp/autosar/src/rules/A5-1-7/LambdaPassedToTypeid.ql index 08dbecc755..56952dace9 100644 --- a/cpp/autosar/src/rules/A5-1-7/LambdaPassedToTypeid.ql +++ b/cpp/autosar/src/rules/A5-1-7/LambdaPassedToTypeid.ql @@ -14,7 +14,7 @@ */ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.autosar import LambdaExpressionToTypeidFlow::PathGraph diff --git a/cpp/autosar/src/rules/A7-5-1/InvalidFunctionReturnType.ql b/cpp/autosar/src/rules/A7-5-1/InvalidFunctionReturnType.ql index 6994ab028f..c36bda6cdd 100644 --- a/cpp/autosar/src/rules/A7-5-1/InvalidFunctionReturnType.ql +++ b/cpp/autosar/src/rules/A7-5-1/InvalidFunctionReturnType.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow from Parameter p, ReturnStmt ret where diff --git a/cpp/autosar/src/rules/A8-4-11/SmartPointerAsParameterWithoutLifetimeSemantics.ql b/cpp/autosar/src/rules/A8-4-11/SmartPointerAsParameterWithoutLifetimeSemantics.ql index 811d98eccb..0bf42ce4ca 100644 --- a/cpp/autosar/src/rules/A8-4-11/SmartPointerAsParameterWithoutLifetimeSemantics.ql +++ b/cpp/autosar/src/rules/A8-4-11/SmartPointerAsParameterWithoutLifetimeSemantics.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.cpp.autosar import codingstandards.cpp.SmartPointers -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.standardlibrary.Utility Expr lifetimeAffectingSmartPointerExpr(Function f) { diff --git a/cpp/autosar/src/rules/A8-4-12/UniquePtrPassedToFunctionWithImproperSemantics.ql b/cpp/autosar/src/rules/A8-4-12/UniquePtrPassedToFunctionWithImproperSemantics.ql index 5dec96ed81..3cd310b59b 100644 --- a/cpp/autosar/src/rules/A8-4-12/UniquePtrPassedToFunctionWithImproperSemantics.ql +++ b/cpp/autosar/src/rules/A8-4-12/UniquePtrPassedToFunctionWithImproperSemantics.ql @@ -18,7 +18,7 @@ import cpp import codingstandards.cpp.autosar import codingstandards.cpp.SmartPointers import codingstandards.cpp.standardlibrary.Utility -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow Expr underlyingObjectAffectingUniquePointerExpr(Function f) { result = diff --git a/cpp/autosar/src/rules/A8-4-4/FunctionReturnMultipleValueCondition.ql b/cpp/autosar/src/rules/A8-4-4/FunctionReturnMultipleValueCondition.ql index fa38b1d3f6..ff0040f26f 100644 --- a/cpp/autosar/src/rules/A8-4-4/FunctionReturnMultipleValueCondition.ql +++ b/cpp/autosar/src/rules/A8-4-4/FunctionReturnMultipleValueCondition.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow abstract class OutputValue extends Element { abstract string getOutputName(); diff --git a/cpp/autosar/src/rules/A9-3-1/ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.ql b/cpp/autosar/src/rules/A9-3-1/ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.ql index f40faad3dd..478f8dcdf0 100644 --- a/cpp/autosar/src/rules/A9-3-1/ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.ql +++ b/cpp/autosar/src/rules/A9-3-1/ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.cpp.autosar import codingstandards.cpp.CommonTypes as CommonTypes -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow class AccessAwareMemberFunction extends MemberFunction { Class c; diff --git a/cpp/autosar/src/rules/M0-3-2/FunctionErroneousReturnValueNotTested.ql b/cpp/autosar/src/rules/M0-3-2/FunctionErroneousReturnValueNotTested.ql index aee4e40838..cd94d63ffc 100644 --- a/cpp/autosar/src/rules/M0-3-2/FunctionErroneousReturnValueNotTested.ql +++ b/cpp/autosar/src/rules/M0-3-2/FunctionErroneousReturnValueNotTested.ql @@ -19,7 +19,7 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.controlflow.Guards from FunctionCall fc diff --git a/cpp/autosar/src/rules/M3-9-3/UnderlyingBitRepresentationsOfFloatingPointValuesUsed.ql b/cpp/autosar/src/rules/M3-9-3/UnderlyingBitRepresentationsOfFloatingPointValuesUsed.ql index f7e6664269..279ad08f3c 100644 --- a/cpp/autosar/src/rules/M3-9-3/UnderlyingBitRepresentationsOfFloatingPointValuesUsed.ql +++ b/cpp/autosar/src/rules/M3-9-3/UnderlyingBitRepresentationsOfFloatingPointValuesUsed.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow predicate pointeeIsModified(PointerDereferenceExpr e, Expr m) { exists(Assignment a | a.getLValue() = e and m = a) diff --git a/cpp/autosar/src/rules/M5-0-17/PointerSubtractionOnDifferentArrays.ql b/cpp/autosar/src/rules/M5-0-17/PointerSubtractionOnDifferentArrays.ql index ec432cea42..d6d4f6130a 100644 --- a/cpp/autosar/src/rules/M5-0-17/PointerSubtractionOnDifferentArrays.ql +++ b/cpp/autosar/src/rules/M5-0-17/PointerSubtractionOnDifferentArrays.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import ArrayToPointerDiffOperandFlow::PathGraph module ArrayToPointerDiffOperandConfig implements DataFlow::ConfigSig { diff --git a/cpp/autosar/src/rules/M5-2-2/PointerToAVirtualBaseClassCastToAPointer.ql b/cpp/autosar/src/rules/M5-2-2/PointerToAVirtualBaseClassCastToAPointer.ql index 8f20bf808e..d24c4d35df 100644 --- a/cpp/autosar/src/rules/M5-2-2/PointerToAVirtualBaseClassCastToAPointer.ql +++ b/cpp/autosar/src/rules/M5-2-2/PointerToAVirtualBaseClassCastToAPointer.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow from Cast cast, VirtualBaseClass castFrom, Class castTo where diff --git a/cpp/autosar/src/rules/M9-3-1/ConstMemberFunctionReturnsNonConstPointer.ql b/cpp/autosar/src/rules/M9-3-1/ConstMemberFunctionReturnsNonConstPointer.ql index 98207a62a3..559b41527c 100644 --- a/cpp/autosar/src/rules/M9-3-1/ConstMemberFunctionReturnsNonConstPointer.ql +++ b/cpp/autosar/src/rules/M9-3-1/ConstMemberFunctionReturnsNonConstPointer.ql @@ -18,7 +18,7 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow class ReferenceTypeWithNonConstBaseType extends ReferenceType { ReferenceTypeWithNonConstBaseType() { not this.getBaseType().isConst() } diff --git a/cpp/cert/src/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql b/cpp/cert/src/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql index 720880dbe4..d60227d2c8 100644 --- a/cpp/cert/src/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql +++ b/cpp/cert/src/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql @@ -16,7 +16,7 @@ import codingstandards.cpp.cert import codingstandards.cpp.Iterators import codingstandards.cpp.rules.containeraccesswithoutrangecheck.ContainerAccessWithoutRangeCheck as ContainerAccessWithoutRangeCheck import semmle.code.cpp.controlflow.Guards -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking import semmle.code.cpp.valuenumbering.GlobalValueNumbering /** diff --git a/cpp/cert/src/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.ql b/cpp/cert/src/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.ql index a7756b6a6a..0f5c50164c 100644 --- a/cpp/cert/src/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.ql +++ b/cpp/cert/src/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.cpp.cert -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import NonFinalClassToPointerArithmeticExprFlow::PathGraph class ArrayAccessOrPointerArith extends Expr { diff --git a/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql b/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql index a385ee1ffc..7bfb298d3d 100644 --- a/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql +++ b/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql @@ -14,8 +14,8 @@ import cpp import codingstandards.cpp.cert import codingstandards.cpp.SideEffect -import codingstandards.cpp.dataflow.DataFlow -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.TaintTracking import semmle.code.cpp.valuenumbering.GlobalValueNumbering /** Holds if the function's return value is derived from the `AliasParamter` p. */ diff --git a/cpp/cert/src/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql b/cpp/cert/src/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql index bdf6a7973e..e900d1b259 100644 --- a/cpp/cert/src/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql +++ b/cpp/cert/src/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.cpp.cert -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import AllocationToDeleteFlow::PathGraph module AllocationToDeleteConfig implements DataFlow::ConfigSig { diff --git a/cpp/cert/src/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.ql b/cpp/cert/src/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.ql index c25e1aa0ad..083aad1e3c 100644 --- a/cpp/cert/src/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.ql +++ b/cpp/cert/src/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.cpp.cert import semmle.code.cpp.controlflow.Guards -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.exceptions.ExceptionSpecifications /** diff --git a/cpp/cert/src/rules/MEM53-CPP/ManuallyManagedLifetime.qll b/cpp/cert/src/rules/MEM53-CPP/ManuallyManagedLifetime.qll index 358a3583fc..413a4b0d3c 100644 --- a/cpp/cert/src/rules/MEM53-CPP/ManuallyManagedLifetime.qll +++ b/cpp/cert/src/rules/MEM53-CPP/ManuallyManagedLifetime.qll @@ -3,7 +3,7 @@ import codingstandards.cpp.Conversion import codingstandards.cpp.TrivialType import ManuallyManagedLifetime import semmle.code.cpp.controlflow.Dominance -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking /** * A taint-tracking configuration from allocation expressions to casts to a specific pointer type. diff --git a/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject.ql b/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject.ql index 30c5280482..6e3121e46d 100644 --- a/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject.ql +++ b/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.cpp.cert import codingstandards.cpp.TrivialType import ManuallyManagedLifetime -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking import AllocToStaticCastFlow::PathGraph /* diff --git a/cpp/cert/src/rules/MEM53-CPP/MissingDestructorCallForManuallyManagedObject.ql b/cpp/cert/src/rules/MEM53-CPP/MissingDestructorCallForManuallyManagedObject.ql index b498729d69..22e2ac336f 100644 --- a/cpp/cert/src/rules/MEM53-CPP/MissingDestructorCallForManuallyManagedObject.ql +++ b/cpp/cert/src/rules/MEM53-CPP/MissingDestructorCallForManuallyManagedObject.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.cpp.cert import ManuallyManagedLifetime -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import FreeWithoutDestructorFlow::PathGraph from FreeWithoutDestructorFlow::PathNode source, FreeWithoutDestructorFlow::PathNode sink diff --git a/cpp/cert/src/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.ql b/cpp/cert/src/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.ql index 52b14d9629..76f8500362 100644 --- a/cpp/cert/src/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.ql +++ b/cpp/cert/src/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.cpp.cert import codingstandards.cpp.standardlibrary.Random -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking from RandomNumberEngineCreation createRandomNumberEngine, string seedSource where diff --git a/cpp/common/src/codingstandards/cpp/AccessPath.qll b/cpp/common/src/codingstandards/cpp/AccessPath.qll index 2393d25db4..ff7601ed4b 100644 --- a/cpp/common/src/codingstandards/cpp/AccessPath.qll +++ b/cpp/common/src/codingstandards/cpp/AccessPath.qll @@ -1,5 +1,5 @@ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow newtype TFieldQualifier = ExplicitQualifier(VariableAccess v) or diff --git a/cpp/common/src/codingstandards/cpp/Allocations.qll b/cpp/common/src/codingstandards/cpp/Allocations.qll index 5bc87221e2..db47b0b028 100644 --- a/cpp/common/src/codingstandards/cpp/Allocations.qll +++ b/cpp/common/src/codingstandards/cpp/Allocations.qll @@ -7,7 +7,7 @@ import cpp import semmle.code.cpp.controlflow.SSA -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow /** * Holds if `alloc` is a use of `malloc` or `new`. `kind` is diff --git a/cpp/common/src/codingstandards/cpp/Concurrency.qll b/cpp/common/src/codingstandards/cpp/Concurrency.qll index d856fa4515..5e7d154d59 100644 --- a/cpp/common/src/codingstandards/cpp/Concurrency.qll +++ b/cpp/common/src/codingstandards/cpp/Concurrency.qll @@ -1,5 +1,5 @@ import cpp -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking /** * Models CFG nodes which should be added to a thread context. diff --git a/cpp/common/src/codingstandards/cpp/ConstHelpers.qll b/cpp/common/src/codingstandards/cpp/ConstHelpers.qll index 8cba3efde4..a7457dc845 100644 --- a/cpp/common/src/codingstandards/cpp/ConstHelpers.qll +++ b/cpp/common/src/codingstandards/cpp/ConstHelpers.qll @@ -4,7 +4,7 @@ import cpp import codingstandards.cpp.SideEffect -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.FunctionParameter /** A variable that can be modified (both the pointer and object pointed to if pointer type) */ diff --git a/cpp/common/src/codingstandards/cpp/FgetsErrorManagement.qll b/cpp/common/src/codingstandards/cpp/FgetsErrorManagement.qll index 7686714635..4f99b02e2e 100644 --- a/cpp/common/src/codingstandards/cpp/FgetsErrorManagement.qll +++ b/cpp/common/src/codingstandards/cpp/FgetsErrorManagement.qll @@ -4,7 +4,7 @@ */ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.controlflow.Guards /* diff --git a/cpp/common/src/codingstandards/cpp/Iterators.qll b/cpp/common/src/codingstandards/cpp/Iterators.qll index 593da544ea..72a9909c20 100644 --- a/cpp/common/src/codingstandards/cpp/Iterators.qll +++ b/cpp/common/src/codingstandards/cpp/Iterators.qll @@ -3,8 +3,8 @@ */ import cpp -import codingstandards.cpp.dataflow.DataFlow -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.TaintTracking import codingstandards.cpp.StdNamespace abstract class ContainerAccess extends VariableAccess { diff --git a/cpp/common/src/codingstandards/cpp/Nullness.qll b/cpp/common/src/codingstandards/cpp/Nullness.qll index d76db4afad..8751c54d9b 100644 --- a/cpp/common/src/codingstandards/cpp/Nullness.qll +++ b/cpp/common/src/codingstandards/cpp/Nullness.qll @@ -1,5 +1,5 @@ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow private class PointerToMember extends Variable { PointerToMember() { this.getType() instanceof PointerToMemberType } diff --git a/cpp/common/src/codingstandards/cpp/Overflow.qll b/cpp/common/src/codingstandards/cpp/Overflow.qll index dca1386513..28a5c0d9db 100644 --- a/cpp/common/src/codingstandards/cpp/Overflow.qll +++ b/cpp/common/src/codingstandards/cpp/Overflow.qll @@ -6,7 +6,7 @@ import cpp import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis import SimpleRangeAnalysisCustomizations import semmle.code.cpp.controlflow.Guards -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking import semmle.code.cpp.valuenumbering.GlobalValueNumbering import codingstandards.cpp.Expr import codingstandards.cpp.UndefinedBehavior diff --git a/cpp/common/src/codingstandards/cpp/ReadErrorsAndEOF.qll b/cpp/common/src/codingstandards/cpp/ReadErrorsAndEOF.qll index 7adb911c9f..c3c433d20d 100644 --- a/cpp/common/src/codingstandards/cpp/ReadErrorsAndEOF.qll +++ b/cpp/common/src/codingstandards/cpp/ReadErrorsAndEOF.qll @@ -1,5 +1,5 @@ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.standardlibrary.FileAccess /** diff --git a/cpp/common/src/codingstandards/cpp/SideEffect.qll b/cpp/common/src/codingstandards/cpp/SideEffect.qll index 08cd9394d3..4b78b5c818 100644 --- a/cpp/common/src/codingstandards/cpp/SideEffect.qll +++ b/cpp/common/src/codingstandards/cpp/SideEffect.qll @@ -1,7 +1,7 @@ /** A module to reason about side effects. */ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow private import exceptions.ExceptionFlow private import codingstandards.cpp.Expr private import codingstandards.cpp.Variable diff --git a/cpp/common/src/codingstandards/cpp/SmartPointers.qll b/cpp/common/src/codingstandards/cpp/SmartPointers.qll index dda645a399..0f01d886be 100644 --- a/cpp/common/src/codingstandards/cpp/SmartPointers.qll +++ b/cpp/common/src/codingstandards/cpp/SmartPointers.qll @@ -1,5 +1,5 @@ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow // Local cached version of localExprFlow to avoid bad magic cached diff --git a/cpp/common/src/codingstandards/cpp/allocations/PlacementNew.qll b/cpp/common/src/codingstandards/cpp/allocations/PlacementNew.qll index 5547f2e151..2c9139d0ae 100644 --- a/cpp/common/src/codingstandards/cpp/allocations/PlacementNew.qll +++ b/cpp/common/src/codingstandards/cpp/allocations/PlacementNew.qll @@ -22,7 +22,7 @@ import cpp import codingstandards.cpp.Conversion -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow /* * TODO You can also have alignas on types diff --git a/cpp/common/src/codingstandards/cpp/dataflow/DataFlow.qll b/cpp/common/src/codingstandards/cpp/dataflow/DataFlow.qll deleted file mode 100644 index c11bf80fc6..0000000000 --- a/cpp/common/src/codingstandards/cpp/dataflow/DataFlow.qll +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Provides a library for local (intra-procedural) and global (inter-procedural) - * data flow analysis: deciding whether data can flow from a _source_ to a - * _sink_. - * - * Unless configured otherwise, _flow_ means that the exact value of - * the source may reach the sink. We do not track flow across pointer - * dereferences or array indexing. To track these types of flow, where the - * exact value may not be preserved, import - * `semmle.code.cpp.dataflow.TaintTracking`. - * - * To use global (interprocedural) data flow, extend the class - * `DataFlow::Configuration` as documented on that class. To use local - * (intraprocedural) data flow between expressions, call - * `DataFlow::localExprFlow`. For more general cases of local data flow, call - * `DataFlow::localFlow` or `DataFlow::localFlowStep` with arguments of type - * `DataFlow::Node`. - * - * NOTE: This is copied from `codeql/cpp-all` to avoid deprecation warnings - * that cannot be avoided in tests. - */ - -import cpp - -/** - * DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead. - * - * Provides classes for performing local (intra-procedural) and - * global (inter-procedural) data flow analyses. - */ -module DataFlow { - private import semmle.code.cpp.dataflow.internal.DataFlowImplSpecific - private import codeql.dataflow.DataFlow - import DataFlowMake - import semmle.code.cpp.dataflow.internal.DataFlowImpl1 -} diff --git a/cpp/common/src/codingstandards/cpp/dataflow/DataFlow2.qll b/cpp/common/src/codingstandards/cpp/dataflow/DataFlow2.qll deleted file mode 100644 index 83859535d8..0000000000 --- a/cpp/common/src/codingstandards/cpp/dataflow/DataFlow2.qll +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Provides a `DataFlow2` module, which is a copy of the `DataFlow` module. Use - * this class when data-flow configurations must depend on each other. Two - * classes extending `DataFlow::Configuration` should never depend on each - * other, but one of them should instead depend on a - * `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a - * `DataFlow4::Configuration`. - * - * See `semmle.code.cpp.dataflow.DataFlow` for the full documentation. - * - * NOTE: This is copied from `codeql/cpp-all` to avoid deprecation warnings - * that cannot be avoided in tests. - */ - -import cpp - -/** - * DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow2` instead. - * - * Provides classes for performing local (intra-procedural) and - * global (inter-procedural) data flow analyses. - */ -module DataFlow2 { - import semmle.code.cpp.dataflow.internal.DataFlowImpl2 -} diff --git a/cpp/common/src/codingstandards/cpp/dataflow/TaintTracking.qll b/cpp/common/src/codingstandards/cpp/dataflow/TaintTracking.qll deleted file mode 100644 index 2b43a53ccb..0000000000 --- a/cpp/common/src/codingstandards/cpp/dataflow/TaintTracking.qll +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Provides classes for performing local (intra-procedural) and - * global (inter-procedural) taint-tracking analyses. - * - * We define _taint propagation_ informally to mean that a substantial part of - * the information from the source is preserved at the sink. For example, taint - * propagates from `x` to `x + 100`, but it does not propagate from `x` to `x > - * 100` since we consider a single bit of information to be too little. - * - * To use global (interprocedural) taint tracking, extend the class - * `TaintTracking::Configuration` as documented on that class. To use local - * (intraprocedural) taint tracking between expressions, call - * `TaintTracking::localExprTaint`. For more general cases of local taint - * tracking, call `TaintTracking::localTaint` or - * `TaintTracking::localTaintStep` with arguments of type `DataFlow::Node`. - * - * NOTE: This is copied from `codeql/cpp-all` to avoid deprecation warnings - * that cannot be avoided in tests. - */ - -import codingstandards.cpp.dataflow.DataFlow -import codingstandards.cpp.dataflow.DataFlow2 - -/** - * DEPRECATED: Use `semmle.code.cpp.dataflow.new.TaintTracking` instead. - * - * Provides classes for performing local (intra-procedural) and - * global (inter-procedural) taint-tracking analyses. - */ -module TaintTracking { - import codingstandards.cpp.dataflow.internal.tainttracking1.TaintTrackingParameter::Public - private import semmle.code.cpp.dataflow.internal.DataFlowImplSpecific - private import semmle.code.cpp.dataflow.internal.TaintTrackingImplSpecific - private import codeql.dataflow.TaintTracking - import TaintFlowMake - import semmle.code.cpp.dataflow.internal.tainttracking1.TaintTrackingImpl -} diff --git a/cpp/common/src/codingstandards/cpp/dataflow/internal/tainttracking1/TaintTrackingParameter.qll b/cpp/common/src/codingstandards/cpp/dataflow/internal/tainttracking1/TaintTrackingParameter.qll deleted file mode 100644 index 63e9c85e22..0000000000 --- a/cpp/common/src/codingstandards/cpp/dataflow/internal/tainttracking1/TaintTrackingParameter.qll +++ /dev/null @@ -1,6 +0,0 @@ -import semmle.code.cpp.dataflow.internal.TaintTrackingUtil as Public - -module Private { - import codingstandards.cpp.dataflow.DataFlow::DataFlow as DataFlow - import semmle.code.cpp.dataflow.internal.DataFlowImpl as DataFlowInternal -} diff --git a/cpp/common/src/codingstandards/cpp/lifetimes/lifetimeprofile/LifetimeProfile.qll b/cpp/common/src/codingstandards/cpp/lifetimes/lifetimeprofile/LifetimeProfile.qll index 7990f50216..354dccdc56 100644 --- a/cpp/common/src/codingstandards/cpp/lifetimes/lifetimeprofile/LifetimeProfile.qll +++ b/cpp/common/src/codingstandards/cpp/lifetimes/lifetimeprofile/LifetimeProfile.qll @@ -1,5 +1,5 @@ import cpp -private import codingstandards.cpp.dataflow.DataFlow +private import semmle.code.cpp.dataflow.DataFlow private import semmle.code.cpp.controlflow.Nullness private import codingstandards.cpp.Dereferenced private import codingstandards.cpp.Expr diff --git a/cpp/common/src/codingstandards/cpp/resources/ResourceManagement.qll b/cpp/common/src/codingstandards/cpp/resources/ResourceManagement.qll index 0798575495..db65dd4920 100644 --- a/cpp/common/src/codingstandards/cpp/resources/ResourceManagement.qll +++ b/cpp/common/src/codingstandards/cpp/resources/ResourceManagement.qll @@ -1,5 +1,5 @@ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow /** * The `ResourceAcquisitionExpr` abstract class models resource diff --git a/cpp/common/src/codingstandards/cpp/rules/accessofnonexistingmemberthroughpointertomember/AccessOfNonExistingMemberThroughPointerToMember.qll b/cpp/common/src/codingstandards/cpp/rules/accessofnonexistingmemberthroughpointertomember/AccessOfNonExistingMemberThroughPointerToMember.qll index 138c0a89b5..ac135386f3 100644 --- a/cpp/common/src/codingstandards/cpp/rules/accessofnonexistingmemberthroughpointertomember/AccessOfNonExistingMemberThroughPointerToMember.qll +++ b/cpp/common/src/codingstandards/cpp/rules/accessofnonexistingmemberthroughpointertomember/AccessOfNonExistingMemberThroughPointerToMember.qll @@ -7,7 +7,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import codingstandards.cpp.Expr -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow abstract class AccessOfNonExistingMemberThroughPointerToMemberSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/accessofundefinedmemberthroughnullpointer/AccessOfUndefinedMemberThroughNullPointer.qll b/cpp/common/src/codingstandards/cpp/rules/accessofundefinedmemberthroughnullpointer/AccessOfUndefinedMemberThroughNullPointer.qll index ab8659efd8..e0fb382008 100644 --- a/cpp/common/src/codingstandards/cpp/rules/accessofundefinedmemberthroughnullpointer/AccessOfUndefinedMemberThroughNullPointer.qll +++ b/cpp/common/src/codingstandards/cpp/rules/accessofundefinedmemberthroughnullpointer/AccessOfUndefinedMemberThroughNullPointer.qll @@ -7,7 +7,7 @@ import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import codingstandards.cpp.Nullness import codingstandards.cpp.Expr -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import NullPointerToPointerMemberExpressionFlow::PathGraph abstract class AccessOfUndefinedMemberThroughNullPointerSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/accessofundefinedmemberthroughuninitializedstaticpointer/AccessOfUndefinedMemberThroughUninitializedStaticPointer.qll b/cpp/common/src/codingstandards/cpp/rules/accessofundefinedmemberthroughuninitializedstaticpointer/AccessOfUndefinedMemberThroughUninitializedStaticPointer.qll index ca1e2a4282..0271d7c6e7 100644 --- a/cpp/common/src/codingstandards/cpp/rules/accessofundefinedmemberthroughuninitializedstaticpointer/AccessOfUndefinedMemberThroughUninitializedStaticPointer.qll +++ b/cpp/common/src/codingstandards/cpp/rules/accessofundefinedmemberthroughuninitializedstaticpointer/AccessOfUndefinedMemberThroughUninitializedStaticPointer.qll @@ -12,7 +12,7 @@ */ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import codingstandards.cpp.EncapsulatingFunctions diff --git a/cpp/common/src/codingstandards/cpp/rules/basicstringmaynotbenullterminated/BasicStringMayNotBeNullTerminated.qll b/cpp/common/src/codingstandards/cpp/rules/basicstringmaynotbenullterminated/BasicStringMayNotBeNullTerminated.qll index cea798ae11..e27f09fd98 100644 --- a/cpp/common/src/codingstandards/cpp/rules/basicstringmaynotbenullterminated/BasicStringMayNotBeNullTerminated.qll +++ b/cpp/common/src/codingstandards/cpp/rules/basicstringmaynotbenullterminated/BasicStringMayNotBeNullTerminated.qll @@ -8,8 +8,8 @@ import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import semmle.code.cpp.security.BufferWrite import semmle.code.cpp.commons.Buffer -import codingstandards.cpp.dataflow.DataFlow -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.TaintTracking import codingstandards.cpp.PossiblyUnsafeStringOperation abstract class BasicStringMayNotBeNullTerminatedSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/constlikereturnvalue/ConstLikeReturnValue.qll b/cpp/common/src/codingstandards/cpp/rules/constlikereturnvalue/ConstLikeReturnValue.qll index f4636b6b13..e5fa82df19 100644 --- a/cpp/common/src/codingstandards/cpp/rules/constlikereturnvalue/ConstLikeReturnValue.qll +++ b/cpp/common/src/codingstandards/cpp/rules/constlikereturnvalue/ConstLikeReturnValue.qll @@ -5,7 +5,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import DFFlow::PathGraph abstract class ConstLikeReturnValueSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/containeraccesswithoutrangecheck/ContainerAccessWithoutRangeCheck.qll b/cpp/common/src/codingstandards/cpp/rules/containeraccesswithoutrangecheck/ContainerAccessWithoutRangeCheck.qll index a3dabedd5a..840cd5330a 100644 --- a/cpp/common/src/codingstandards/cpp/rules/containeraccesswithoutrangecheck/ContainerAccessWithoutRangeCheck.qll +++ b/cpp/common/src/codingstandards/cpp/rules/containeraccesswithoutrangecheck/ContainerAccessWithoutRangeCheck.qll @@ -12,7 +12,7 @@ import codingstandards.cpp.Operator import semmle.code.cpp.controlflow.Guards private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.valuenumbering.GlobalValueNumbering abstract class ContainerAccessWithoutRangeCheckSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/danglingcapturewhenmovinglambdaobject/DanglingCaptureWhenMovingLambdaObject.qll b/cpp/common/src/codingstandards/cpp/rules/danglingcapturewhenmovinglambdaobject/DanglingCaptureWhenMovingLambdaObject.qll index ab2b067279..902d0ecf1f 100644 --- a/cpp/common/src/codingstandards/cpp/rules/danglingcapturewhenmovinglambdaobject/DanglingCaptureWhenMovingLambdaObject.qll +++ b/cpp/common/src/codingstandards/cpp/rules/danglingcapturewhenmovinglambdaobject/DanglingCaptureWhenMovingLambdaObject.qll @@ -5,7 +5,7 @@ */ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import codingstandards.cpp.Expr diff --git a/cpp/common/src/codingstandards/cpp/rules/danglingcapturewhenreturninglambdaobject/DanglingCaptureWhenReturningLambdaObject.qll b/cpp/common/src/codingstandards/cpp/rules/danglingcapturewhenreturninglambdaobject/DanglingCaptureWhenReturningLambdaObject.qll index c35b723ff3..4ab01520f6 100644 --- a/cpp/common/src/codingstandards/cpp/rules/danglingcapturewhenreturninglambdaobject/DanglingCaptureWhenReturningLambdaObject.qll +++ b/cpp/common/src/codingstandards/cpp/rules/danglingcapturewhenreturninglambdaobject/DanglingCaptureWhenReturningLambdaObject.qll @@ -5,7 +5,7 @@ */ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions diff --git a/cpp/common/src/codingstandards/cpp/rules/donotaccessaclosedfile/DoNotAccessAClosedFile.qll b/cpp/common/src/codingstandards/cpp/rules/donotaccessaclosedfile/DoNotAccessAClosedFile.qll index 3d84366d9a..83266ed524 100644 --- a/cpp/common/src/codingstandards/cpp/rules/donotaccessaclosedfile/DoNotAccessAClosedFile.qll +++ b/cpp/common/src/codingstandards/cpp/rules/donotaccessaclosedfile/DoNotAccessAClosedFile.qll @@ -6,7 +6,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.standardlibrary.FileAccess import semmle.code.cpp.controlflow.SubBasicBlocks diff --git a/cpp/common/src/codingstandards/cpp/rules/donotallowamutextogooutofscopewhilelocked/DoNotAllowAMutexToGoOutOfScopeWhileLocked.qll b/cpp/common/src/codingstandards/cpp/rules/donotallowamutextogooutofscopewhilelocked/DoNotAllowAMutexToGoOutOfScopeWhileLocked.qll index 8a8155f971..759d235eb4 100644 --- a/cpp/common/src/codingstandards/cpp/rules/donotallowamutextogooutofscopewhilelocked/DoNotAllowAMutexToGoOutOfScopeWhileLocked.qll +++ b/cpp/common/src/codingstandards/cpp/rules/donotallowamutextogooutofscopewhilelocked/DoNotAllowAMutexToGoOutOfScopeWhileLocked.qll @@ -17,7 +17,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import codingstandards.cpp.Concurrency -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking abstract class DoNotAllowAMutexToGoOutOfScopeWhileLockedSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/donotdestroyamutexwhileitislocked/DoNotDestroyAMutexWhileItIsLocked.qll b/cpp/common/src/codingstandards/cpp/rules/donotdestroyamutexwhileitislocked/DoNotDestroyAMutexWhileItIsLocked.qll index 46335c3d94..d77ae8cf39 100644 --- a/cpp/common/src/codingstandards/cpp/rules/donotdestroyamutexwhileitislocked/DoNotDestroyAMutexWhileItIsLocked.qll +++ b/cpp/common/src/codingstandards/cpp/rules/donotdestroyamutexwhileitislocked/DoNotDestroyAMutexWhileItIsLocked.qll @@ -15,7 +15,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import codingstandards.cpp.Concurrency -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking abstract class DoNotDestroyAMutexWhileItIsLockedSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.qll b/cpp/common/src/codingstandards/cpp/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.qll index 0aa8d64feb..adb9785814 100644 --- a/cpp/common/src/codingstandards/cpp/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.qll +++ b/cpp/common/src/codingstandards/cpp/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.qll @@ -6,7 +6,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import ArrayToPointerDiffOperandFlow::PathGraph module ArrayToPointerDiffOperandConfig implements DataFlow::ConfigSig { diff --git a/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll b/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll index dd10b840c5..57b4eb0bfb 100644 --- a/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll +++ b/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll @@ -7,7 +7,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis abstract class DoNotUsePointerArithmeticToAddressDifferentArraysSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/donotuserelationaloperatorswithdifferingarrays/DoNotUseRelationalOperatorsWithDifferingArrays.qll b/cpp/common/src/codingstandards/cpp/rules/donotuserelationaloperatorswithdifferingarrays/DoNotUseRelationalOperatorsWithDifferingArrays.qll index 155ed1a7f4..aa8fa29bfd 100644 --- a/cpp/common/src/codingstandards/cpp/rules/donotuserelationaloperatorswithdifferingarrays/DoNotUseRelationalOperatorsWithDifferingArrays.qll +++ b/cpp/common/src/codingstandards/cpp/rules/donotuserelationaloperatorswithdifferingarrays/DoNotUseRelationalOperatorsWithDifferingArrays.qll @@ -7,7 +7,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import ArrayToRelationalOperationOperandFlow::PathGraph abstract class DoNotUseRelationalOperatorsWithDifferingArraysSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointers/InvalidatedEnvStringPointers.qll b/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointers/InvalidatedEnvStringPointers.qll index 81a3251355..3949ff50a8 100644 --- a/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointers/InvalidatedEnvStringPointers.qll +++ b/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointers/InvalidatedEnvStringPointers.qll @@ -6,7 +6,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow abstract class InvalidatedEnvStringPointersSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointerswarn/InvalidatedEnvStringPointersWarn.qll b/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointerswarn/InvalidatedEnvStringPointersWarn.qll index fd8a969d00..8bc1b0c920 100644 --- a/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointerswarn/InvalidatedEnvStringPointersWarn.qll +++ b/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointerswarn/InvalidatedEnvStringPointersWarn.qll @@ -6,7 +6,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.rules.invalidatedenvstringpointers.InvalidatedEnvStringPointers as EnvString abstract class InvalidatedEnvStringPointersWarnSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll b/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll index 3a7e225369..89f847c5aa 100644 --- a/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll +++ b/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll @@ -5,7 +5,7 @@ */ import cpp -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking import codingstandards.cpp.Exclusions import codingstandards.cpp.standardlibrary.FileStreams import codingstandards.cpp.standardlibrary.FileAccess diff --git a/cpp/common/src/codingstandards/cpp/rules/movedfromobjectsunspecifiedstate/MovedFromObjectsUnspecifiedState.qll b/cpp/common/src/codingstandards/cpp/rules/movedfromobjectsunspecifiedstate/MovedFromObjectsUnspecifiedState.qll index a0006eb643..f17da7e457 100644 --- a/cpp/common/src/codingstandards/cpp/rules/movedfromobjectsunspecifiedstate/MovedFromObjectsUnspecifiedState.qll +++ b/cpp/common/src/codingstandards/cpp/rules/movedfromobjectsunspecifiedstate/MovedFromObjectsUnspecifiedState.qll @@ -4,7 +4,7 @@ */ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.Exclusions import codingstandards.cpp.standardlibrary.Utility diff --git a/cpp/common/src/codingstandards/cpp/rules/nonconstantformat/NonConstantFormat.qll b/cpp/common/src/codingstandards/cpp/rules/nonconstantformat/NonConstantFormat.qll index 91b2b05a3f..248cde106f 100644 --- a/cpp/common/src/codingstandards/cpp/rules/nonconstantformat/NonConstantFormat.qll +++ b/cpp/common/src/codingstandards/cpp/rules/nonconstantformat/NonConstantFormat.qll @@ -1,7 +1,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking import semmle.code.cpp.commons.Printf abstract class NonConstantFormatSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/onlyfreememoryallocateddynamicallyshared/OnlyFreeMemoryAllocatedDynamicallyShared.qll b/cpp/common/src/codingstandards/cpp/rules/onlyfreememoryallocateddynamicallyshared/OnlyFreeMemoryAllocatedDynamicallyShared.qll index bede451e24..89c732ff5a 100644 --- a/cpp/common/src/codingstandards/cpp/rules/onlyfreememoryallocateddynamicallyshared/OnlyFreeMemoryAllocatedDynamicallyShared.qll +++ b/cpp/common/src/codingstandards/cpp/rules/onlyfreememoryallocateddynamicallyshared/OnlyFreeMemoryAllocatedDynamicallyShared.qll @@ -7,7 +7,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import codingstandards.cpp.Allocations -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import NonDynamicPointerToFreeFlow::PathGraph /** diff --git a/cpp/common/src/codingstandards/cpp/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.qll b/cpp/common/src/codingstandards/cpp/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.qll index e24fb91539..2ee92b1611 100644 --- a/cpp/common/src/codingstandards/cpp/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.qll +++ b/cpp/common/src/codingstandards/cpp/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.qll @@ -8,7 +8,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import codingstandards.cpp.SmartPointers -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking import PointerToSmartPointerConstructorFlowFlow::PathGraph abstract class OwnedPointerValueStoredInUnrelatedSmartPointerSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/placementnewinsufficientstorage/PlacementNewInsufficientStorage.qll b/cpp/common/src/codingstandards/cpp/rules/placementnewinsufficientstorage/PlacementNewInsufficientStorage.qll index dc26d13b87..6b2c6c87c9 100644 --- a/cpp/common/src/codingstandards/cpp/rules/placementnewinsufficientstorage/PlacementNewInsufficientStorage.qll +++ b/cpp/common/src/codingstandards/cpp/rules/placementnewinsufficientstorage/PlacementNewInsufficientStorage.qll @@ -7,7 +7,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import codingstandards.cpp.allocations.PlacementNew -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import PlacementNewOriginFlow::PathGraph abstract class PlacementNewInsufficientStorageSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/placementnewnotproperlyaligned/PlacementNewNotProperlyAligned.qll b/cpp/common/src/codingstandards/cpp/rules/placementnewnotproperlyaligned/PlacementNewNotProperlyAligned.qll index 72286f2d79..d250061a23 100644 --- a/cpp/common/src/codingstandards/cpp/rules/placementnewnotproperlyaligned/PlacementNewNotProperlyAligned.qll +++ b/cpp/common/src/codingstandards/cpp/rules/placementnewnotproperlyaligned/PlacementNewNotProperlyAligned.qll @@ -7,7 +7,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import codingstandards.cpp.allocations.PlacementNew -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import PlacementNewOriginFlow::PathGraph abstract class PlacementNewNotProperlyAlignedSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/stringnumberconversionmissingerrorcheck/StringNumberConversionMissingErrorCheck.qll b/cpp/common/src/codingstandards/cpp/rules/stringnumberconversionmissingerrorcheck/StringNumberConversionMissingErrorCheck.qll index 98fd51a58f..fd56f5d899 100644 --- a/cpp/common/src/codingstandards/cpp/rules/stringnumberconversionmissingerrorcheck/StringNumberConversionMissingErrorCheck.qll +++ b/cpp/common/src/codingstandards/cpp/rules/stringnumberconversionmissingerrorcheck/StringNumberConversionMissingErrorCheck.qll @@ -7,7 +7,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import semmle.code.cpp.valuenumbering.GlobalValueNumbering -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.TaintTracking import codingstandards.cpp.standardlibrary.CharStreams abstract class StringNumberConversionMissingErrorCheckSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/throwingoperatornewreturnsnull/ThrowingOperatorNewReturnsNull.qll b/cpp/common/src/codingstandards/cpp/rules/throwingoperatornewreturnsnull/ThrowingOperatorNewReturnsNull.qll index 9dbefeaa75..e28ef7ab07 100644 --- a/cpp/common/src/codingstandards/cpp/rules/throwingoperatornewreturnsnull/ThrowingOperatorNewReturnsNull.qll +++ b/cpp/common/src/codingstandards/cpp/rules/throwingoperatornewreturnsnull/ThrowingOperatorNewReturnsNull.qll @@ -4,7 +4,7 @@ */ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.allocations.CustomOperatorNewDelete import codingstandards.cpp.exceptions.ExceptionSpecifications import codingstandards.cpp.Customizations diff --git a/cpp/common/src/codingstandards/cpp/rules/useonlyarrayindexingforpointerarithmetic/UseOnlyArrayIndexingForPointerArithmetic.qll b/cpp/common/src/codingstandards/cpp/rules/useonlyarrayindexingforpointerarithmetic/UseOnlyArrayIndexingForPointerArithmetic.qll index c421ae3cc9..3b0abbad0d 100644 --- a/cpp/common/src/codingstandards/cpp/rules/useonlyarrayindexingforpointerarithmetic/UseOnlyArrayIndexingForPointerArithmetic.qll +++ b/cpp/common/src/codingstandards/cpp/rules/useonlyarrayindexingforpointerarithmetic/UseOnlyArrayIndexingForPointerArithmetic.qll @@ -6,7 +6,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow abstract class UseOnlyArrayIndexingForPointerArithmeticSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/standardlibrary/FileStreams.qll b/cpp/common/src/codingstandards/cpp/standardlibrary/FileStreams.qll index c4724d36c2..709e80dc1a 100644 --- a/cpp/common/src/codingstandards/cpp/standardlibrary/FileStreams.qll +++ b/cpp/common/src/codingstandards/cpp/standardlibrary/FileStreams.qll @@ -10,8 +10,8 @@ */ import cpp -import codingstandards.cpp.dataflow.DataFlow -import codingstandards.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.TaintTracking private import codingstandards.cpp.Operator /** diff --git a/cpp/common/src/codingstandards/cpp/trustboundary/UninitializedField.qll b/cpp/common/src/codingstandards/cpp/trustboundary/UninitializedField.qll index e6a2bbe706..f58f1352a7 100644 --- a/cpp/common/src/codingstandards/cpp/trustboundary/UninitializedField.qll +++ b/cpp/common/src/codingstandards/cpp/trustboundary/UninitializedField.qll @@ -5,7 +5,7 @@ */ import cpp -private import codingstandards.cpp.dataflow.DataFlow +private import semmle.code.cpp.dataflow.DataFlow private import semmle.code.cpp.controlflow.SubBasicBlocks private import semmle.code.cpp.padding.Padding as Padding private import semmle.code.cpp.dataflow.internal.FlowVar diff --git a/cpp/common/test/deviations/deviation_permits_basic_test/UnusedReturnValue.ql b/cpp/common/test/deviations/deviation_permits_basic_test/UnusedReturnValue.ql index 2517965fc1..38b75bda3c 100644 --- a/cpp/common/test/deviations/deviation_permits_basic_test/UnusedReturnValue.ql +++ b/cpp/common/test/deviations/deviation_permits_basic_test/UnusedReturnValue.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.cpp.CodingStandards -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.exclusions.cpp.RuleMetadata /* This is a copy of an AUTOSAR rule, which we are using for testing purposes. */ diff --git a/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.ql b/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.ql index 2517965fc1..38b75bda3c 100644 --- a/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.ql +++ b/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.cpp.CodingStandards -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.exclusions.cpp.RuleMetadata /* This is a copy of an AUTOSAR rule, which we are using for testing purposes. */ diff --git a/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.ql b/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.ql index 2517965fc1..38b75bda3c 100644 --- a/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.ql +++ b/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.cpp.CodingStandards -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.exclusions.cpp.RuleMetadata /* This is a copy of an AUTOSAR rule, which we are using for testing purposes. */ From 4b4373615affbe350aef308db34d8e26b2d4fd75 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Wed, 13 Mar 2024 21:53:02 +0000 Subject: [PATCH 016/370] Accept test changes. --- ...bleLengthArraySizeNotInValidRange.expected | 2 ++ ...rithmeticOnNonArrayObjectPointers.expected | 5 ++++ ...rSubtractAScaledIntegerToAPointer.expected | 4 ++++ .../CleanUpThreadSpecificStorage.expected | 6 +++++ ...riateThreadObjectStorageDurations.expected | 8 +++++++ ...ectStorageDurationsNotInitialized.expected | 5 ++++ ...ateStorageDurationsFunctionReturn.expected | 5 ++++ .../ERR30-C/ErrnoReadBeforeReturn.expected | 1 + .../ERR30-C/SetlocaleMightSetErrno.expected | 1 + ...tRelyOnIndeterminateValuesOfErrno.expected | 4 ++++ ...ectAndHandleStandardLibraryErrors.expected | 1 + ...OfFunctionArgumentsForSideEffects.expected | 24 +++++++++++++++++++ ...rToMoreStrictlyAlignedPointerType.expected | 10 ++++++++ ...nctionPointerWithIncompatibleType.expected | 4 ++++ ...iableViaPointerOfIncompatibleType.expected | 7 ++++++ .../DoNotModifyConstantObjects.expected | 4 ++++ ...edPointerToRestrictQualifiedParam.expected | 12 ++++++++++ ...ointerReferencesOverlappingObject.expected | 7 ++++++ ...esetStringsOnFgetsOrFgetwsFailure.expected | 3 +++ ...FsetposThatAreReturnedFromFgetpos.expected | 5 ++++ ...RaceConditionsWhileAccessingFiles.expected | 1 + ...ufficientMemoryAllocatedForObject.expected | 2 ++ ...odifyAlignmentOfMemoryWithRealloc.expected | 5 ++++ ...ssInvalidDataToTheAsctimeFunction.expected | 4 ++++ ...VaListThatHasAnIndeterminateValue.expected | 7 ++++++ ...SafeFunctionsWithinSignalHandlers.expected | 3 +++ ...romAComputationalExceptionHandler.expected | 1 + ...oNotAttemptToModifyStringLiterals.expected | 15 ++++++++++++ ...fficientSpaceForTheNullTerminator.expected | 6 +++++ ...natedToFunctionThatExpectsAString.expected | 9 +++++++ ...yFunctionArgumentNumberOfElements.expected | 6 +++++ ...sedToCompareNullTerminatedStrings.expected | 4 ++++ ...ForReadAndWriteOnDifferentStreams.expected | 1 + .../AttemptToWriteToAReadOnlyStream.expected | 6 +++++ ...omparedWithUnmodifiedReturnValues.expected | 8 +++++++ ...rformConversionOfPassedParameters.expected | 3 +++ .../AssignmentOperatorReturnThis.expected | 1 + .../ThrownExceptionsShouldBeUnique.expected | 1 + ...orErrorLeavesObjectInInvalidState.expected | 9 +++++++ ...entOfAnArrayPassedToASmartPointer.expected | 7 ++++++ .../UnnecessaryUseOfDynamicStorage.expected | 4 ++++ ...ArgumentToForwardSubsequentlyUsed.expected | 3 +++ ...PointerUsedWithNoOwnershipSharing.expected | 1 + .../rules/A27-0-4/CStyleStringsUsed.expected | 3 +++ ...UsedWithPointersToNonFinalClasses.expected | 4 ++++ .../A5-1-7/LambdaPassedToDecltype.expected | 6 +++++ .../A5-1-7/LambdaPassedToTypeid.expected | 4 ++++ .../A7-1-2/VariableMissingConstexpr.expected | 6 +++++ .../A7-5-1/InvalidFunctionReturnType.expected | 3 +++ ...ParameterWithoutLifetimeSemantics.expected | 2 ++ ...edToFunctionWithImproperSemantics.expected | 2 ++ ...tParametersDeclaredAsTNotModified.expected | 2 ++ ...eferencesToPrivateOrProtectedData.expected | 3 +++ ...tionErroneousReturnValueNotTested.expected | 3 +++ ...ntationsOfFloatingPointValuesUsed.expected | 3 +++ ...berFunctionReturnsNonConstPointer.expected | 2 ++ ...cCppLibraryFunctionsDoNotOverflow.expected | 9 +++++++ .../CTR53-CPP/UseValidIteratorRanges.expected | 6 +++++ ...terArithmeticOnPolymorphicObjects.expected | 4 ++++ ...nFunctionCallsAsFunctionArguments.expected | 24 +++++++++++++++++++ ...ThroughAPointerOfTheIncorrectType.expected | 4 ++++ ...ctAndHandleMemoryAllocationErrors.expected | 7 ++++++ .../BadlySeededRandomNumberGenerator.expected | 1 + 63 files changed, 323 insertions(+) diff --git a/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected b/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected index 25153f195b..bcb1c8eddd 100644 --- a/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected +++ b/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected @@ -1,3 +1,5 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:104,11-19) +WARNING: Module TaintTracking has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:87,5-18) | test.c:14:8:14:8 | VLA declaration | Variable-length array dimension size may be in an invalid range. | | test.c:15:8:15:8 | VLA declaration | Variable-length array dimension size may be in an invalid range. | | test.c:16:8:16:8 | VLA declaration | Variable-length array dimension size may be in an invalid range. | diff --git a/c/cert/test/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.expected b/c/cert/test/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.expected index e5e0252e3a..d75db521af 100644 --- a/c/cert/test/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.expected +++ b/c/cert/test/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.expected @@ -1,3 +1,8 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:23,60-68) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:24,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:36,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:44,26-34) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:65,3-11) edges | test.c:14:38:14:39 | p1 | test.c:18:10:18:11 | v1 | provenance | | | test.c:14:38:14:39 | p1 | test.c:19:10:19:11 | v2 | provenance | | diff --git a/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.expected b/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.expected index bfd6b23128..7782984e5b 100644 --- a/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.expected +++ b/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.expected @@ -1,3 +1,7 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:72,56-64) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:73,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:75,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:84,45-53) edges | test.c:7:13:7:14 | p1 | test.c:9:9:9:10 | p1 | provenance | | | test.c:16:19:16:41 | ... - ... | test.c:18:26:18:31 | offset | provenance | | diff --git a/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected b/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected index e03b665a1c..9b1288d578 100644 --- a/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected +++ b/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected @@ -1,3 +1,9 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:21,46-54) +WARNING: Module DataFlow has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:22,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:31,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:41,35-43) +WARNING: Module DataFlow has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:49,36-44) +WARNING: Module DataFlow has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:51,36-44) | test.c:27:3:27:12 | call to tss_create | Resources used by thread specific storage may not be cleaned up. | | test.c:49:3:49:12 | call to tss_create | Resources used by thread specific storage may not be cleaned up. | | test.c:71:3:71:12 | call to tss_create | Resources used by thread specific storage may not be cleaned up. | diff --git a/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected b/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected index c3cdc8bd7b..a513b55b73 100644 --- a/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected +++ b/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected @@ -1,3 +1,11 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:28,29-37) +WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:28,54-62) +WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:35,62-70) +WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:40,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:40,30-38) +WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:41,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:41,30-38) +WARNING: Module TaintTracking has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:28,3-16) | test.c:23:3:23:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:23:24:23:29 | & ... | Shared object | | test.c:74:3:74:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:74:24:74:24 | p | Shared object | | test.c:85:3:85:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:85:24:85:24 | p | Shared object | diff --git a/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected b/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected index 95d0a20041..337df4c14c 100644 --- a/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected +++ b/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected @@ -1 +1,6 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:28,38-46) +WARNING: Module DataFlow has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:31,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:31,30-38) +WARNING: Module DataFlow has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:32,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:32,30-38) | test.c:14:7:14:13 | call to tss_get | Call to a thread specific storage function from within a threaded context on an object that may not be owned by this thread. | diff --git a/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected b/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected index ff842ddcad..18d28b61bc 100644 --- a/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected +++ b/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected @@ -1,2 +1,7 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:22,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:26,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:39,6-14) +WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:39,26-34) +WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:45,3-11) | test.c:3:10:3:10 | a | $@ with automatic storage may be accessible outside of its lifetime. | test.c:3:10:3:10 | a | a | | test.c:15:4:15:8 | param [inner post update] | $@ with automatic storage may be accessible outside of its lifetime. | test.c:15:12:15:13 | a2 | a2 | diff --git a/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected b/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected index b6d7caa513..b3e5c4b7fc 100644 --- a/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected +++ b/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected @@ -1,3 +1,4 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (ErrnoReadBeforeReturn.ql:40,7-15) | test.c:69:7:69:11 | * ... | Do not read `errno` before checking the return value of function $@. | test.c:68:3:68:7 | call to ftell | call to ftell | | test.c:69:7:69:11 | call to __errno_location | Do not read `errno` before checking the return value of function $@. | test.c:68:3:68:7 | call to ftell | call to ftell | | test.c:70:5:70:10 | call to perror | Do not read `errno` before checking the return value of function $@. | test.c:68:3:68:7 | call to ftell | call to ftell | diff --git a/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected b/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected index 9ab88a3395..0ffaf56bd1 100644 --- a/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected +++ b/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected @@ -1,2 +1,3 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (SetlocaleMightSetErrno.ql:64,7-15) | test.c:98:3:98:11 | call to setlocale | Do not read `errno` before checking the return value of a call to `setlocale`. | | test.c:104:7:104:15 | call to setlocale | The value of `errno` may be different than `0` when `setlocale` is called. The following `errno` check might be invalid. | diff --git a/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected b/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected index da9122cfd4..77fa7b7ba7 100644 --- a/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected +++ b/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected @@ -1,3 +1,7 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:50,7-15) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:50,27-35) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:51,9-17) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:54,9-17) | test.c:12:5:12:10 | call to perror | `errno` has indeterminate value after this $@. | test.c:10:21:10:26 | call to signal | call to signal | | test.c:30:5:30:10 | call to perror | `errno` has indeterminate value after this $@. | test.c:26:21:26:26 | call to signal | call to signal | | test.c:49:5:49:10 | call to perror | `errno` has indeterminate value after this $@. | test.c:45:21:45:26 | call to signal | call to signal | diff --git a/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected b/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected index fbcc44b856..a32a03a3b9 100644 --- a/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected +++ b/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected @@ -1,3 +1,4 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleStandardLibraryErrors.ql:453,5-13) | test.c:18:3:18:11 | call to setlocale | Missing error detection for the call to function `setlocale`. | | test.c:24:23:24:31 | call to setlocale | Missing error detection for the call to function `setlocale`. | | test.c:29:22:29:27 | call to calloc | Missing error detection for the call to function `calloc`. | diff --git a/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected b/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected index 3ea1a05fd7..6ea3499517 100644 --- a/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected +++ b/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected @@ -1 +1,25 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:24,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:24,59-67) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:27,33-41) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:27,57-65) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:31,33-41) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:31,59-67) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:40,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:40,25-33) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:40,53-61) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:43,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:43,57-65) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:52,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:52,55-63) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:59,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:59,57-65) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:71,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:71,55-63) +WARNING: Module TaintTracking has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:24,5-18) +WARNING: Module TaintTracking has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:27,7-20) +WARNING: Module TaintTracking has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:31,7-20) +WARNING: Module TaintTracking has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:43,5-18) +WARNING: Module TaintTracking has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:52,5-18) +WARNING: Module TaintTracking has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:59,5-18) +WARNING: Module TaintTracking has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:71,5-18) | test.c:20:3:20:4 | call to f1 | Depending on the order of evaluation for the arguments $@ and $@ for side effects on shared state is unspecified and can result in unexpected behavior. | test.c:20:6:20:7 | call to f2 | call to f2 | test.c:20:12:20:13 | call to f3 | call to f3 | diff --git a/c/cert/test/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.expected b/c/cert/test/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.expected index c4bc63cc94..b6f96f6ea5 100644 --- a/c/cert/test/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.expected +++ b/c/cert/test/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.expected @@ -1,3 +1,13 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:98,86-94) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:120,3-11) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:122,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:127,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:133,3-11) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:139,55-63) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:140,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:142,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:149,26-34) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:164,44-52) edges | test.c:75:14:75:16 | & ... | test.c:76:11:76:12 | v1 | provenance | | | test.c:75:14:75:16 | & ... | test.c:77:12:77:13 | v1 | provenance | | diff --git a/c/cert/test/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.expected b/c/cert/test/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.expected index 546c753ebb..1b6505f472 100644 --- a/c/cert/test/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.expected +++ b/c/cert/test/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.expected @@ -1,3 +1,7 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:40,54-62) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:41,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:45,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:50,43-51) edges | test.c:48:68:48:70 | fns [f1] | test.c:49:3:49:5 | fns [f1] | provenance | | | test.c:49:3:49:5 | fns [f1] | test.c:49:8:49:9 | f1 | provenance | | diff --git a/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected b/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected index 137017d53a..3316256acb 100644 --- a/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected +++ b/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected @@ -1,3 +1,10 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:61,38-46) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:64,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:69,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:102,23-31) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:111,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:111,45-53) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:133,27-35) edges | test.c:49:8:49:9 | s3 | test.c:50:8:50:9 | s1 | provenance | | | test.c:60:16:60:18 | E1A | test.c:61:16:61:17 | e1 | provenance | | diff --git a/c/cert/test/rules/EXP40-C/DoNotModifyConstantObjects.expected b/c/cert/test/rules/EXP40-C/DoNotModifyConstantObjects.expected index bef45f3841..e7af404ec1 100644 --- a/c/cert/test/rules/EXP40-C/DoNotModifyConstantObjects.expected +++ b/c/cert/test/rules/EXP40-C/DoNotModifyConstantObjects.expected @@ -1,3 +1,7 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:35,30-38) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:36,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:42,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:47,19-27) edges | test.c:5:8:5:9 | & ... | test.c:6:4:6:5 | aa | provenance | | | test.c:26:15:26:15 | a | test.c:27:4:27:4 | a | provenance | | diff --git a/c/cert/test/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.expected b/c/cert/test/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.expected index 4d4c20a39c..a77a92ee81 100644 --- a/c/cert/test/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.expected +++ b/c/cert/test/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.expected @@ -1,3 +1,15 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:103,36-44) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:118,51-59) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:119,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:121,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:127,25-33) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:132,40-48) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:146,41-49) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:147,7-15) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:150,43-51) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:151,9-17) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:158,43-51) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:159,9-17) | test.c:59:3:59:6 | call to copy | Call to 'copy' passes an $@ to a $@ (pointer value derived from a pair of address-of expressions ($@, $@). | test.c:59:13:59:15 | & ... | aliased pointer | test.c:59:8:59:10 | & ... | restrict-qualified parameter | test.c:59:8:59:10 | & ... | addressof1 | test.c:59:13:59:15 | & ... | addressof2 | | test.c:65:3:65:6 | call to copy | Call to 'copy' passes an $@ to a $@ (pointer value derived from a pair of address-of expressions ($@, $@). | test.c:65:15:65:19 | & ... | aliased pointer | test.c:65:8:65:12 | & ... | restrict-qualified parameter | test.c:65:8:65:12 | & ... | addressof1 | test.c:65:15:65:19 | & ... | addressof2 | | test.c:67:3:67:6 | call to copy | Call to 'copy' passes an $@ to a $@ (pointer value derived from a pair of address-of expressions ($@, $@). | test.c:67:15:67:16 | px | aliased pointer | test.c:67:8:67:12 | & ... | restrict-qualified parameter | test.c:67:8:67:12 | & ... | addressof1 | test.c:63:13:63:17 | & ... | addressof2 | diff --git a/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected b/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected index 3746991c09..591e17661a 100644 --- a/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected +++ b/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected @@ -1,3 +1,10 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:42,57-65) +WARNING: Module DataFlow has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:43,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:47,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:53,3-11) +WARNING: Module DataFlow has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:56,58-66) +WARNING: Module DataFlow has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:72,64-72) +WARNING: Module DataFlow has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:73,64-72) | test.c:18:22:18:23 | i2 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:18:17:18:18 | i3 | i3 | test.c:18:22:18:23 | i2 | the object pointed to by i2 | | test.c:19:8:19:9 | g2 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:5:15:5:16 | g1 | g1 | test.c:19:8:19:9 | g2 | the object pointed to by g2 | | test.c:20:8:20:9 | i2 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:16:17:16:18 | i1 | i1 | test.c:20:8:20:9 | i2 | the object pointed to by i2 | diff --git a/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected b/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected index 20c108cfa0..6a73ee98a7 100644 --- a/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected +++ b/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected @@ -1,3 +1,6 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:42,11-19) +WARNING: Module DataFlow has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:42,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:43,13-21) | test.c:20:10:20:12 | buf | The buffer is not reset before being referenced following a failed $@. | test.c:15:7:15:11 | call to fgets | call to fgets | | test.c:57:10:57:12 | buf | The buffer is not reset before being referenced following a failed $@. | test.c:52:7:52:11 | call to fgets | call to fgets | | test.c:66:18:66:20 | buf | The buffer is not reset before being referenced following a failed $@. | test.c:61:7:61:11 | call to fgets | call to fgets | diff --git a/c/cert/test/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.expected b/c/cert/test/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.expected index 8074710738..637918f241 100644 --- a/c/cert/test/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.expected +++ b/c/cert/test/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.expected @@ -1,2 +1,7 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:25,32-40) +WARNING: Module DataFlow has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:26,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:28,14-22) +WARNING: Module DataFlow has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:31,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:37,21-29) | test.c:7:24:7:30 | & ... | The position argument of a call to `fsetpos()` should be obtained from a call to `fgetpos()`. | | test.c:33:24:33:30 | & ... | The position argument of a call to `fsetpos()` should be obtained from a call to `fgetpos()`. | diff --git a/c/cert/test/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.expected b/c/cert/test/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.expected index 1b2923b780..f294ce05b7 100644 --- a/c/cert/test/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.expected +++ b/c/cert/test/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.expected @@ -1,2 +1,3 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (ToctouRaceConditionsWhileAccessingFiles.ql:27,35-43) | test.c:4:13:4:17 | call to fopen | This call is trying to prevent an existing file from being overwritten by $@. An attacker might be able to exploit the race window between the two calls. | test.c:11:9:11:13 | call to fopen | another call | | test.c:88:13:88:17 | call to fopen | This call is trying to prevent an existing file from being overwritten by $@. An attacker might be able to exploit the race window between the two calls. | test.c:95:9:95:13 | call to fopen | another call | diff --git a/c/cert/test/rules/MEM35-C/InsufficientMemoryAllocatedForObject.expected b/c/cert/test/rules/MEM35-C/InsufficientMemoryAllocatedForObject.expected index 30dece9299..73dd6ba1e0 100644 --- a/c/cert/test/rules/MEM35-C/InsufficientMemoryAllocatedForObject.expected +++ b/c/cert/test/rules/MEM35-C/InsufficientMemoryAllocatedForObject.expected @@ -1,3 +1,5 @@ +WARNING: Module TaintTracking has been deprecated and may be removed in future (InsufficientMemoryAllocatedForObject.ql:85,5-18) +WARNING: Module TaintTracking has been deprecated and may be removed in future (InsufficientMemoryAllocatedForObject.ql:143,5-18) | test.c:12:19:12:24 | call to malloc | Allocation size (32 bytes) is not a multiple of the size of 'S1' (36 bytes). | test.c:12:26:12:32 | 32 | | | test.c:15:19:15:24 | call to malloc | Allocation size calculated from the size of a different type ($@). | test.c:15:26:15:35 | sizeof() | sizeof(S1 *) | | test.c:20:19:20:24 | call to malloc | Allocation size (128 bytes) is not a multiple of the size of 'S1' (36 bytes). | test.c:20:26:20:36 | ... * ... | | diff --git a/c/cert/test/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.expected b/c/cert/test/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.expected index 0ae87f2ee8..61c2cfb1f0 100644 --- a/c/cert/test/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.expected +++ b/c/cert/test/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.expected @@ -1,3 +1,8 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:26,36-44) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:40,47-55) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:41,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:45,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:50,36-44) edges | test.c:5:10:5:22 | call to aligned_alloc | test.c:15:8:15:28 | call to aligned_alloc_wrapper | provenance | | | test.c:8:29:8:31 | ptr | test.c:8:64:8:66 | ptr | provenance | | diff --git a/c/cert/test/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.expected b/c/cert/test/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.expected index 70d60c528a..713646db10 100644 --- a/c/cert/test/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.expected +++ b/c/cert/test/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.expected @@ -1 +1,5 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:33,38-46) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:34,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:41,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:44,27-35) | test.c:6:24:6:30 | time_tm | The function `asctime` and `asctime_r` should be discouraged. Unsanitized input can overflow the output buffer. | diff --git a/c/cert/test/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.expected b/c/cert/test/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.expected index 2b7bb2bdbc..4d4a713487 100644 --- a/c/cert/test/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.expected +++ b/c/cert/test/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.expected @@ -1,3 +1,10 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:38,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:39,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:44,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:47,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:68,10-18) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:69,29-37) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:70,29-37) | test.c:23:32:23:33 | ap | The value of ap is indeterminate after the $@. | test.c:17:7:17:19 | call to contains_zero | call to contains_zero | | test.c:26:10:26:11 | ap | The value of ap is indeterminate after the $@. | test.c:17:7:17:19 | call to contains_zero | call to contains_zero | | test.c:39:12:39:13 | ap | The value of ap is indeterminate after the $@. | test.c:35:7:35:19 | call to contains_zero | call to contains_zero | diff --git a/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected b/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected index a601fe63f4..a5f4af8c3c 100644 --- a/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected +++ b/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected @@ -1,3 +1,6 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:105,11-19) +WARNING: Module DataFlow has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:105,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:106,9-17) | test.c:10:3:10:18 | call to log_local_unsafe | Asyncronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:16:7:16:12 | call to signal | signal handler | | test.c:11:3:11:6 | call to free | Asyncronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:16:7:16:12 | call to signal | signal handler | | test.c:46:3:46:9 | call to longjmp | Asyncronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:50:7:50:12 | call to signal | signal handler | diff --git a/c/cert/test/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.expected b/c/cert/test/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.expected index 31412c466a..d4796c6ede 100644 --- a/c/cert/test/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.expected +++ b/c/cert/test/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.expected @@ -1 +1,2 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotReturnFromAComputationalExceptionHandler.ql:39,5-13) | test.c:10:1:10:1 | return ... | Do not return from a $@ signal handler. | test.c:13:10:13:15 | SIGFPE | computational exception | diff --git a/c/cert/test/rules/STR30-C/DoNotAttemptToModifyStringLiterals.expected b/c/cert/test/rules/STR30-C/DoNotAttemptToModifyStringLiterals.expected index 27ef66bc7a..7215fd8603 100644 --- a/c/cert/test/rules/STR30-C/DoNotAttemptToModifyStringLiterals.expected +++ b/c/cert/test/rules/STR30-C/DoNotAttemptToModifyStringLiterals.expected @@ -1,3 +1,18 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:42,65-73) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:43,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:64,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:77,3-11) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:101,11-19) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:101,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:101,55-63) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:106,11-19) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:106,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:106,57-65) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:139,11-19) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:139,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:139,55-63) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:150,53-61) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:151,5-13) | test.c:7:3:7:3 | a | This operation may write to a string that may be a string literal that was $@. | test.c:6:13:6:20 | codeql | created here | | test.c:30:3:30:3 | a | This operation may write to a string that may be a string literal that was $@. | test.c:29:13:29:18 | call to strchr | created here | | test.c:36:3:36:3 | b | This operation may write to a string that may be a string literal that was $@. | test.c:35:13:35:18 | call to strchr | created here | diff --git a/c/cert/test/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.expected b/c/cert/test/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.expected index 71e713d120..4c411382f0 100644 --- a/c/cert/test/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.expected +++ b/c/cert/test/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.expected @@ -1,3 +1,9 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:57,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:57,55-63) +WARNING: Module DataFlow has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:63,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:63,54-62) +WARNING: Module TaintTracking has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:57,5-18) +WARNING: Module TaintTracking has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:63,5-18) | test.c:10:20:10:24 | Cod | Expression produces or consumes a string that may not have sufficient space for a null-terminator. | | test.c:16:3:16:9 | call to strncpy | Expression produces or consumes a string that may not have sufficient space for a null-terminator. | | test.c:26:3:26:10 | call to snprintf | Expression produces or consumes a string that may not have sufficient space for a null-terminator. | diff --git a/c/cert/test/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.expected b/c/cert/test/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.expected index 4099e3fb1a..341440d589 100644 --- a/c/cert/test/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.expected +++ b/c/cert/test/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.expected @@ -1,3 +1,12 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:55,33-41) +WARNING: Module DataFlow has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:55,73-81) +WARNING: Module DataFlow has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:61,33-41) +WARNING: Module DataFlow has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:61,57-65) +WARNING: Module DataFlow has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:69,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:69,69-77) +WARNING: Module TaintTracking has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:55,7-20) +WARNING: Module TaintTracking has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:61,7-20) +WARNING: Module TaintTracking has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:69,5-18) | test.c:19:3:19:8 | call to printf | String modified by $@ is passed to function expecting a null-terminated string. | test.c:7:20:7:24 | Cod | this expression | | test.c:20:3:20:8 | call to printf | String modified by $@ is passed to function expecting a null-terminated string. | test.c:7:20:7:24 | Cod | this expression | | test.c:22:3:22:8 | call to printf | String modified by $@ is passed to function expecting a null-terminated string. | test.c:13:3:13:9 | call to strncpy | this expression | diff --git a/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected b/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected index 913f6f1c34..d9cd037d42 100644 --- a/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected +++ b/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected @@ -1,3 +1,9 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:47,36-44) +WARNING: Module DataFlow has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:48,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:50,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:55,25-33) +WARNING: Module DataFlow has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:71,28-36) +WARNING: Module DataFlow has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:71,51-59) | test.c:18:6:18:6 | 0 | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter | | test.c:19:6:19:7 | ar | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter | | test.c:21:6:21:9 | ar2p | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter | diff --git a/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected b/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected index cded1a0a89..ef6703a285 100644 --- a/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected +++ b/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected @@ -1,3 +1,7 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:22,54-62) +WARNING: Module DataFlow has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:23,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:49,20-28) +WARNING: Module TaintTracking has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:57,43-56) edges | test.c:12:13:12:15 | a | test.c:14:10:14:10 | a | provenance | | | test.c:12:13:12:15 | a | test.c:23:13:23:13 | a | provenance | | diff --git a/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected b/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected index 6111072ba8..3382b66847 100644 --- a/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected +++ b/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected @@ -1,3 +1,4 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (FileOpenForReadAndWriteOnDifferentStreams.ql:38,9-17) | test.c:6:14:6:18 | call to fopen | The same file was already opened $@. Files should not be read and written at the same time using different streams. | test.c:5:14:5:18 | call to fopen | here | | test.c:17:14:17:18 | call to fopen | The same file was already opened $@. Files should not be read and written at the same time using different streams. | test.c:16:14:16:18 | call to fopen | here | | test.c:33:14:33:18 | call to fopen | The same file was already opened $@. Files should not be read and written at the same time using different streams. | test.c:32:14:32:18 | call to fopen | here | diff --git a/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected b/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected index 0bfce133c5..08363e7dda 100644 --- a/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected +++ b/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected @@ -1,2 +1,8 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:18,32-40) +WARNING: Module DataFlow has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:19,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:24,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:30,21-29) +WARNING: Module DataFlow has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:32,6-14) +WARNING: Module DataFlow has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:35,28-36) | test.c:10:3:10:9 | call to fprintf | Attempt to write to a $@ opened as read-only. | test.c:9:14:9:18 | call to fopen | stream | | test.c:15:3:15:9 | call to fprintf | Attempt to write to a $@ opened as read-only. | test.c:18:14:18:18 | call to fopen | stream | diff --git a/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected b/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected index 709d8b002c..9e975d34e4 100644 --- a/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected +++ b/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected @@ -1,2 +1,10 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:22,28-36) +WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:23,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:27,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:36,23-31) +WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:41,17-25) +WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:50,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:58,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:58,46-54) | test.c:6:7:6:20 | ... != ... | The check is not reliable as the type of the return value of $@ is converted. | test.c:5:14:5:20 | call to getchar | call to getchar | | test.c:13:7:13:15 | ... != ... | The check is not reliable as the type of the return value of $@ is converted. | test.c:12:14:12:20 | call to getchar | call to getchar | diff --git a/cpp/autosar/test/rules/A13-1-3/UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.expected b/cpp/autosar/test/rules/A13-1-3/UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.expected index 53dc884023..11b622f271 100644 --- a/cpp/autosar/test/rules/A13-1-3/UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.expected +++ b/cpp/autosar/test/rules/A13-1-3/UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.expected @@ -1 +1,4 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.ql:27,33-41) +WARNING: Module DataFlow has been deprecated and may be removed in future (UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.ql:28,5-13) +WARNING: Module TaintTracking has been deprecated and may be removed in future (UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.ql:27,7-20) | test.cpp:47:8:47:23 | operator ""_uds5 | User defined literal operator returns $@, which is not converted from a passed parameter | test.cpp:48:10:48:12 | 0.0 | expression | diff --git a/cpp/autosar/test/rules/A13-2-1/AssignmentOperatorReturnThis.expected b/cpp/autosar/test/rules/A13-2-1/AssignmentOperatorReturnThis.expected index e9929173b0..4a4697facc 100644 --- a/cpp/autosar/test/rules/A13-2-1/AssignmentOperatorReturnThis.expected +++ b/cpp/autosar/test/rules/A13-2-1/AssignmentOperatorReturnThis.expected @@ -1,3 +1,4 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (AssignmentOperatorReturnThis.ql:25,5-13) | test.cpp:10:12:10:20 | operator= | User-defined assignment operator $@ does not return *this | test.cpp:10:12:10:20 | operator= | user defined assignment operator | | test.cpp:17:11:17:19 | operator= | User-defined assignment operator $@ does not return *this | test.cpp:17:11:17:19 | operator= | user defined assignment operator | | test.cpp:24:12:24:20 | operator= | User-defined assignment operator $@ does not return *this | test.cpp:24:12:24:20 | operator= | user defined assignment operator | diff --git a/cpp/autosar/test/rules/A15-1-3/ThrownExceptionsShouldBeUnique.expected b/cpp/autosar/test/rules/A15-1-3/ThrownExceptionsShouldBeUnique.expected index b085736659..92504006b9 100644 --- a/cpp/autosar/test/rules/A15-1-3/ThrownExceptionsShouldBeUnique.expected +++ b/cpp/autosar/test/rules/A15-1-3/ThrownExceptionsShouldBeUnique.expected @@ -1,3 +1,4 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (ThrownExceptionsShouldBeUnique.ql:24,3-11) | test.cpp:6:5:6:26 | throw ... | The $@ thrown here is a possible duplicate of the $@ thrown $@. | test.cpp:6:5:6:26 | call to exception | std::exception exception | test.cpp:14:5:14:26 | call to exception | exception | test.cpp:14:5:14:26 | throw ... | here | | test.cpp:8:5:8:53 | throw ... | The $@ thrown here is a possible duplicate of the $@ thrown $@. | test.cpp:8:5:8:53 | call to runtime_error | std::runtime_error exception | test.cpp:16:5:16:53 | call to runtime_error | exception | test.cpp:16:5:16:53 | throw ... | here | | test.cpp:14:5:14:26 | throw ... | The $@ thrown here is a possible duplicate of the $@ thrown $@. | test.cpp:14:5:14:26 | call to exception | std::exception exception | test.cpp:6:5:6:26 | call to exception | exception | test.cpp:6:5:6:26 | throw ... | here | diff --git a/cpp/autosar/test/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.expected b/cpp/autosar/test/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.expected index 941771dada..2fd57c3b20 100644 --- a/cpp/autosar/test/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.expected +++ b/cpp/autosar/test/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.expected @@ -1,3 +1,12 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:47,12-20) +WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:48,30-38) +WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:48,57-65) +WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:74,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:74,25-33) +WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:75,7-15) +WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:130,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:130,25-33) +WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:130,54-62) edges | test.cpp:12:16:12:27 | new [bad_alloc] | test.cpp:14:33:16:5 | { ... } [bad_alloc] | | test.cpp:13:7:13:28 | throw ... [exception] | test.cpp:14:33:16:5 | { ... } [exception] | diff --git a/cpp/autosar/test/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.expected b/cpp/autosar/test/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.expected index 5f752403dc..6babf2c883 100644 --- a/cpp/autosar/test/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.expected +++ b/cpp/autosar/test/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.expected @@ -1,3 +1,10 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:26,67-75) +WARNING: Module DataFlow has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:27,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:39,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:50,34-42) +WARNING: Module DataFlow has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:50,57-65) +WARNING: Module DataFlow has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:58,25-33) +WARNING: Module TaintTracking has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:70,3-16) edges | test.cpp:3:36:3:45 | new[] | test.cpp:19:27:19:44 | call to allocate_int_array | provenance | | | test.cpp:3:36:3:45 | new[] | test.cpp:23:12:23:29 | call to allocate_int_array | provenance | | diff --git a/cpp/autosar/test/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.expected b/cpp/autosar/test/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.expected index d9dd02c054..cf611ded5b 100644 --- a/cpp/autosar/test/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.expected +++ b/cpp/autosar/test/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.expected @@ -1,3 +1,7 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:55,34-42) +WARNING: Module DataFlow has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:57,26-34) +WARNING: Module TaintTracking has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:71,5-18) +WARNING: Module TaintTracking has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:76,41-54) | test.cpp:17:17:17:29 | new | StructA object of size 8 bytes does not appear to outlive the function, but is created on the heap instead of the stack. | | test.cpp:21:17:21:32 | new[] | StructA[] object of size 800 bytes does not appear to outlive the function, but is created on the heap instead of the stack. | | test.cpp:35:20:35:44 | call to make_shared | StructA object of size 8 bytes does not appear to outlive the function, but is created on the heap instead of the stack. | diff --git a/cpp/autosar/test/rules/A18-9-4/ArgumentToForwardSubsequentlyUsed.expected b/cpp/autosar/test/rules/A18-9-4/ArgumentToForwardSubsequentlyUsed.expected index 1c72dd7bf3..2875a68f28 100644 --- a/cpp/autosar/test/rules/A18-9-4/ArgumentToForwardSubsequentlyUsed.expected +++ b/cpp/autosar/test/rules/A18-9-4/ArgumentToForwardSubsequentlyUsed.expected @@ -1 +1,4 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (ArgumentToForwardSubsequentlyUsed.ql:22,10-18) +WARNING: Module DataFlow has been deprecated and may be removed in future (ArgumentToForwardSubsequentlyUsed.ql:24,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (ArgumentToForwardSubsequentlyUsed.ql:24,30-38) | test.cpp:8:5:8:6 | t2 | The argument $@ of `std::forward` may be indeterminate when accessed at this location. | test.cpp:7:45:7:46 | t2 | t2 | diff --git a/cpp/autosar/test/rules/A20-8-4/SharedPointerUsedWithNoOwnershipSharing.expected b/cpp/autosar/test/rules/A20-8-4/SharedPointerUsedWithNoOwnershipSharing.expected index f15f142b3b..03406ac254 100644 --- a/cpp/autosar/test/rules/A20-8-4/SharedPointerUsedWithNoOwnershipSharing.expected +++ b/cpp/autosar/test/rules/A20-8-4/SharedPointerUsedWithNoOwnershipSharing.expected @@ -1,3 +1,4 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (SharedPointerUsedWithNoOwnershipSharing.ql:47,7-15) | test.cpp:14:24:14:26 | sp3 | The ownership of shared_ptr $@ is not shared within or passed out of the local scope of function $@. | test.cpp:14:24:14:26 | sp3 | sp3 | test.cpp:11:22:11:23 | f1 | f1 | | test.cpp:16:24:16:26 | sp5 | The ownership of shared_ptr $@ is not shared within or passed out of the local scope of function $@. | test.cpp:16:24:16:26 | sp5 | sp5 | test.cpp:11:22:11:23 | f1 | f1 | | test.cpp:17:24:17:26 | sp6 | The ownership of shared_ptr $@ is not shared within or passed out of the local scope of function $@. | test.cpp:17:24:17:26 | sp6 | sp6 | test.cpp:11:22:11:23 | f1 | f1 | diff --git a/cpp/autosar/test/rules/A27-0-4/CStyleStringsUsed.expected b/cpp/autosar/test/rules/A27-0-4/CStyleStringsUsed.expected index 6184aad74e..eaaaaac98d 100644 --- a/cpp/autosar/test/rules/A27-0-4/CStyleStringsUsed.expected +++ b/cpp/autosar/test/rules/A27-0-4/CStyleStringsUsed.expected @@ -1,3 +1,6 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (CStyleStringsUsed.ql:39,3-11) +WARNING: Module DataFlow has been deprecated and may be removed in future (CStyleStringsUsed.ql:39,23-31) +WARNING: Module DataFlow has been deprecated and may be removed in future (CStyleStringsUsed.ql:39,47-55) | test.cpp:7:20:7:27 | CodeQL | Usage of C-style string in $@. | test.cpp:7:20:7:27 | CodeQL | expression | | test.cpp:7:20:7:27 | CodeQL | Usage of C-style string in $@. | test.cpp:16:16:16:17 | a1 | expression | | test.cpp:8:22:8:26 | call to c_str | Usage of C-style string in $@. | test.cpp:8:22:8:26 | call to c_str | expression | diff --git a/cpp/autosar/test/rules/A5-0-4/PointerArithmeticUsedWithPointersToNonFinalClasses.expected b/cpp/autosar/test/rules/A5-0-4/PointerArithmeticUsedWithPointersToNonFinalClasses.expected index b47755725c..9f97a58467 100644 --- a/cpp/autosar/test/rules/A5-0-4/PointerArithmeticUsedWithPointersToNonFinalClasses.expected +++ b/cpp/autosar/test/rules/A5-0-4/PointerArithmeticUsedWithPointersToNonFinalClasses.expected @@ -1,3 +1,7 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (PointerArithmeticUsedWithPointersToNonFinalClasses.ql:45,62-70) +WARNING: Module DataFlow has been deprecated and may be removed in future (PointerArithmeticUsedWithPointersToNonFinalClasses.ql:46,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (PointerArithmeticUsedWithPointersToNonFinalClasses.ql:55,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (PointerArithmeticUsedWithPointersToNonFinalClasses.ql:61,3-11) edges | test.cpp:10:18:10:20 | foo | test.cpp:11:23:11:25 | foo | provenance | | | test.cpp:10:18:10:20 | foo | test.cpp:11:50:11:52 | foo | provenance | | diff --git a/cpp/autosar/test/rules/A5-1-7/LambdaPassedToDecltype.expected b/cpp/autosar/test/rules/A5-1-7/LambdaPassedToDecltype.expected index 8f6447a96b..03eaab82aa 100644 --- a/cpp/autosar/test/rules/A5-1-7/LambdaPassedToDecltype.expected +++ b/cpp/autosar/test/rules/A5-1-7/LambdaPassedToDecltype.expected @@ -1 +1,7 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:20,55-63) +WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:21,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:23,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:28,44-52) +WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:39,47-55) +WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:40,9-17) | test.cpp:14:23:14:24 | decltype(...) | Lambda $@ passed as operand to decltype. | test.cpp:5:13:5:30 | [...](...){...} | expression | diff --git a/cpp/autosar/test/rules/A5-1-7/LambdaPassedToTypeid.expected b/cpp/autosar/test/rules/A5-1-7/LambdaPassedToTypeid.expected index 6d65a7b5d5..916b9db113 100644 --- a/cpp/autosar/test/rules/A5-1-7/LambdaPassedToTypeid.expected +++ b/cpp/autosar/test/rules/A5-1-7/LambdaPassedToTypeid.expected @@ -1,3 +1,7 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToTypeid.ql:21,50-58) +WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToTypeid.ql:22,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToTypeid.ql:24,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToTypeid.ql:27,39-47) edges | test.cpp:5:13:5:30 | [...](...){...} | test.cpp:8:38:8:39 | l1 | provenance | | | test.cpp:6:13:6:30 | [...](...){...} | test.cpp:9:38:9:39 | l2 | provenance | | diff --git a/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected b/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected index dbf223e0cf..dd499ceb57 100644 --- a/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected +++ b/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected @@ -1,3 +1,9 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (VariableMissingConstexpr.ql:64,7-15) +WARNING: Module DataFlow has been deprecated and may be removed in future (VariableMissingConstexpr.ql:79,10-18) +WARNING: Module DataFlow has been deprecated and may be removed in future (VariableMissingConstexpr.ql:79,44-52) +WARNING: Module DataFlow has been deprecated and may be removed in future (VariableMissingConstexpr.ql:80,17-25) +WARNING: Module DataFlow has been deprecated and may be removed in future (VariableMissingConstexpr.ql:81,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (VariableMissingConstexpr.ql:82,9-17) | test.cpp:4:5:4:6 | g1 | Variable g1 could be marked 'constexpr'. | | test.cpp:6:5:6:6 | g2 | Variable g2 could be marked 'constexpr'. | | test.cpp:13:14:13:15 | lc | Variable lc could be marked 'constexpr'. | diff --git a/cpp/autosar/test/rules/A7-5-1/InvalidFunctionReturnType.expected b/cpp/autosar/test/rules/A7-5-1/InvalidFunctionReturnType.expected index b6d9490803..0ab837454a 100644 --- a/cpp/autosar/test/rules/A7-5-1/InvalidFunctionReturnType.expected +++ b/cpp/autosar/test/rules/A7-5-1/InvalidFunctionReturnType.expected @@ -1,2 +1,5 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (InvalidFunctionReturnType.ql:27,3-11) +WARNING: Module DataFlow has been deprecated and may be removed in future (InvalidFunctionReturnType.ql:27,23-31) +WARNING: Module DataFlow has been deprecated and may be removed in future (InvalidFunctionReturnType.ql:27,51-59) | test.cpp:5:3:5:11 | return ... | Function test_refconst_return returns a reference or a pointer to $@ that is passed by reference to const. | test.cpp:4:44:4:44 | x | parameter | | test.cpp:8:3:8:14 | return ... | Function test_ptrconst_return returns a reference or a pointer to $@ that is passed by reference to const. | test.cpp:7:44:7:44 | x | parameter | diff --git a/cpp/autosar/test/rules/A8-4-11/SmartPointerAsParameterWithoutLifetimeSemantics.expected b/cpp/autosar/test/rules/A8-4-11/SmartPointerAsParameterWithoutLifetimeSemantics.expected index b751d81835..be4a4107fd 100644 --- a/cpp/autosar/test/rules/A8-4-11/SmartPointerAsParameterWithoutLifetimeSemantics.expected +++ b/cpp/autosar/test/rules/A8-4-11/SmartPointerAsParameterWithoutLifetimeSemantics.expected @@ -1,3 +1,5 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (SmartPointerAsParameterWithoutLifetimeSemantics.ql:47,3-11) +WARNING: Module DataFlow has been deprecated and may be removed in future (SmartPointerAsParameterWithoutLifetimeSemantics.ql:56,5-13) | test.cpp:7:41:7:43 | up1 | Function $@ takes smart pointer parameter 'up1' but does not implement any lifetime-affecting operations. | test.cpp:7:6:7:18 | smart_ptr_get | smart_ptr_get | | test.cpp:16:53:16:55 | sp1 | Function $@ takes smart pointer parameter 'sp1' but does not implement any lifetime-affecting operations. | test.cpp:16:6:16:29 | smart_ptr_ref_assign_ref | smart_ptr_ref_assign_ref | | test.cpp:28:55:28:57 | sp1 | Function $@ takes smart pointer parameter 'sp1' but does not implement any lifetime-affecting operations. | test.cpp:28:6:28:31 | smart_ptr_ref_noncompliant | smart_ptr_ref_noncompliant | diff --git a/cpp/autosar/test/rules/A8-4-12/UniquePtrPassedToFunctionWithImproperSemantics.expected b/cpp/autosar/test/rules/A8-4-12/UniquePtrPassedToFunctionWithImproperSemantics.expected index a01b93335d..b2273e66f3 100644 --- a/cpp/autosar/test/rules/A8-4-12/UniquePtrPassedToFunctionWithImproperSemantics.expected +++ b/cpp/autosar/test/rules/A8-4-12/UniquePtrPassedToFunctionWithImproperSemantics.expected @@ -1,3 +1,5 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (UniquePtrPassedToFunctionWithImproperSemantics.ql:41,3-11) +WARNING: Module DataFlow has been deprecated and may be removed in future (UniquePtrPassedToFunctionWithImproperSemantics.ql:51,5-13) | test.cpp:13:55:13:56 | v1 | Parameter of type std::unique_ptr passed as lvalue reference but not used to modify underlying object. | | test.cpp:17:47:17:48 | v1 | Parameter of type std::unique_ptr passed as lvalue reference but not used to modify underlying object. | | test.cpp:22:27:22:28 | v1 | Parameter of type std::unique_ptr passed as lvalue reference but not used to modify underlying object. | diff --git a/cpp/autosar/test/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.expected b/cpp/autosar/test/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.expected index e3cfa71bb7..15e513c639 100644 --- a/cpp/autosar/test/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.expected +++ b/cpp/autosar/test/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.expected @@ -1,3 +1,5 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (InOutParametersDeclaredAsTNotModified.ql:49,7-15) +WARNING: Module DataFlow has been deprecated and may be removed in future (InOutParametersDeclaredAsTNotModified.ql:63,7-15) | test.cpp:4:13:4:13 | i | In-out parameter i that is not written to. | | test.cpp:7:22:7:24 | str | In-out parameter str that is not read from. | | test.cpp:18:14:18:14 | i | In-out parameter i that is not read from. | diff --git a/cpp/autosar/test/rules/A9-3-1/ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.expected b/cpp/autosar/test/rules/A9-3-1/ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.expected index 04c1f35a45..84d7f2d7f0 100644 --- a/cpp/autosar/test/rules/A9-3-1/ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.expected +++ b/cpp/autosar/test/rules/A9-3-1/ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.expected @@ -1,3 +1,6 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.ql:73,3-11) +WARNING: Module DataFlow has been deprecated and may be removed in future (ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.ql:73,23-31) +WARNING: Module DataFlow has been deprecated and may be removed in future (ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.ql:73,46-54) | test.cpp:20:8:20:12 | getB2 | Member function A::getB2 $@ a non-const raw pointer or reference to a private or protected $@. | test.cpp:20:25:20:25 | b | returns | test.cpp:54:7:54:7 | b | field | | test.cpp:22:8:22:12 | getB3 | Member function A::getB3 $@ a non-const raw pointer or reference to a private or protected $@. | test.cpp:22:25:22:26 | & ... | returns | test.cpp:54:7:54:7 | b | field | | test.cpp:24:8:24:13 | getB33 | Member function A::getB33 $@ a non-const raw pointer or reference to a private or protected $@. | test.cpp:26:12:26:13 | bb | returns | test.cpp:54:7:54:7 | b | field | diff --git a/cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.expected b/cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.expected index 76cbcebed0..15f4e9a793 100644 --- a/cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.expected +++ b/cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.expected @@ -1 +1,4 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (FunctionErroneousReturnValueNotTested.ql:70,9-17) +WARNING: Module DataFlow has been deprecated and may be removed in future (FunctionErroneousReturnValueNotTested.ql:70,29-37) +WARNING: Module DataFlow has been deprecated and may be removed in future (FunctionErroneousReturnValueNotTested.ql:70,53-61) | test.cpp:16:3:16:8 | call to remove | Return value is not tested for errors. | diff --git a/cpp/autosar/test/rules/M3-9-3/UnderlyingBitRepresentationsOfFloatingPointValuesUsed.expected b/cpp/autosar/test/rules/M3-9-3/UnderlyingBitRepresentationsOfFloatingPointValuesUsed.expected index 9aec2314da..2545360a7b 100644 --- a/cpp/autosar/test/rules/M3-9-3/UnderlyingBitRepresentationsOfFloatingPointValuesUsed.expected +++ b/cpp/autosar/test/rules/M3-9-3/UnderlyingBitRepresentationsOfFloatingPointValuesUsed.expected @@ -1,2 +1,5 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (UnderlyingBitRepresentationsOfFloatingPointValuesUsed.ql:27,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (UnderlyingBitRepresentationsOfFloatingPointValuesUsed.ql:36,10-18) +WARNING: Module DataFlow has been deprecated and may be removed in future (UnderlyingBitRepresentationsOfFloatingPointValuesUsed.ql:37,5-13) | test.cpp:5:3:5:20 | ... &= ... | Modification of bit-representation of float originated at $@ | test.cpp:4:24:4:60 | reinterpret_cast... | cast | | test.cpp:12:3:12:14 | ... &= ... | Modification of bit-representation of float originated at $@ | test.cpp:11:18:11:30 | (uint8_t *)... | cast | diff --git a/cpp/autosar/test/rules/M9-3-1/ConstMemberFunctionReturnsNonConstPointer.expected b/cpp/autosar/test/rules/M9-3-1/ConstMemberFunctionReturnsNonConstPointer.expected index ee9652f505..eee85d22c0 100644 --- a/cpp/autosar/test/rules/M9-3-1/ConstMemberFunctionReturnsNonConstPointer.expected +++ b/cpp/autosar/test/rules/M9-3-1/ConstMemberFunctionReturnsNonConstPointer.expected @@ -1,3 +1,5 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (ConstMemberFunctionReturnsNonConstPointer.ql:53,7-15) +WARNING: Module DataFlow has been deprecated and may be removed in future (ConstMemberFunctionReturnsNonConstPointer.ql:55,7-15) | test.cpp:8:8:8:11 | getA | Const member function returns a pointer to class data $@. | test.cpp:3:8:3:8 | a | a | | test.cpp:9:8:9:11 | getB | Const member function returns a pointer to class data $@. | test.cpp:4:8:4:8 | b | b | | test.cpp:11:6:11:12 | getThis | Const member function returns a pointer to class data $@. | test.cpp:11:36:11:39 | this | this | diff --git a/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected b/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected index 4e87d1436c..06abadc4fe 100644 --- a/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected +++ b/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected @@ -1,3 +1,12 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:97,7-15) +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:97,27-35) +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:98,9-17) +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:102,9-17) +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:102,29-37) +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:103,11-19) +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:113,35-43) +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:114,11-19) +WARNING: Module TaintTracking has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:113,9-22) | test.cpp:8:42:8:46 | call to begin | Output iterator for $@ is not guaranteed to be large enough for the input iterator. | test.cpp:8:3:8:11 | call to copy | call to copy | | test.cpp:17:42:17:46 | call to begin | Output iterator for $@ is not guaranteed to be large enough for the input iterator. | test.cpp:17:3:17:11 | call to copy | call to copy | | test.cpp:55:42:55:46 | call to begin | Output iterator for $@ is not guaranteed to be large enough for the input iterator. | test.cpp:55:3:55:11 | call to copy | call to copy | diff --git a/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected b/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected index 61260a0579..5730a54b2c 100644 --- a/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected +++ b/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected @@ -1,3 +1,9 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (UseValidIteratorRanges.ql:23,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (UseValidIteratorRanges.ql:23,25-33) +WARNING: Module DataFlow has been deprecated and may be removed in future (UseValidIteratorRanges.ql:24,7-15) +WARNING: Module DataFlow has been deprecated and may be removed in future (UseValidIteratorRanges.ql:30,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (UseValidIteratorRanges.ql:30,25-33) +WARNING: Module DataFlow has been deprecated and may be removed in future (UseValidIteratorRanges.ql:31,7-15) | test.cpp:7:3:7:15 | call to for_each | The $@ of iterator range function does not point to the end of an iterator. | test.cpp:7:28:7:32 | call to begin | argument | | test.cpp:7:3:7:15 | call to for_each | The $@ of iterator range function does not point to the start of an iterator. | test.cpp:7:19:7:21 | call to end | argument | | test.cpp:8:3:8:15 | call to for_each | The $@ of iterator range function does not point to the end of an iterator. | test.cpp:8:30:8:34 | call to begin | argument | diff --git a/cpp/cert/test/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.expected b/cpp/cert/test/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.expected index eabb6d7515..1f97f2ca40 100644 --- a/cpp/cert/test/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.expected +++ b/cpp/cert/test/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.expected @@ -1,3 +1,7 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:41,62-70) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:42,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:51,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:57,3-11) edges | test.cpp:15:19:15:21 | foo | test.cpp:16:24:16:26 | foo | provenance | | | test.cpp:15:19:15:21 | foo | test.cpp:16:51:16:53 | foo | provenance | | diff --git a/cpp/cert/test/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.expected b/cpp/cert/test/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.expected index b432856e8b..243602e104 100644 --- a/cpp/cert/test/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.expected +++ b/cpp/cert/test/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.expected @@ -1,3 +1,27 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:24,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:24,59-67) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:27,33-41) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:27,57-65) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:31,33-41) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:31,59-67) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:40,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:40,25-33) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:40,53-61) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:43,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:43,57-65) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:52,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:52,55-63) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:59,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:59,57-65) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:71,31-39) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:71,55-63) +WARNING: Module TaintTracking has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:24,5-18) +WARNING: Module TaintTracking has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:27,7-20) +WARNING: Module TaintTracking has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:31,7-20) +WARNING: Module TaintTracking has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:43,5-18) +WARNING: Module TaintTracking has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:52,5-18) +WARNING: Module TaintTracking has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:59,5-18) +WARNING: Module TaintTracking has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:71,5-18) | test.cpp:82:3:82:4 | call to f2 | Depending on the order of evaluation for the arguments $@ and $@ for side effects on shared state is unspecified and can result in unexpected behavior. | test.cpp:82:6:82:7 | call to f5 | call to f5 | test.cpp:82:12:82:13 | call to f6 | call to f6 | | test.cpp:84:3:84:4 | call to f2 | Depending on the order of evaluation for the arguments $@ and $@ for side effects on shared state is unspecified and can result in unexpected behavior. | test.cpp:84:6:84:7 | call to f5 | call to f5 | test.cpp:84:12:84:13 | call to f7 | call to f7 | | test.cpp:87:3:87:4 | call to f2 | Depending on the order of evaluation for the arguments $@ and $@ for side effects on shared state is unspecified and can result in unexpected behavior. | test.cpp:87:9:87:10 | call to m1 | call to m1 | test.cpp:87:18:87:19 | call to m1 | call to m1 | diff --git a/cpp/cert/test/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.expected b/cpp/cert/test/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.expected index 9c6e6dd071..a3c0c08011 100644 --- a/cpp/cert/test/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.expected +++ b/cpp/cert/test/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.expected @@ -1,3 +1,7 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:19,44-52) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:20,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:22,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:27,33-41) edges | test.cpp:6:19:6:37 | new[] | test.cpp:9:12:9:13 | l1 | provenance | | | test.cpp:7:22:7:40 | new[] | test.cpp:10:12:10:13 | l2 | provenance | | diff --git a/cpp/cert/test/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.expected b/cpp/cert/test/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.expected index b7452ec199..b30e94a38e 100644 --- a/cpp/cert/test/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.expected +++ b/cpp/cert/test/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.expected @@ -1,2 +1,9 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:59,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:61,36-44) +WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:77,46-54) +WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:78,22-30) +WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:82,20-28) +WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:85,35-43) +WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:90,38-46) | test.cpp:24:7:24:34 | new | nothrow new allocation of $@ returns here without a subsequent check to see whether the pointer is valid. | test.cpp:24:7:24:34 | new | StructA * | | test.cpp:40:17:40:38 | call to allocate_without_check | nothrow new allocation of $@ returns here without a subsequent check to see whether the pointer is valid. | test.cpp:35:17:35:44 | new | StructA * | diff --git a/cpp/cert/test/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.expected b/cpp/cert/test/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.expected index 0128221ffc..adabb21674 100644 --- a/cpp/cert/test/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.expected +++ b/cpp/cert/test/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.expected @@ -1,3 +1,4 @@ +WARNING: Module TaintTracking has been deprecated and may be removed in future (BadlySeededRandomNumberGenerator.ql:37,7-20) | test.cpp:9:33:9:33 | call to linear_congruential_engine | Random number generator linear_congruential_engine is default-initialized and is therefore not properly seeded. | | test.cpp:10:30:10:31 | call to linear_congruential_engine | Random number generator linear_congruential_engine is default-initialized and is therefore not properly seeded. | | test.cpp:11:21:11:22 | call to linear_congruential_engine | Random number generator linear_congruential_engine is default-initialized and is therefore not properly seeded. | From e5cdb71cf7b21c1d03fa209be40fc6fb16a59087 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 23 May 2024 17:42:29 +0200 Subject: [PATCH 017/370] C++: Update expected test results after dataflow library changes and merge from main --- ...riableViaPointerOfIncompatibleType.expected | 2 +- ...tPointersAddressingDifferentArrays.expected | 4 ++-- ...tionalOperatorsWithDifferingArrays.expected | 6 +++--- ...mentOfAnArrayPassedToASmartPointer.expected | 1 + .../A7-1-2/VariableMissingConstexpr.expected | 6 ------ ...icCppLibraryFunctionsDoNotOverflow.expected | 18 +++++++++--------- ...tUseAnAdditiveOperatorOnAnIterator.expected | 9 +++++++++ ...tPointersAddressingDifferentArrays.expected | 4 ++-- ...tionalOperatorsWithDifferingArrays.expected | 6 +++--- ...ValueStoredInUnrelatedSmartPointer.expected | 5 +++-- 10 files changed, 33 insertions(+), 28 deletions(-) diff --git a/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected b/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected index 3316256acb..6cf822fa15 100644 --- a/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected +++ b/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected @@ -16,7 +16,7 @@ edges | test.c:97:32:97:37 | call to malloc | test.c:98:40:98:41 | s2 | provenance | | | test.c:98:32:98:38 | call to realloc | test.c:99:3:99:4 | s3 | provenance | | | test.c:98:32:98:38 | call to realloc | test.c:100:10:100:11 | s3 | provenance | | -| test.c:98:40:98:41 | s2 | test.c:98:32:98:38 | call to realloc | provenance | | +| test.c:98:40:98:41 | s2 | test.c:98:32:98:38 | call to realloc | provenance | Config | nodes | test.c:6:19:6:20 | & ... | semmle.label | & ... | | test.c:11:10:11:11 | & ... | semmle.label | & ... | diff --git a/c/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected b/c/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected index c595e7e5f7..75866b8503 100644 --- a/c/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected +++ b/c/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected @@ -4,10 +4,10 @@ problems | test.c:13:10:13:11 | p4 | test.c:5:14:5:15 | l2 | test.c:13:10:13:11 | p4 | Subtraction between left operand pointing to array $@ and other operand pointing to array $@. | test.c:3:7:3:8 | l2 | l2 | test.c:2:7:2:8 | l1 | l1 | | test.c:13:15:13:16 | l1 | test.c:13:15:13:16 | l1 | test.c:13:15:13:16 | l1 | Subtraction between right operand pointing to array $@ and other operand pointing to array $@. | test.c:2:7:2:8 | l1 | l1 | test.c:3:7:3:8 | l2 | l2 | edges -| test.c:4:14:4:15 | l1 | test.c:4:14:4:18 | access to array | provenance | | +| test.c:4:14:4:15 | l1 | test.c:4:14:4:18 | access to array | provenance | Config | | test.c:4:14:4:18 | access to array | test.c:10:10:10:11 | p1 | provenance | | | test.c:4:14:4:18 | access to array | test.c:12:10:12:11 | p1 | provenance | | -| test.c:5:14:5:15 | l2 | test.c:5:14:5:19 | access to array | provenance | | +| test.c:5:14:5:15 | l2 | test.c:5:14:5:19 | access to array | provenance | Config | | test.c:5:14:5:19 | access to array | test.c:11:10:11:11 | p2 | provenance | | | test.c:5:14:5:19 | access to array | test.c:12:15:12:16 | p2 | provenance | | | test.c:5:14:5:19 | access to array | test.c:13:10:13:11 | p4 | provenance | | diff --git a/c/common/test/rules/donotuserelationaloperatorswithdifferingarrays/DoNotUseRelationalOperatorsWithDifferingArrays.expected b/c/common/test/rules/donotuserelationaloperatorswithdifferingarrays/DoNotUseRelationalOperatorsWithDifferingArrays.expected index 05c0ed4ca0..bda6c7ad05 100644 --- a/c/common/test/rules/donotuserelationaloperatorswithdifferingarrays/DoNotUseRelationalOperatorsWithDifferingArrays.expected +++ b/c/common/test/rules/donotuserelationaloperatorswithdifferingarrays/DoNotUseRelationalOperatorsWithDifferingArrays.expected @@ -11,17 +11,17 @@ problems | test.c:25:7:25:14 | ... >= ... | test.c:25:13:25:14 | l3 | test.c:25:13:25:14 | l3 | Compare operation >= comparing right operand pointing to array $@ and other operand pointing to array $@. | test.c:4:7:4:8 | l3 | l3 | test.c:2:7:2:8 | l1 | l1 | edges | test.c:6:13:6:14 | l1 | test.c:13:12:13:13 | p0 | provenance | | -| test.c:7:14:7:15 | l1 | test.c:7:14:7:18 | access to array | provenance | | +| test.c:7:14:7:15 | l1 | test.c:7:14:7:18 | access to array | provenance | Config | | test.c:7:14:7:18 | access to array | test.c:11:7:11:8 | p1 | provenance | | | test.c:7:14:7:18 | access to array | test.c:13:7:13:8 | p1 | provenance | | | test.c:7:14:7:18 | access to array | test.c:15:13:15:14 | p1 | provenance | | | test.c:7:14:7:18 | access to array | test.c:17:7:17:8 | p1 | provenance | | | test.c:7:14:7:18 | access to array | test.c:23:13:23:14 | p1 | provenance | | | test.c:7:14:7:18 | access to array | test.c:25:7:25:8 | p1 | provenance | | -| test.c:8:14:8:15 | l1 | test.c:8:14:8:18 | access to array | provenance | | +| test.c:8:14:8:15 | l1 | test.c:8:14:8:18 | access to array | provenance | Config | | test.c:8:14:8:18 | access to array | test.c:11:12:11:13 | p2 | provenance | | | test.c:8:14:8:18 | access to array | test.c:21:7:21:8 | p2 | provenance | | -| test.c:9:14:9:15 | l2 | test.c:9:14:9:18 | access to array | provenance | | +| test.c:9:14:9:15 | l2 | test.c:9:14:9:18 | access to array | provenance | Config | | test.c:9:14:9:18 | access to array | test.c:21:12:21:13 | p3 | provenance | | nodes | test.c:6:13:6:14 | l1 | semmle.label | l1 | diff --git a/cpp/autosar/test/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.expected b/cpp/autosar/test/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.expected index 6babf2c883..e71e667685 100644 --- a/cpp/autosar/test/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.expected +++ b/cpp/autosar/test/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.expected @@ -11,6 +11,7 @@ edges | test.cpp:3:36:3:45 | new[] | test.cpp:27:20:27:37 | call to allocate_int_array | provenance | | | test.cpp:11:29:11:41 | call to unique_ptr | test.cpp:12:27:12:28 | v2 | provenance | | | test.cpp:12:27:12:28 | v2 | test.cpp:12:30:12:36 | call to release | provenance | | +| test.cpp:12:27:12:28 | v2 | test.cpp:12:30:12:36 | call to release | provenance | Config | | test.cpp:27:20:27:37 | call to allocate_int_array | test.cpp:32:12:32:20 | int_array | provenance | | nodes | test.cpp:3:36:3:45 | new[] | semmle.label | new[] | diff --git a/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected b/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected index dd499ceb57..dbf223e0cf 100644 --- a/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected +++ b/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected @@ -1,9 +1,3 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (VariableMissingConstexpr.ql:64,7-15) -WARNING: Module DataFlow has been deprecated and may be removed in future (VariableMissingConstexpr.ql:79,10-18) -WARNING: Module DataFlow has been deprecated and may be removed in future (VariableMissingConstexpr.ql:79,44-52) -WARNING: Module DataFlow has been deprecated and may be removed in future (VariableMissingConstexpr.ql:80,17-25) -WARNING: Module DataFlow has been deprecated and may be removed in future (VariableMissingConstexpr.ql:81,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (VariableMissingConstexpr.ql:82,9-17) | test.cpp:4:5:4:6 | g1 | Variable g1 could be marked 'constexpr'. | | test.cpp:6:5:6:6 | g2 | Variable g2 could be marked 'constexpr'. | | test.cpp:13:14:13:15 | lc | Variable lc could be marked 'constexpr'. | diff --git a/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected b/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected index 06abadc4fe..9259112890 100644 --- a/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected +++ b/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected @@ -1,12 +1,12 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:97,7-15) -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:97,27-35) -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:98,9-17) -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:102,9-17) -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:102,29-37) -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:103,11-19) -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:113,35-43) -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:114,11-19) -WARNING: Module TaintTracking has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:113,9-22) +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:88,7-15) +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:88,27-35) +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:89,9-17) +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:93,9-17) +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:93,29-37) +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:94,11-19) +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:104,35-43) +WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:105,11-19) +WARNING: Module TaintTracking has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:104,9-22) | test.cpp:8:42:8:46 | call to begin | Output iterator for $@ is not guaranteed to be large enough for the input iterator. | test.cpp:8:3:8:11 | call to copy | call to copy | | test.cpp:17:42:17:46 | call to begin | Output iterator for $@ is not guaranteed to be large enough for the input iterator. | test.cpp:17:3:17:11 | call to copy | call to copy | | test.cpp:55:42:55:46 | call to begin | Output iterator for $@ is not guaranteed to be large enough for the input iterator. | test.cpp:55:3:55:11 | call to copy | call to copy | diff --git a/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected b/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected index 0a06677b54..be69b2024d 100644 --- a/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected +++ b/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected @@ -1,3 +1,12 @@ +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:38,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:38,25-33) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:38,51-59) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:39,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:39,25-33) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:39,52-60) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:74,5-13) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:74,25-33) +WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:75,7-15) | test.cpp:8:7:8:7 | i | Increment of iterator may overflow since its bounds are not checked. | | test.cpp:9:9:9:9 | i | Increment of iterator may overflow since its bounds are not checked. | | test.cpp:10:9:10:9 | i | Increment of iterator may overflow since its bounds are not checked. | diff --git a/cpp/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected b/cpp/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected index dcbc6d05bc..2d293e6928 100644 --- a/cpp/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected +++ b/cpp/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected @@ -4,10 +4,10 @@ problems | test.cpp:13:10:13:11 | p4 | test.cpp:5:14:5:15 | l2 | test.cpp:13:10:13:11 | p4 | Subtraction between left operand pointing to array $@ and other operand pointing to array $@. | test.cpp:3:7:3:8 | l2 | l2 | test.cpp:2:7:2:8 | l1 | l1 | | test.cpp:13:15:13:16 | l1 | test.cpp:13:15:13:16 | l1 | test.cpp:13:15:13:16 | l1 | Subtraction between right operand pointing to array $@ and other operand pointing to array $@. | test.cpp:2:7:2:8 | l1 | l1 | test.cpp:3:7:3:8 | l2 | l2 | edges -| test.cpp:4:14:4:15 | l1 | test.cpp:4:14:4:18 | access to array | provenance | | +| test.cpp:4:14:4:15 | l1 | test.cpp:4:14:4:18 | access to array | provenance | Config | | test.cpp:4:14:4:18 | access to array | test.cpp:10:10:10:11 | p1 | provenance | | | test.cpp:4:14:4:18 | access to array | test.cpp:12:10:12:11 | p1 | provenance | | -| test.cpp:5:14:5:15 | l2 | test.cpp:5:14:5:19 | access to array | provenance | | +| test.cpp:5:14:5:15 | l2 | test.cpp:5:14:5:19 | access to array | provenance | Config | | test.cpp:5:14:5:19 | access to array | test.cpp:11:10:11:11 | p2 | provenance | | | test.cpp:5:14:5:19 | access to array | test.cpp:12:15:12:16 | p2 | provenance | | | test.cpp:5:14:5:19 | access to array | test.cpp:13:10:13:11 | p4 | provenance | | diff --git a/cpp/common/test/rules/donotuserelationaloperatorswithdifferingarrays/DoNotUseRelationalOperatorsWithDifferingArrays.expected b/cpp/common/test/rules/donotuserelationaloperatorswithdifferingarrays/DoNotUseRelationalOperatorsWithDifferingArrays.expected index f02c9a5712..cab80e0fe0 100644 --- a/cpp/common/test/rules/donotuserelationaloperatorswithdifferingarrays/DoNotUseRelationalOperatorsWithDifferingArrays.expected +++ b/cpp/common/test/rules/donotuserelationaloperatorswithdifferingarrays/DoNotUseRelationalOperatorsWithDifferingArrays.expected @@ -11,17 +11,17 @@ problems | test.cpp:25:7:25:14 | ... >= ... | test.cpp:25:13:25:14 | l3 | test.cpp:25:13:25:14 | l3 | Compare operation >= comparing right operand pointing to array $@ and other operand pointing to array $@. | test.cpp:4:7:4:8 | l3 | l3 | test.cpp:2:7:2:8 | l1 | l1 | edges | test.cpp:6:13:6:14 | l1 | test.cpp:13:12:13:13 | p0 | provenance | | -| test.cpp:7:14:7:15 | l1 | test.cpp:7:14:7:18 | access to array | provenance | | +| test.cpp:7:14:7:15 | l1 | test.cpp:7:14:7:18 | access to array | provenance | Config | | test.cpp:7:14:7:18 | access to array | test.cpp:11:7:11:8 | p1 | provenance | | | test.cpp:7:14:7:18 | access to array | test.cpp:13:7:13:8 | p1 | provenance | | | test.cpp:7:14:7:18 | access to array | test.cpp:15:13:15:14 | p1 | provenance | | | test.cpp:7:14:7:18 | access to array | test.cpp:17:7:17:8 | p1 | provenance | | | test.cpp:7:14:7:18 | access to array | test.cpp:23:13:23:14 | p1 | provenance | | | test.cpp:7:14:7:18 | access to array | test.cpp:25:7:25:8 | p1 | provenance | | -| test.cpp:8:14:8:15 | l1 | test.cpp:8:14:8:18 | access to array | provenance | | +| test.cpp:8:14:8:15 | l1 | test.cpp:8:14:8:18 | access to array | provenance | Config | | test.cpp:8:14:8:18 | access to array | test.cpp:11:12:11:13 | p2 | provenance | | | test.cpp:8:14:8:18 | access to array | test.cpp:21:7:21:8 | p2 | provenance | | -| test.cpp:9:14:9:15 | l2 | test.cpp:9:14:9:18 | access to array | provenance | | +| test.cpp:9:14:9:15 | l2 | test.cpp:9:14:9:18 | access to array | provenance | Config | | test.cpp:9:14:9:18 | access to array | test.cpp:21:12:21:13 | p3 | provenance | | nodes | test.cpp:6:13:6:14 | l1 | semmle.label | l1 | diff --git a/cpp/common/test/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.expected b/cpp/common/test/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.expected index 0b23493cfa..7790582443 100644 --- a/cpp/common/test/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.expected +++ b/cpp/common/test/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.expected @@ -11,10 +11,11 @@ edges | test.cpp:3:14:3:15 | v1 | test.cpp:7:28:7:29 | v2 | provenance | | | test.cpp:4:13:4:14 | v1 | test.cpp:7:28:7:29 | v2 | provenance | | | test.cpp:5:27:5:28 | v1 | test.cpp:5:27:5:29 | call to shared_ptr | provenance | | +| test.cpp:5:27:5:28 | v1 | test.cpp:5:27:5:29 | call to shared_ptr | provenance | Config | | test.cpp:5:27:5:29 | call to shared_ptr | test.cpp:6:28:6:29 | p1 | provenance | | | test.cpp:5:27:5:29 | call to shared_ptr | test.cpp:6:28:6:29 | p1 | provenance | | -| test.cpp:6:28:6:29 | p1 | test.cpp:6:31:6:33 | call to get | provenance | | -| test.cpp:6:28:6:29 | p1 | test.cpp:6:31:6:33 | call to get | provenance | | +| test.cpp:6:28:6:29 | p1 | test.cpp:6:31:6:33 | call to get | provenance | Config | +| test.cpp:6:28:6:29 | p1 | test.cpp:6:31:6:33 | call to get | provenance | Config | | test.cpp:8:8:8:14 | 0 | test.cpp:9:28:9:29 | v2 | provenance | | | test.cpp:10:8:10:17 | new | test.cpp:11:28:11:29 | v2 | provenance | | | test.cpp:10:8:10:17 | new | test.cpp:12:28:12:29 | v2 | provenance | | From 9ca0d42a6e32a395dccff48fb1eb16476ccac1ce Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 3 Jun 2024 16:51:30 +0100 Subject: [PATCH 018/370] A3-1-5: Remove invalid interpretation of rule As per: https://forum.misra.org.uk/archive/index.php?thread-1588.html --- ...teFunctionDefinedOutsideClassDefinition.ql | 51 ------------------- ...tionDefinedOutsideClassDefinition.expected | 7 --- ...unctionDefinedOutsideClassDefinition.qlref | 1 - 3 files changed, 59 deletions(-) delete mode 100644 cpp/autosar/src/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.ql delete mode 100644 cpp/autosar/test/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.expected delete mode 100644 cpp/autosar/test/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.qlref diff --git a/cpp/autosar/src/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.ql b/cpp/autosar/src/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.ql deleted file mode 100644 index 920875ca3b..0000000000 --- a/cpp/autosar/src/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.ql +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @id cpp/autosar/trivial-or-template-function-defined-outside-class-definition - * @name A3-1-5: A function shall be defined with a class body if and only if it is intended to be inlined - * @description A function that is either trivial, a template function, or a member of a template - * class may not be defined outside of a class body. - * @kind problem - * @precision very-high - * @problem.severity recommendation - * @tags external/autosar/id/a3-1-5 - * external/autosar/allocated-target/design - * external/autosar/enforcement/partially-automated - * external/autosar/obligation/required - */ - -import cpp -import codingstandards.cpp.autosar -import codingstandards.cpp.Class - -/* - * Find instances of `MemberFunction` where the `MemberFunction` is trivial - * and it is not inlined within the class. - */ - -from MemberFunction mf, string kind -where - not isExcluded(mf, ClassesPackage::trivialOrTemplateFunctionDefinedOutsideClassDefinitionQuery()) and - // The member function `mf` is not defined in the class body. - exists(FunctionDeclarationEntry fde | - fde = mf.getClassBodyDeclarationEntry() and not fde.isDefinition() - ) and - //ignore destructors - not mf instanceof Destructor and - // Report functions that are NOT defined in the class body if they are either trivial or - // either a template member or part of a template class (i.e., they should - // be defined in the class body) - ( - if - mf instanceof TemplateOrTemplateClassMemberFunction and - mf instanceof TrivialMemberFunction - then kind = "template" - else - if mf instanceof TrivialMemberFunction - then kind = "trivial" - else - if mf instanceof TemplateOrTemplateClassMemberFunction - then kind = "template" - else none() - ) -select mf, - "The " + kind + " member function " + mf.getName() + " is not defined in the class body of $@.", - mf.getDeclaringType(), mf.getDeclaringType().getName() diff --git a/cpp/autosar/test/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.expected b/cpp/autosar/test/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.expected deleted file mode 100644 index af8a1d4588..0000000000 --- a/cpp/autosar/test/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.expected +++ /dev/null @@ -1,7 +0,0 @@ -| test.cpp:58:5:58:11 | getB | The trivial member function getB is not defined in the class body of $@. | test.cpp:2:7:2:7 | A | A | -| test.cpp:60:25:60:28 | d | The template member function d is not defined in the class body of $@. | test.cpp:2:7:2:7 | A | A | -| test.cpp:62:5:62:8 | b | The trivial member function b is not defined in the class body of $@. | test.cpp:2:7:2:7 | A | A | -| test.cpp:81:34:81:57 | complexCalculation | The template member function complexCalculation is not defined in the class body of $@. | test.cpp:64:29:64:29 | B | B | -| test.cpp:97:47:97:53 | d | The template member function d is not defined in the class body of $@. | test.cpp:64:29:64:29 | B | B | -| test.cpp:101:27:101:33 | b | The template member function b is not defined in the class body of $@. | test.cpp:64:29:64:29 | B | B | -| test.cpp:106:27:106:36 | getB | The template member function getB is not defined in the class body of $@. | test.cpp:64:29:64:29 | B | B | diff --git a/cpp/autosar/test/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.qlref b/cpp/autosar/test/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.qlref deleted file mode 100644 index c644147bb4..0000000000 --- a/cpp/autosar/test/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.ql \ No newline at end of file From f1024ae1ca5109f925e9ab7d78e0dd6b8e4c540a Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 3 Jun 2024 17:10:34 +0100 Subject: [PATCH 019/370] A3-1-5: Exclude member functions in template instantiations --- cpp/autosar/test/rules/A3-1-5/test.cpp | 59 +++++++++++++++++--- cpp/common/src/codingstandards/cpp/Class.qll | 5 +- 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/cpp/autosar/test/rules/A3-1-5/test.cpp b/cpp/autosar/test/rules/A3-1-5/test.cpp index eb5bc9edb7..62edb8f582 100644 --- a/cpp/autosar/test/rules/A3-1-5/test.cpp +++ b/cpp/autosar/test/rules/A3-1-5/test.cpp @@ -23,7 +23,7 @@ class A { int complexCalculation(); - int gcd(int a, int b) { + int gcd(int a, int b) { // NON_COMPLIANT if (b == 0) return a; int result = gcd(b, (a % b)); @@ -55,11 +55,11 @@ inline int A::complexCalculation() { // COMPLIANT return 1; } -int A::getB() { return 1; } // NON_COMPLIANT +int A::getB() { return 1; } // COMPLIANT -template T A::d(T t) { return t; } // NON_COMPLIANT +template T A::d(T t) { return t; } // COMPLIANT -int A::b() { return 3; } // NON_COMPLIANT +int A::b() { return 3; } // COMPLIANT template class B { public: @@ -76,9 +76,30 @@ template class B { template T d(T t); int complexCalculation(); + + int complexCalculation2() { // COMPLIANT - template + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + return 1; + } }; -template inline int B::complexCalculation() { // NON_COMPLIANT +void test_B() { + B b; + b.complexCalculation2(); +} + +template inline int B::complexCalculation() { // COMPLIANT ; ; ; @@ -94,16 +115,16 @@ template inline int B::complexCalculation() { // NON_COMPLIANT return 1; } -template template T B::d(T t) { // NON_COMPLIANT +template template T B::d(T t) { // COMPLIANT return t; } -template int B::b() { // NON_COMPLIANT +template int B::b() { // COMPLIANT C c; return 3; } -template int B::getB() { return 3; } // NON_COMPLIANT +template int B::getB() { return 3; } // COMPLIANT template class Foo { public: @@ -121,8 +142,30 @@ class FooBar { public: ~FooBar(); int f1(int a, int b); + + template int complexCalculation() { // COMPLIANT - template + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + return 1; + } }; +void test_FooBar() { + FooBar foobar; + foobar.complexCalculation(); +} + + FooBar::~FooBar() {} // COMPLIANT want to ignore pImpl uses of destructors int FooBar::f1(int a, int b) { // COMPLIANT not a trivial function diff --git a/cpp/common/src/codingstandards/cpp/Class.qll b/cpp/common/src/codingstandards/cpp/Class.qll index 19bec9fa5f..09d39ce6f8 100644 --- a/cpp/common/src/codingstandards/cpp/Class.qll +++ b/cpp/common/src/codingstandards/cpp/Class.qll @@ -192,7 +192,10 @@ class TrivialMemberFunction extends IntrospectedMemberFunction { * class. */ class TemplateOrTemplateClassMemberFunction extends MemberFunction { - TemplateOrTemplateClassMemberFunction() { isFromUninstantiatedTemplate(_) } + TemplateOrTemplateClassMemberFunction() { + isFromUninstantiatedTemplate(_) or + isFromTemplateInstantiation(_) + } } /** From 8078f8167744651ef4db0d2e795126a7ede83093 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 19 Jun 2024 09:42:28 +0200 Subject: [PATCH 020/370] Accept new warning format in ql tests --- ...bleLengthArraySizeNotInValidRange.expected | 4 +- ...rithmeticOnNonArrayObjectPointers.expected | 10 ++-- ...rSubtractAScaledIntegerToAPointer.expected | 8 ++-- .../CleanUpThreadSpecificStorage.expected | 12 ++--- ...riateThreadObjectStorageDurations.expected | 16 +++---- ...ectStorageDurationsNotInitialized.expected | 10 ++-- ...ateStorageDurationsFunctionReturn.expected | 10 ++-- .../ERR30-C/ErrnoReadBeforeReturn.expected | 2 +- .../ERR30-C/SetlocaleMightSetErrno.expected | 2 +- ...tRelyOnIndeterminateValuesOfErrno.expected | 8 ++-- ...ectAndHandleStandardLibraryErrors.expected | 2 +- ...OfFunctionArgumentsForSideEffects.expected | 48 +++++++++---------- ...rToMoreStrictlyAlignedPointerType.expected | 20 ++++---- ...nctionPointerWithIncompatibleType.expected | 8 ++-- ...iableViaPointerOfIncompatibleType.expected | 14 +++--- .../DoNotModifyConstantObjects.expected | 8 ++-- ...edPointerToRestrictQualifiedParam.expected | 24 +++++----- ...ointerReferencesOverlappingObject.expected | 14 +++--- ...esetStringsOnFgetsOrFgetwsFailure.expected | 6 +-- ...FsetposThatAreReturnedFromFgetpos.expected | 10 ++-- ...RaceConditionsWhileAccessingFiles.expected | 2 +- ...ufficientMemoryAllocatedForObject.expected | 4 +- ...odifyAlignmentOfMemoryWithRealloc.expected | 10 ++-- ...ssInvalidDataToTheAsctimeFunction.expected | 8 ++-- ...VaListThatHasAnIndeterminateValue.expected | 14 +++--- ...SafeFunctionsWithinSignalHandlers.expected | 6 +-- ...romAComputationalExceptionHandler.expected | 2 +- ...oNotAttemptToModifyStringLiterals.expected | 30 ++++++------ ...fficientSpaceForTheNullTerminator.expected | 12 ++--- ...natedToFunctionThatExpectsAString.expected | 20 ++++---- ...yFunctionArgumentNumberOfElements.expected | 12 ++--- ...sedToCompareNullTerminatedStrings.expected | 8 ++-- ...ForReadAndWriteOnDifferentStreams.expected | 2 +- .../AttemptToWriteToAReadOnlyStream.expected | 12 ++--- ...omparedWithUnmodifiedReturnValues.expected | 16 +++---- ...rformConversionOfPassedParameters.expected | 6 +-- .../AssignmentOperatorReturnThis.expected | 2 +- .../ThrownExceptionsShouldBeUnique.expected | 2 +- ...orErrorLeavesObjectInInvalidState.expected | 18 +++---- ...entOfAnArrayPassedToASmartPointer.expected | 14 +++--- .../UnnecessaryUseOfDynamicStorage.expected | 8 ++-- ...ArgumentToForwardSubsequentlyUsed.expected | 6 +-- ...PointerUsedWithNoOwnershipSharing.expected | 2 +- .../rules/A27-0-4/CStyleStringsUsed.expected | 6 +-- ...UsedWithPointersToNonFinalClasses.expected | 8 ++-- .../A5-1-7/LambdaPassedToDecltype.expected | 12 ++--- .../A5-1-7/LambdaPassedToTypeid.expected | 8 ++-- .../A7-5-1/InvalidFunctionReturnType.expected | 6 +-- ...ParameterWithoutLifetimeSemantics.expected | 4 +- ...edToFunctionWithImproperSemantics.expected | 4 +- ...tParametersDeclaredAsTNotModified.expected | 4 +- ...eferencesToPrivateOrProtectedData.expected | 6 +-- ...tionErroneousReturnValueNotTested.expected | 6 +-- ...ntationsOfFloatingPointValuesUsed.expected | 6 +-- ...berFunctionReturnsNonConstPointer.expected | 4 +- ...cCppLibraryFunctionsDoNotOverflow.expected | 18 +++---- .../CTR53-CPP/UseValidIteratorRanges.expected | 12 ++--- ...UseAnAdditiveOperatorOnAnIterator.expected | 18 +++---- ...terArithmeticOnPolymorphicObjects.expected | 8 ++-- ...nFunctionCallsAsFunctionArguments.expected | 48 +++++++++---------- ...ThroughAPointerOfTheIncorrectType.expected | 8 ++-- ...ctAndHandleMemoryAllocationErrors.expected | 14 +++--- .../BadlySeededRandomNumberGenerator.expected | 2 +- 63 files changed, 327 insertions(+), 327 deletions(-) diff --git a/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected b/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected index bcb1c8eddd..083e7dfb87 100644 --- a/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected +++ b/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected @@ -1,5 +1,5 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:104,11-19) -WARNING: Module TaintTracking has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:87,5-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:104,11-19) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:87,5-18) | test.c:14:8:14:8 | VLA declaration | Variable-length array dimension size may be in an invalid range. | | test.c:15:8:15:8 | VLA declaration | Variable-length array dimension size may be in an invalid range. | | test.c:16:8:16:8 | VLA declaration | Variable-length array dimension size may be in an invalid range. | diff --git a/c/cert/test/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.expected b/c/cert/test/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.expected index d75db521af..ca4ef2a7a0 100644 --- a/c/cert/test/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.expected +++ b/c/cert/test/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.expected @@ -1,8 +1,8 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:23,60-68) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:24,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:36,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:44,26-34) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:65,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:23,60-68) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:24,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:36,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:44,26-34) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:65,3-11) edges | test.c:14:38:14:39 | p1 | test.c:18:10:18:11 | v1 | provenance | | | test.c:14:38:14:39 | p1 | test.c:19:10:19:11 | v2 | provenance | | diff --git a/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.expected b/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.expected index 7782984e5b..d343811aaf 100644 --- a/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.expected +++ b/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.expected @@ -1,7 +1,7 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:72,56-64) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:73,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:75,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:84,45-53) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:72,56-64) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:73,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:75,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:84,45-53) edges | test.c:7:13:7:14 | p1 | test.c:9:9:9:10 | p1 | provenance | | | test.c:16:19:16:41 | ... - ... | test.c:18:26:18:31 | offset | provenance | | diff --git a/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected b/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected index 9b1288d578..2706474f29 100644 --- a/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected +++ b/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected @@ -1,9 +1,9 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:21,46-54) -WARNING: Module DataFlow has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:22,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:31,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:41,35-43) -WARNING: Module DataFlow has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:49,36-44) -WARNING: Module DataFlow has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:51,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:21,46-54) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:22,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:31,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:41,35-43) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:49,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:51,36-44) | test.c:27:3:27:12 | call to tss_create | Resources used by thread specific storage may not be cleaned up. | | test.c:49:3:49:12 | call to tss_create | Resources used by thread specific storage may not be cleaned up. | | test.c:71:3:71:12 | call to tss_create | Resources used by thread specific storage may not be cleaned up. | diff --git a/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected b/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected index a513b55b73..25cb74d7fa 100644 --- a/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected +++ b/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected @@ -1,11 +1,11 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:28,29-37) -WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:28,54-62) -WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:35,62-70) -WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:40,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:40,30-38) -WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:41,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:41,30-38) -WARNING: Module TaintTracking has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:28,3-16) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:28,29-37) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:28,54-62) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:35,62-70) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:40,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:40,30-38) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:41,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:41,30-38) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:28,3-16) | test.c:23:3:23:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:23:24:23:29 | & ... | Shared object | | test.c:74:3:74:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:74:24:74:24 | p | Shared object | | test.c:85:3:85:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:85:24:85:24 | p | Shared object | diff --git a/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected b/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected index 337df4c14c..d6b6548581 100644 --- a/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected +++ b/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected @@ -1,6 +1,6 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:28,38-46) -WARNING: Module DataFlow has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:31,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:31,30-38) -WARNING: Module DataFlow has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:32,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:32,30-38) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:28,38-46) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:31,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:31,30-38) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:32,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:32,30-38) | test.c:14:7:14:13 | call to tss_get | Call to a thread specific storage function from within a threaded context on an object that may not be owned by this thread. | diff --git a/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected b/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected index 18d28b61bc..905c9cc22b 100644 --- a/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected +++ b/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected @@ -1,7 +1,7 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:22,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:26,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:39,6-14) -WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:39,26-34) -WARNING: Module DataFlow has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:45,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:22,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:26,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:39,6-14) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:39,26-34) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:45,3-11) | test.c:3:10:3:10 | a | $@ with automatic storage may be accessible outside of its lifetime. | test.c:3:10:3:10 | a | a | | test.c:15:4:15:8 | param [inner post update] | $@ with automatic storage may be accessible outside of its lifetime. | test.c:15:12:15:13 | a2 | a2 | diff --git a/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected b/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected index b3e5c4b7fc..659a731d7c 100644 --- a/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected +++ b/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected @@ -1,4 +1,4 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (ErrnoReadBeforeReturn.ql:40,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ErrnoReadBeforeReturn.ql:40,7-15) | test.c:69:7:69:11 | * ... | Do not read `errno` before checking the return value of function $@. | test.c:68:3:68:7 | call to ftell | call to ftell | | test.c:69:7:69:11 | call to __errno_location | Do not read `errno` before checking the return value of function $@. | test.c:68:3:68:7 | call to ftell | call to ftell | | test.c:70:5:70:10 | call to perror | Do not read `errno` before checking the return value of function $@. | test.c:68:3:68:7 | call to ftell | call to ftell | diff --git a/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected b/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected index 0ffaf56bd1..d20f4a4e34 100644 --- a/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected +++ b/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected @@ -1,3 +1,3 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (SetlocaleMightSetErrno.ql:64,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (SetlocaleMightSetErrno.ql:64,7-15) | test.c:98:3:98:11 | call to setlocale | Do not read `errno` before checking the return value of a call to `setlocale`. | | test.c:104:7:104:15 | call to setlocale | The value of `errno` may be different than `0` when `setlocale` is called. The following `errno` check might be invalid. | diff --git a/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected b/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected index 77fa7b7ba7..a90dd6b7f5 100644 --- a/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected +++ b/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected @@ -1,7 +1,7 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:50,7-15) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:50,27-35) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:51,9-17) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:54,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:50,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:50,27-35) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:51,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:54,9-17) | test.c:12:5:12:10 | call to perror | `errno` has indeterminate value after this $@. | test.c:10:21:10:26 | call to signal | call to signal | | test.c:30:5:30:10 | call to perror | `errno` has indeterminate value after this $@. | test.c:26:21:26:26 | call to signal | call to signal | | test.c:49:5:49:10 | call to perror | `errno` has indeterminate value after this $@. | test.c:45:21:45:26 | call to signal | call to signal | diff --git a/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected b/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected index a32a03a3b9..030596976e 100644 --- a/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected +++ b/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected @@ -1,4 +1,4 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleStandardLibraryErrors.ql:453,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleStandardLibraryErrors.ql:453,5-13) | test.c:18:3:18:11 | call to setlocale | Missing error detection for the call to function `setlocale`. | | test.c:24:23:24:31 | call to setlocale | Missing error detection for the call to function `setlocale`. | | test.c:29:22:29:27 | call to calloc | Missing error detection for the call to function `calloc`. | diff --git a/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected b/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected index 6ea3499517..6567ef6fd1 100644 --- a/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected +++ b/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected @@ -1,25 +1,25 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:24,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:24,59-67) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:27,33-41) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:27,57-65) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:31,33-41) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:31,59-67) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:40,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:40,25-33) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:40,53-61) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:43,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:43,57-65) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:52,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:52,55-63) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:59,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:59,57-65) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:71,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:71,55-63) -WARNING: Module TaintTracking has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:24,5-18) -WARNING: Module TaintTracking has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:27,7-20) -WARNING: Module TaintTracking has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:31,7-20) -WARNING: Module TaintTracking has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:43,5-18) -WARNING: Module TaintTracking has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:52,5-18) -WARNING: Module TaintTracking has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:59,5-18) -WARNING: Module TaintTracking has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:71,5-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:24,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:24,59-67) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:27,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:27,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:31,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:31,59-67) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:40,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:40,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:40,53-61) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:43,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:43,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:52,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:52,55-63) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:59,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:59,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:71,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:71,55-63) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:24,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:27,7-20) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:31,7-20) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:43,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:52,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:59,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:71,5-18) | test.c:20:3:20:4 | call to f1 | Depending on the order of evaluation for the arguments $@ and $@ for side effects on shared state is unspecified and can result in unexpected behavior. | test.c:20:6:20:7 | call to f2 | call to f2 | test.c:20:12:20:13 | call to f3 | call to f3 | diff --git a/c/cert/test/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.expected b/c/cert/test/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.expected index b6f96f6ea5..eed9fb4585 100644 --- a/c/cert/test/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.expected +++ b/c/cert/test/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.expected @@ -1,13 +1,13 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:98,86-94) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:120,3-11) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:122,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:127,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:133,3-11) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:139,55-63) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:140,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:142,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:149,26-34) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:164,44-52) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:98,86-94) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:120,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:122,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:127,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:133,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:139,55-63) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:140,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:142,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:149,26-34) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:164,44-52) edges | test.c:75:14:75:16 | & ... | test.c:76:11:76:12 | v1 | provenance | | | test.c:75:14:75:16 | & ... | test.c:77:12:77:13 | v1 | provenance | | diff --git a/c/cert/test/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.expected b/c/cert/test/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.expected index 1b6505f472..229bd74165 100644 --- a/c/cert/test/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.expected +++ b/c/cert/test/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.expected @@ -1,7 +1,7 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:40,54-62) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:41,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:45,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:50,43-51) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:40,54-62) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:41,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:45,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:50,43-51) edges | test.c:48:68:48:70 | fns [f1] | test.c:49:3:49:5 | fns [f1] | provenance | | | test.c:49:3:49:5 | fns [f1] | test.c:49:8:49:9 | f1 | provenance | | diff --git a/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected b/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected index 6cf822fa15..9f0880455f 100644 --- a/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected +++ b/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected @@ -1,10 +1,10 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:61,38-46) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:64,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:69,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:102,23-31) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:111,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:111,45-53) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:133,27-35) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:61,38-46) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:64,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:69,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:102,23-31) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:111,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:111,45-53) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:133,27-35) edges | test.c:49:8:49:9 | s3 | test.c:50:8:50:9 | s1 | provenance | | | test.c:60:16:60:18 | E1A | test.c:61:16:61:17 | e1 | provenance | | diff --git a/c/cert/test/rules/EXP40-C/DoNotModifyConstantObjects.expected b/c/cert/test/rules/EXP40-C/DoNotModifyConstantObjects.expected index e7af404ec1..6dd4ec261a 100644 --- a/c/cert/test/rules/EXP40-C/DoNotModifyConstantObjects.expected +++ b/c/cert/test/rules/EXP40-C/DoNotModifyConstantObjects.expected @@ -1,7 +1,7 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:35,30-38) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:36,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:42,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:47,19-27) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:35,30-38) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:36,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:42,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:47,19-27) edges | test.c:5:8:5:9 | & ... | test.c:6:4:6:5 | aa | provenance | | | test.c:26:15:26:15 | a | test.c:27:4:27:4 | a | provenance | | diff --git a/c/cert/test/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.expected b/c/cert/test/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.expected index a77a92ee81..1c8a649094 100644 --- a/c/cert/test/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.expected +++ b/c/cert/test/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.expected @@ -1,15 +1,15 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:103,36-44) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:118,51-59) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:119,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:121,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:127,25-33) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:132,40-48) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:146,41-49) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:147,7-15) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:150,43-51) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:151,9-17) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:158,43-51) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:159,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:103,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:118,51-59) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:119,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:121,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:127,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:132,40-48) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:146,41-49) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:147,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:150,43-51) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:151,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:158,43-51) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:159,9-17) | test.c:59:3:59:6 | call to copy | Call to 'copy' passes an $@ to a $@ (pointer value derived from a pair of address-of expressions ($@, $@). | test.c:59:13:59:15 | & ... | aliased pointer | test.c:59:8:59:10 | & ... | restrict-qualified parameter | test.c:59:8:59:10 | & ... | addressof1 | test.c:59:13:59:15 | & ... | addressof2 | | test.c:65:3:65:6 | call to copy | Call to 'copy' passes an $@ to a $@ (pointer value derived from a pair of address-of expressions ($@, $@). | test.c:65:15:65:19 | & ... | aliased pointer | test.c:65:8:65:12 | & ... | restrict-qualified parameter | test.c:65:8:65:12 | & ... | addressof1 | test.c:65:15:65:19 | & ... | addressof2 | | test.c:67:3:67:6 | call to copy | Call to 'copy' passes an $@ to a $@ (pointer value derived from a pair of address-of expressions ($@, $@). | test.c:67:15:67:16 | px | aliased pointer | test.c:67:8:67:12 | & ... | restrict-qualified parameter | test.c:67:8:67:12 | & ... | addressof1 | test.c:63:13:63:17 | & ... | addressof2 | diff --git a/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected b/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected index 591e17661a..b9765e77fb 100644 --- a/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected +++ b/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected @@ -1,10 +1,10 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:42,57-65) -WARNING: Module DataFlow has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:43,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:47,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:53,3-11) -WARNING: Module DataFlow has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:56,58-66) -WARNING: Module DataFlow has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:72,64-72) -WARNING: Module DataFlow has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:73,64-72) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:42,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:43,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:47,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:53,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:56,58-66) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:72,64-72) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:73,64-72) | test.c:18:22:18:23 | i2 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:18:17:18:18 | i3 | i3 | test.c:18:22:18:23 | i2 | the object pointed to by i2 | | test.c:19:8:19:9 | g2 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:5:15:5:16 | g1 | g1 | test.c:19:8:19:9 | g2 | the object pointed to by g2 | | test.c:20:8:20:9 | i2 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:16:17:16:18 | i1 | i1 | test.c:20:8:20:9 | i2 | the object pointed to by i2 | diff --git a/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected b/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected index 6a73ee98a7..669dd829c8 100644 --- a/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected +++ b/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected @@ -1,6 +1,6 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:42,11-19) -WARNING: Module DataFlow has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:42,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:43,13-21) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:42,11-19) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:42,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:43,13-21) | test.c:20:10:20:12 | buf | The buffer is not reset before being referenced following a failed $@. | test.c:15:7:15:11 | call to fgets | call to fgets | | test.c:57:10:57:12 | buf | The buffer is not reset before being referenced following a failed $@. | test.c:52:7:52:11 | call to fgets | call to fgets | | test.c:66:18:66:20 | buf | The buffer is not reset before being referenced following a failed $@. | test.c:61:7:61:11 | call to fgets | call to fgets | diff --git a/c/cert/test/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.expected b/c/cert/test/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.expected index 637918f241..5bff6016e4 100644 --- a/c/cert/test/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.expected +++ b/c/cert/test/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.expected @@ -1,7 +1,7 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:25,32-40) -WARNING: Module DataFlow has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:26,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:28,14-22) -WARNING: Module DataFlow has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:31,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:37,21-29) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:25,32-40) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:26,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:28,14-22) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:31,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:37,21-29) | test.c:7:24:7:30 | & ... | The position argument of a call to `fsetpos()` should be obtained from a call to `fgetpos()`. | | test.c:33:24:33:30 | & ... | The position argument of a call to `fsetpos()` should be obtained from a call to `fgetpos()`. | diff --git a/c/cert/test/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.expected b/c/cert/test/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.expected index f294ce05b7..71df14e907 100644 --- a/c/cert/test/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.expected +++ b/c/cert/test/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.expected @@ -1,3 +1,3 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (ToctouRaceConditionsWhileAccessingFiles.ql:27,35-43) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ToctouRaceConditionsWhileAccessingFiles.ql:27,35-43) | test.c:4:13:4:17 | call to fopen | This call is trying to prevent an existing file from being overwritten by $@. An attacker might be able to exploit the race window between the two calls. | test.c:11:9:11:13 | call to fopen | another call | | test.c:88:13:88:17 | call to fopen | This call is trying to prevent an existing file from being overwritten by $@. An attacker might be able to exploit the race window between the two calls. | test.c:95:9:95:13 | call to fopen | another call | diff --git a/c/cert/test/rules/MEM35-C/InsufficientMemoryAllocatedForObject.expected b/c/cert/test/rules/MEM35-C/InsufficientMemoryAllocatedForObject.expected index 73dd6ba1e0..6bfbbefc14 100644 --- a/c/cert/test/rules/MEM35-C/InsufficientMemoryAllocatedForObject.expected +++ b/c/cert/test/rules/MEM35-C/InsufficientMemoryAllocatedForObject.expected @@ -1,5 +1,5 @@ -WARNING: Module TaintTracking has been deprecated and may be removed in future (InsufficientMemoryAllocatedForObject.ql:85,5-18) -WARNING: Module TaintTracking has been deprecated and may be removed in future (InsufficientMemoryAllocatedForObject.ql:143,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (InsufficientMemoryAllocatedForObject.ql:85,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (InsufficientMemoryAllocatedForObject.ql:143,5-18) | test.c:12:19:12:24 | call to malloc | Allocation size (32 bytes) is not a multiple of the size of 'S1' (36 bytes). | test.c:12:26:12:32 | 32 | | | test.c:15:19:15:24 | call to malloc | Allocation size calculated from the size of a different type ($@). | test.c:15:26:15:35 | sizeof() | sizeof(S1 *) | | test.c:20:19:20:24 | call to malloc | Allocation size (128 bytes) is not a multiple of the size of 'S1' (36 bytes). | test.c:20:26:20:36 | ... * ... | | diff --git a/c/cert/test/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.expected b/c/cert/test/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.expected index 61c2cfb1f0..2f5889c4c6 100644 --- a/c/cert/test/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.expected +++ b/c/cert/test/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.expected @@ -1,8 +1,8 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:26,36-44) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:40,47-55) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:41,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:45,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:50,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:26,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:40,47-55) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:41,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:45,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:50,36-44) edges | test.c:5:10:5:22 | call to aligned_alloc | test.c:15:8:15:28 | call to aligned_alloc_wrapper | provenance | | | test.c:8:29:8:31 | ptr | test.c:8:64:8:66 | ptr | provenance | | diff --git a/c/cert/test/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.expected b/c/cert/test/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.expected index 713646db10..853d999d4e 100644 --- a/c/cert/test/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.expected +++ b/c/cert/test/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.expected @@ -1,5 +1,5 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:33,38-46) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:34,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:41,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:44,27-35) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:33,38-46) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:34,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:41,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:44,27-35) | test.c:6:24:6:30 | time_tm | The function `asctime` and `asctime_r` should be discouraged. Unsanitized input can overflow the output buffer. | diff --git a/c/cert/test/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.expected b/c/cert/test/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.expected index 4d4a713487..4eaa05b179 100644 --- a/c/cert/test/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.expected +++ b/c/cert/test/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.expected @@ -1,10 +1,10 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:38,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:39,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:44,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:47,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:68,10-18) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:69,29-37) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:70,29-37) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:38,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:39,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:44,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:47,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:68,10-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:69,29-37) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:70,29-37) | test.c:23:32:23:33 | ap | The value of ap is indeterminate after the $@. | test.c:17:7:17:19 | call to contains_zero | call to contains_zero | | test.c:26:10:26:11 | ap | The value of ap is indeterminate after the $@. | test.c:17:7:17:19 | call to contains_zero | call to contains_zero | | test.c:39:12:39:13 | ap | The value of ap is indeterminate after the $@. | test.c:35:7:35:19 | call to contains_zero | call to contains_zero | diff --git a/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected b/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected index a5f4af8c3c..6190259408 100644 --- a/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected +++ b/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected @@ -1,6 +1,6 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:105,11-19) -WARNING: Module DataFlow has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:105,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:106,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:105,11-19) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:105,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:106,9-17) | test.c:10:3:10:18 | call to log_local_unsafe | Asyncronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:16:7:16:12 | call to signal | signal handler | | test.c:11:3:11:6 | call to free | Asyncronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:16:7:16:12 | call to signal | signal handler | | test.c:46:3:46:9 | call to longjmp | Asyncronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:50:7:50:12 | call to signal | signal handler | diff --git a/c/cert/test/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.expected b/c/cert/test/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.expected index d4796c6ede..e861e90e9e 100644 --- a/c/cert/test/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.expected +++ b/c/cert/test/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.expected @@ -1,2 +1,2 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotReturnFromAComputationalExceptionHandler.ql:39,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotReturnFromAComputationalExceptionHandler.ql:39,5-13) | test.c:10:1:10:1 | return ... | Do not return from a $@ signal handler. | test.c:13:10:13:15 | SIGFPE | computational exception | diff --git a/c/cert/test/rules/STR30-C/DoNotAttemptToModifyStringLiterals.expected b/c/cert/test/rules/STR30-C/DoNotAttemptToModifyStringLiterals.expected index 7215fd8603..2a45193a17 100644 --- a/c/cert/test/rules/STR30-C/DoNotAttemptToModifyStringLiterals.expected +++ b/c/cert/test/rules/STR30-C/DoNotAttemptToModifyStringLiterals.expected @@ -1,18 +1,18 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:42,65-73) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:43,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:64,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:77,3-11) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:101,11-19) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:101,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:101,55-63) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:106,11-19) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:106,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:106,57-65) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:139,11-19) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:139,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:139,55-63) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:150,53-61) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:151,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:42,65-73) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:43,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:64,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:77,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:101,11-19) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:101,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:101,55-63) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:106,11-19) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:106,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:106,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:139,11-19) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:139,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:139,55-63) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:150,53-61) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:151,5-13) | test.c:7:3:7:3 | a | This operation may write to a string that may be a string literal that was $@. | test.c:6:13:6:20 | codeql | created here | | test.c:30:3:30:3 | a | This operation may write to a string that may be a string literal that was $@. | test.c:29:13:29:18 | call to strchr | created here | | test.c:36:3:36:3 | b | This operation may write to a string that may be a string literal that was $@. | test.c:35:13:35:18 | call to strchr | created here | diff --git a/c/cert/test/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.expected b/c/cert/test/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.expected index 4c411382f0..9012a2d78a 100644 --- a/c/cert/test/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.expected +++ b/c/cert/test/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.expected @@ -1,9 +1,9 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:57,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:57,55-63) -WARNING: Module DataFlow has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:63,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:63,54-62) -WARNING: Module TaintTracking has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:57,5-18) -WARNING: Module TaintTracking has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:63,5-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:57,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:57,55-63) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:63,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:63,54-62) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:57,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:63,5-18) | test.c:10:20:10:24 | Cod | Expression produces or consumes a string that may not have sufficient space for a null-terminator. | | test.c:16:3:16:9 | call to strncpy | Expression produces or consumes a string that may not have sufficient space for a null-terminator. | | test.c:26:3:26:10 | call to snprintf | Expression produces or consumes a string that may not have sufficient space for a null-terminator. | diff --git a/c/cert/test/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.expected b/c/cert/test/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.expected index e20b708dab..da86e69b88 100644 --- a/c/cert/test/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.expected +++ b/c/cert/test/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.expected @@ -1,13 +1,13 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:64,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:66,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:74,39-47) -WARNING: Module DataFlow has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:75,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:81,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:83,34-42) -WARNING: Module DataFlow has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:83,57-65) -WARNING: Module DataFlow has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:123,3-11) -WARNING: Module DataFlow has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:123,26-34) -WARNING: Module TaintTracking has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:120,17-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:64,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:66,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:74,39-47) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:75,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:81,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:83,34-42) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:83,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:123,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:123,26-34) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:120,17-30) | test.c:20:3:20:8 | call to printf | String modified by $@ is passed to function expecting a null-terminated string. | test.c:8:20:8:24 | Cod | this expression | | test.c:21:3:21:8 | call to printf | String modified by $@ is passed to function expecting a null-terminated string. | test.c:8:20:8:24 | Cod | this expression | | test.c:23:3:23:8 | call to printf | String modified by $@ is passed to function expecting a null-terminated string. | test.c:14:3:14:9 | call to strncpy | this expression | diff --git a/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected b/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected index d9cd037d42..cb4422f5f1 100644 --- a/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected +++ b/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected @@ -1,9 +1,9 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:47,36-44) -WARNING: Module DataFlow has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:48,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:50,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:55,25-33) -WARNING: Module DataFlow has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:71,28-36) -WARNING: Module DataFlow has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:71,51-59) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:47,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:48,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:50,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:55,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:71,28-36) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:71,51-59) | test.c:18:6:18:6 | 0 | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter | | test.c:19:6:19:7 | ar | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter | | test.c:21:6:21:9 | ar2p | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter | diff --git a/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected b/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected index ef6703a285..cf45b21eb4 100644 --- a/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected +++ b/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected @@ -1,7 +1,7 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:22,54-62) -WARNING: Module DataFlow has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:23,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:49,20-28) -WARNING: Module TaintTracking has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:57,43-56) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:22,54-62) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:23,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:49,20-28) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:57,43-56) edges | test.c:12:13:12:15 | a | test.c:14:10:14:10 | a | provenance | | | test.c:12:13:12:15 | a | test.c:23:13:23:13 | a | provenance | | diff --git a/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected b/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected index 3382b66847..6360b21973 100644 --- a/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected +++ b/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected @@ -1,4 +1,4 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (FileOpenForReadAndWriteOnDifferentStreams.ql:38,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (FileOpenForReadAndWriteOnDifferentStreams.ql:38,9-17) | test.c:6:14:6:18 | call to fopen | The same file was already opened $@. Files should not be read and written at the same time using different streams. | test.c:5:14:5:18 | call to fopen | here | | test.c:17:14:17:18 | call to fopen | The same file was already opened $@. Files should not be read and written at the same time using different streams. | test.c:16:14:16:18 | call to fopen | here | | test.c:33:14:33:18 | call to fopen | The same file was already opened $@. Files should not be read and written at the same time using different streams. | test.c:32:14:32:18 | call to fopen | here | diff --git a/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected b/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected index 08363e7dda..88dca316a2 100644 --- a/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected +++ b/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected @@ -1,8 +1,8 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:18,32-40) -WARNING: Module DataFlow has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:19,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:24,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:30,21-29) -WARNING: Module DataFlow has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:32,6-14) -WARNING: Module DataFlow has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:35,28-36) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:18,32-40) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:19,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:24,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:30,21-29) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:32,6-14) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:35,28-36) | test.c:10:3:10:9 | call to fprintf | Attempt to write to a $@ opened as read-only. | test.c:9:14:9:18 | call to fopen | stream | | test.c:15:3:15:9 | call to fprintf | Attempt to write to a $@ opened as read-only. | test.c:18:14:18:18 | call to fopen | stream | diff --git a/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected b/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected index 9e975d34e4..a7ee20c0b0 100644 --- a/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected +++ b/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected @@ -1,10 +1,10 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:22,28-36) -WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:23,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:27,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:36,23-31) -WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:41,17-25) -WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:50,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:58,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:58,46-54) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:22,28-36) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:23,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:27,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:36,23-31) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:41,17-25) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:50,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:58,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:58,46-54) | test.c:6:7:6:20 | ... != ... | The check is not reliable as the type of the return value of $@ is converted. | test.c:5:14:5:20 | call to getchar | call to getchar | | test.c:13:7:13:15 | ... != ... | The check is not reliable as the type of the return value of $@ is converted. | test.c:12:14:12:20 | call to getchar | call to getchar | diff --git a/cpp/autosar/test/rules/A13-1-3/UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.expected b/cpp/autosar/test/rules/A13-1-3/UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.expected index 11b622f271..5d1d6022b5 100644 --- a/cpp/autosar/test/rules/A13-1-3/UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.expected +++ b/cpp/autosar/test/rules/A13-1-3/UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.expected @@ -1,4 +1,4 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.ql:27,33-41) -WARNING: Module DataFlow has been deprecated and may be removed in future (UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.ql:28,5-13) -WARNING: Module TaintTracking has been deprecated and may be removed in future (UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.ql:27,7-20) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.ql:27,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.ql:28,5-13) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (UserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters.ql:27,7-20) | test.cpp:47:8:47:23 | operator ""_uds5 | User defined literal operator returns $@, which is not converted from a passed parameter | test.cpp:48:10:48:12 | 0.0 | expression | diff --git a/cpp/autosar/test/rules/A13-2-1/AssignmentOperatorReturnThis.expected b/cpp/autosar/test/rules/A13-2-1/AssignmentOperatorReturnThis.expected index 4a4697facc..9c0d50ca86 100644 --- a/cpp/autosar/test/rules/A13-2-1/AssignmentOperatorReturnThis.expected +++ b/cpp/autosar/test/rules/A13-2-1/AssignmentOperatorReturnThis.expected @@ -1,4 +1,4 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (AssignmentOperatorReturnThis.ql:25,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AssignmentOperatorReturnThis.ql:25,5-13) | test.cpp:10:12:10:20 | operator= | User-defined assignment operator $@ does not return *this | test.cpp:10:12:10:20 | operator= | user defined assignment operator | | test.cpp:17:11:17:19 | operator= | User-defined assignment operator $@ does not return *this | test.cpp:17:11:17:19 | operator= | user defined assignment operator | | test.cpp:24:12:24:20 | operator= | User-defined assignment operator $@ does not return *this | test.cpp:24:12:24:20 | operator= | user defined assignment operator | diff --git a/cpp/autosar/test/rules/A15-1-3/ThrownExceptionsShouldBeUnique.expected b/cpp/autosar/test/rules/A15-1-3/ThrownExceptionsShouldBeUnique.expected index 92504006b9..5db0f83985 100644 --- a/cpp/autosar/test/rules/A15-1-3/ThrownExceptionsShouldBeUnique.expected +++ b/cpp/autosar/test/rules/A15-1-3/ThrownExceptionsShouldBeUnique.expected @@ -1,4 +1,4 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (ThrownExceptionsShouldBeUnique.ql:24,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThrownExceptionsShouldBeUnique.ql:24,3-11) | test.cpp:6:5:6:26 | throw ... | The $@ thrown here is a possible duplicate of the $@ thrown $@. | test.cpp:6:5:6:26 | call to exception | std::exception exception | test.cpp:14:5:14:26 | call to exception | exception | test.cpp:14:5:14:26 | throw ... | here | | test.cpp:8:5:8:53 | throw ... | The $@ thrown here is a possible duplicate of the $@ thrown $@. | test.cpp:8:5:8:53 | call to runtime_error | std::runtime_error exception | test.cpp:16:5:16:53 | call to runtime_error | exception | test.cpp:16:5:16:53 | throw ... | here | | test.cpp:14:5:14:26 | throw ... | The $@ thrown here is a possible duplicate of the $@ thrown $@. | test.cpp:14:5:14:26 | call to exception | std::exception exception | test.cpp:6:5:6:26 | call to exception | exception | test.cpp:6:5:6:26 | throw ... | here | diff --git a/cpp/autosar/test/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.expected b/cpp/autosar/test/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.expected index 2fd57c3b20..529a7ccf99 100644 --- a/cpp/autosar/test/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.expected +++ b/cpp/autosar/test/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.expected @@ -1,12 +1,12 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:47,12-20) -WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:48,30-38) -WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:48,57-65) -WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:74,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:74,25-33) -WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:75,7-15) -WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:130,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:130,25-33) -WARNING: Module DataFlow has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:130,54-62) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:47,12-20) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:48,30-38) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:48,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:74,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:74,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:75,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:130,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:130,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ConstructorErrorLeavesObjectInInvalidState.ql:130,54-62) edges | test.cpp:12:16:12:27 | new [bad_alloc] | test.cpp:14:33:16:5 | { ... } [bad_alloc] | | test.cpp:13:7:13:28 | throw ... [exception] | test.cpp:14:33:16:5 | { ... } [exception] | diff --git a/cpp/autosar/test/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.expected b/cpp/autosar/test/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.expected index e71e667685..bd46224da6 100644 --- a/cpp/autosar/test/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.expected +++ b/cpp/autosar/test/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.expected @@ -1,10 +1,10 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:26,67-75) -WARNING: Module DataFlow has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:27,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:39,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:50,34-42) -WARNING: Module DataFlow has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:50,57-65) -WARNING: Module DataFlow has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:58,25-33) -WARNING: Module TaintTracking has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:70,3-16) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:26,67-75) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:27,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:39,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:50,34-42) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:50,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:58,25-33) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (PointerToAnElementOfAnArrayPassedToASmartPointer.ql:70,3-16) edges | test.cpp:3:36:3:45 | new[] | test.cpp:19:27:19:44 | call to allocate_int_array | provenance | | | test.cpp:3:36:3:45 | new[] | test.cpp:23:12:23:29 | call to allocate_int_array | provenance | | diff --git a/cpp/autosar/test/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.expected b/cpp/autosar/test/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.expected index cf611ded5b..6ab75d989e 100644 --- a/cpp/autosar/test/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.expected +++ b/cpp/autosar/test/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.expected @@ -1,7 +1,7 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:55,34-42) -WARNING: Module DataFlow has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:57,26-34) -WARNING: Module TaintTracking has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:71,5-18) -WARNING: Module TaintTracking has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:76,41-54) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:55,34-42) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:57,26-34) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:71,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:76,41-54) | test.cpp:17:17:17:29 | new | StructA object of size 8 bytes does not appear to outlive the function, but is created on the heap instead of the stack. | | test.cpp:21:17:21:32 | new[] | StructA[] object of size 800 bytes does not appear to outlive the function, but is created on the heap instead of the stack. | | test.cpp:35:20:35:44 | call to make_shared | StructA object of size 8 bytes does not appear to outlive the function, but is created on the heap instead of the stack. | diff --git a/cpp/autosar/test/rules/A18-9-4/ArgumentToForwardSubsequentlyUsed.expected b/cpp/autosar/test/rules/A18-9-4/ArgumentToForwardSubsequentlyUsed.expected index 2875a68f28..9e1cf41d3d 100644 --- a/cpp/autosar/test/rules/A18-9-4/ArgumentToForwardSubsequentlyUsed.expected +++ b/cpp/autosar/test/rules/A18-9-4/ArgumentToForwardSubsequentlyUsed.expected @@ -1,4 +1,4 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (ArgumentToForwardSubsequentlyUsed.ql:22,10-18) -WARNING: Module DataFlow has been deprecated and may be removed in future (ArgumentToForwardSubsequentlyUsed.ql:24,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (ArgumentToForwardSubsequentlyUsed.ql:24,30-38) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArgumentToForwardSubsequentlyUsed.ql:22,10-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArgumentToForwardSubsequentlyUsed.ql:24,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArgumentToForwardSubsequentlyUsed.ql:24,30-38) | test.cpp:8:5:8:6 | t2 | The argument $@ of `std::forward` may be indeterminate when accessed at this location. | test.cpp:7:45:7:46 | t2 | t2 | diff --git a/cpp/autosar/test/rules/A20-8-4/SharedPointerUsedWithNoOwnershipSharing.expected b/cpp/autosar/test/rules/A20-8-4/SharedPointerUsedWithNoOwnershipSharing.expected index 03406ac254..5b770a1925 100644 --- a/cpp/autosar/test/rules/A20-8-4/SharedPointerUsedWithNoOwnershipSharing.expected +++ b/cpp/autosar/test/rules/A20-8-4/SharedPointerUsedWithNoOwnershipSharing.expected @@ -1,4 +1,4 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (SharedPointerUsedWithNoOwnershipSharing.ql:47,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (SharedPointerUsedWithNoOwnershipSharing.ql:47,7-15) | test.cpp:14:24:14:26 | sp3 | The ownership of shared_ptr $@ is not shared within or passed out of the local scope of function $@. | test.cpp:14:24:14:26 | sp3 | sp3 | test.cpp:11:22:11:23 | f1 | f1 | | test.cpp:16:24:16:26 | sp5 | The ownership of shared_ptr $@ is not shared within or passed out of the local scope of function $@. | test.cpp:16:24:16:26 | sp5 | sp5 | test.cpp:11:22:11:23 | f1 | f1 | | test.cpp:17:24:17:26 | sp6 | The ownership of shared_ptr $@ is not shared within or passed out of the local scope of function $@. | test.cpp:17:24:17:26 | sp6 | sp6 | test.cpp:11:22:11:23 | f1 | f1 | diff --git a/cpp/autosar/test/rules/A27-0-4/CStyleStringsUsed.expected b/cpp/autosar/test/rules/A27-0-4/CStyleStringsUsed.expected index eaaaaac98d..555cb412b8 100644 --- a/cpp/autosar/test/rules/A27-0-4/CStyleStringsUsed.expected +++ b/cpp/autosar/test/rules/A27-0-4/CStyleStringsUsed.expected @@ -1,6 +1,6 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (CStyleStringsUsed.ql:39,3-11) -WARNING: Module DataFlow has been deprecated and may be removed in future (CStyleStringsUsed.ql:39,23-31) -WARNING: Module DataFlow has been deprecated and may be removed in future (CStyleStringsUsed.ql:39,47-55) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CStyleStringsUsed.ql:39,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CStyleStringsUsed.ql:39,23-31) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CStyleStringsUsed.ql:39,47-55) | test.cpp:7:20:7:27 | CodeQL | Usage of C-style string in $@. | test.cpp:7:20:7:27 | CodeQL | expression | | test.cpp:7:20:7:27 | CodeQL | Usage of C-style string in $@. | test.cpp:16:16:16:17 | a1 | expression | | test.cpp:8:22:8:26 | call to c_str | Usage of C-style string in $@. | test.cpp:8:22:8:26 | call to c_str | expression | diff --git a/cpp/autosar/test/rules/A5-0-4/PointerArithmeticUsedWithPointersToNonFinalClasses.expected b/cpp/autosar/test/rules/A5-0-4/PointerArithmeticUsedWithPointersToNonFinalClasses.expected index 9f97a58467..e2b51e5fb9 100644 --- a/cpp/autosar/test/rules/A5-0-4/PointerArithmeticUsedWithPointersToNonFinalClasses.expected +++ b/cpp/autosar/test/rules/A5-0-4/PointerArithmeticUsedWithPointersToNonFinalClasses.expected @@ -1,7 +1,7 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (PointerArithmeticUsedWithPointersToNonFinalClasses.ql:45,62-70) -WARNING: Module DataFlow has been deprecated and may be removed in future (PointerArithmeticUsedWithPointersToNonFinalClasses.ql:46,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (PointerArithmeticUsedWithPointersToNonFinalClasses.ql:55,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (PointerArithmeticUsedWithPointersToNonFinalClasses.ql:61,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (PointerArithmeticUsedWithPointersToNonFinalClasses.ql:45,62-70) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (PointerArithmeticUsedWithPointersToNonFinalClasses.ql:46,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (PointerArithmeticUsedWithPointersToNonFinalClasses.ql:55,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (PointerArithmeticUsedWithPointersToNonFinalClasses.ql:61,3-11) edges | test.cpp:10:18:10:20 | foo | test.cpp:11:23:11:25 | foo | provenance | | | test.cpp:10:18:10:20 | foo | test.cpp:11:50:11:52 | foo | provenance | | diff --git a/cpp/autosar/test/rules/A5-1-7/LambdaPassedToDecltype.expected b/cpp/autosar/test/rules/A5-1-7/LambdaPassedToDecltype.expected index 03eaab82aa..56896d69fd 100644 --- a/cpp/autosar/test/rules/A5-1-7/LambdaPassedToDecltype.expected +++ b/cpp/autosar/test/rules/A5-1-7/LambdaPassedToDecltype.expected @@ -1,7 +1,7 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:20,55-63) -WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:21,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:23,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:28,44-52) -WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:39,47-55) -WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:40,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:20,55-63) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:21,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:23,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:28,44-52) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:39,47-55) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (LambdaPassedToDecltype.ql:40,9-17) | test.cpp:14:23:14:24 | decltype(...) | Lambda $@ passed as operand to decltype. | test.cpp:5:13:5:30 | [...](...){...} | expression | diff --git a/cpp/autosar/test/rules/A5-1-7/LambdaPassedToTypeid.expected b/cpp/autosar/test/rules/A5-1-7/LambdaPassedToTypeid.expected index 916b9db113..8f86a87616 100644 --- a/cpp/autosar/test/rules/A5-1-7/LambdaPassedToTypeid.expected +++ b/cpp/autosar/test/rules/A5-1-7/LambdaPassedToTypeid.expected @@ -1,7 +1,7 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToTypeid.ql:21,50-58) -WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToTypeid.ql:22,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToTypeid.ql:24,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (LambdaPassedToTypeid.ql:27,39-47) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (LambdaPassedToTypeid.ql:21,50-58) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (LambdaPassedToTypeid.ql:22,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (LambdaPassedToTypeid.ql:24,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (LambdaPassedToTypeid.ql:27,39-47) edges | test.cpp:5:13:5:30 | [...](...){...} | test.cpp:8:38:8:39 | l1 | provenance | | | test.cpp:6:13:6:30 | [...](...){...} | test.cpp:9:38:9:39 | l2 | provenance | | diff --git a/cpp/autosar/test/rules/A7-5-1/InvalidFunctionReturnType.expected b/cpp/autosar/test/rules/A7-5-1/InvalidFunctionReturnType.expected index 0ab837454a..3287ba88d1 100644 --- a/cpp/autosar/test/rules/A7-5-1/InvalidFunctionReturnType.expected +++ b/cpp/autosar/test/rules/A7-5-1/InvalidFunctionReturnType.expected @@ -1,5 +1,5 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (InvalidFunctionReturnType.ql:27,3-11) -WARNING: Module DataFlow has been deprecated and may be removed in future (InvalidFunctionReturnType.ql:27,23-31) -WARNING: Module DataFlow has been deprecated and may be removed in future (InvalidFunctionReturnType.ql:27,51-59) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (InvalidFunctionReturnType.ql:27,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (InvalidFunctionReturnType.ql:27,23-31) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (InvalidFunctionReturnType.ql:27,51-59) | test.cpp:5:3:5:11 | return ... | Function test_refconst_return returns a reference or a pointer to $@ that is passed by reference to const. | test.cpp:4:44:4:44 | x | parameter | | test.cpp:8:3:8:14 | return ... | Function test_ptrconst_return returns a reference or a pointer to $@ that is passed by reference to const. | test.cpp:7:44:7:44 | x | parameter | diff --git a/cpp/autosar/test/rules/A8-4-11/SmartPointerAsParameterWithoutLifetimeSemantics.expected b/cpp/autosar/test/rules/A8-4-11/SmartPointerAsParameterWithoutLifetimeSemantics.expected index be4a4107fd..2ce56fdce9 100644 --- a/cpp/autosar/test/rules/A8-4-11/SmartPointerAsParameterWithoutLifetimeSemantics.expected +++ b/cpp/autosar/test/rules/A8-4-11/SmartPointerAsParameterWithoutLifetimeSemantics.expected @@ -1,5 +1,5 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (SmartPointerAsParameterWithoutLifetimeSemantics.ql:47,3-11) -WARNING: Module DataFlow has been deprecated and may be removed in future (SmartPointerAsParameterWithoutLifetimeSemantics.ql:56,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (SmartPointerAsParameterWithoutLifetimeSemantics.ql:47,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (SmartPointerAsParameterWithoutLifetimeSemantics.ql:56,5-13) | test.cpp:7:41:7:43 | up1 | Function $@ takes smart pointer parameter 'up1' but does not implement any lifetime-affecting operations. | test.cpp:7:6:7:18 | smart_ptr_get | smart_ptr_get | | test.cpp:16:53:16:55 | sp1 | Function $@ takes smart pointer parameter 'sp1' but does not implement any lifetime-affecting operations. | test.cpp:16:6:16:29 | smart_ptr_ref_assign_ref | smart_ptr_ref_assign_ref | | test.cpp:28:55:28:57 | sp1 | Function $@ takes smart pointer parameter 'sp1' but does not implement any lifetime-affecting operations. | test.cpp:28:6:28:31 | smart_ptr_ref_noncompliant | smart_ptr_ref_noncompliant | diff --git a/cpp/autosar/test/rules/A8-4-12/UniquePtrPassedToFunctionWithImproperSemantics.expected b/cpp/autosar/test/rules/A8-4-12/UniquePtrPassedToFunctionWithImproperSemantics.expected index b2273e66f3..0a8ead4af8 100644 --- a/cpp/autosar/test/rules/A8-4-12/UniquePtrPassedToFunctionWithImproperSemantics.expected +++ b/cpp/autosar/test/rules/A8-4-12/UniquePtrPassedToFunctionWithImproperSemantics.expected @@ -1,5 +1,5 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (UniquePtrPassedToFunctionWithImproperSemantics.ql:41,3-11) -WARNING: Module DataFlow has been deprecated and may be removed in future (UniquePtrPassedToFunctionWithImproperSemantics.ql:51,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UniquePtrPassedToFunctionWithImproperSemantics.ql:41,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UniquePtrPassedToFunctionWithImproperSemantics.ql:51,5-13) | test.cpp:13:55:13:56 | v1 | Parameter of type std::unique_ptr passed as lvalue reference but not used to modify underlying object. | | test.cpp:17:47:17:48 | v1 | Parameter of type std::unique_ptr passed as lvalue reference but not used to modify underlying object. | | test.cpp:22:27:22:28 | v1 | Parameter of type std::unique_ptr passed as lvalue reference but not used to modify underlying object. | diff --git a/cpp/autosar/test/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.expected b/cpp/autosar/test/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.expected index 15e513c639..bafa98112f 100644 --- a/cpp/autosar/test/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.expected +++ b/cpp/autosar/test/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.expected @@ -1,5 +1,5 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (InOutParametersDeclaredAsTNotModified.ql:49,7-15) -WARNING: Module DataFlow has been deprecated and may be removed in future (InOutParametersDeclaredAsTNotModified.ql:63,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (InOutParametersDeclaredAsTNotModified.ql:49,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (InOutParametersDeclaredAsTNotModified.ql:63,7-15) | test.cpp:4:13:4:13 | i | In-out parameter i that is not written to. | | test.cpp:7:22:7:24 | str | In-out parameter str that is not read from. | | test.cpp:18:14:18:14 | i | In-out parameter i that is not read from. | diff --git a/cpp/autosar/test/rules/A9-3-1/ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.expected b/cpp/autosar/test/rules/A9-3-1/ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.expected index 84d7f2d7f0..70892c12c8 100644 --- a/cpp/autosar/test/rules/A9-3-1/ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.expected +++ b/cpp/autosar/test/rules/A9-3-1/ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.expected @@ -1,6 +1,6 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.ql:73,3-11) -WARNING: Module DataFlow has been deprecated and may be removed in future (ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.ql:73,23-31) -WARNING: Module DataFlow has been deprecated and may be removed in future (ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.ql:73,46-54) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.ql:73,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.ql:73,23-31) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedData.ql:73,46-54) | test.cpp:20:8:20:12 | getB2 | Member function A::getB2 $@ a non-const raw pointer or reference to a private or protected $@. | test.cpp:20:25:20:25 | b | returns | test.cpp:54:7:54:7 | b | field | | test.cpp:22:8:22:12 | getB3 | Member function A::getB3 $@ a non-const raw pointer or reference to a private or protected $@. | test.cpp:22:25:22:26 | & ... | returns | test.cpp:54:7:54:7 | b | field | | test.cpp:24:8:24:13 | getB33 | Member function A::getB33 $@ a non-const raw pointer or reference to a private or protected $@. | test.cpp:26:12:26:13 | bb | returns | test.cpp:54:7:54:7 | b | field | diff --git a/cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.expected b/cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.expected index 15f4e9a793..1b2aef1b24 100644 --- a/cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.expected +++ b/cpp/autosar/test/rules/M0-3-2/FunctionErroneousReturnValueNotTested.expected @@ -1,4 +1,4 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (FunctionErroneousReturnValueNotTested.ql:70,9-17) -WARNING: Module DataFlow has been deprecated and may be removed in future (FunctionErroneousReturnValueNotTested.ql:70,29-37) -WARNING: Module DataFlow has been deprecated and may be removed in future (FunctionErroneousReturnValueNotTested.ql:70,53-61) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (FunctionErroneousReturnValueNotTested.ql:70,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (FunctionErroneousReturnValueNotTested.ql:70,29-37) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (FunctionErroneousReturnValueNotTested.ql:70,53-61) | test.cpp:16:3:16:8 | call to remove | Return value is not tested for errors. | diff --git a/cpp/autosar/test/rules/M3-9-3/UnderlyingBitRepresentationsOfFloatingPointValuesUsed.expected b/cpp/autosar/test/rules/M3-9-3/UnderlyingBitRepresentationsOfFloatingPointValuesUsed.expected index 2545360a7b..d0fe6416ca 100644 --- a/cpp/autosar/test/rules/M3-9-3/UnderlyingBitRepresentationsOfFloatingPointValuesUsed.expected +++ b/cpp/autosar/test/rules/M3-9-3/UnderlyingBitRepresentationsOfFloatingPointValuesUsed.expected @@ -1,5 +1,5 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (UnderlyingBitRepresentationsOfFloatingPointValuesUsed.ql:27,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (UnderlyingBitRepresentationsOfFloatingPointValuesUsed.ql:36,10-18) -WARNING: Module DataFlow has been deprecated and may be removed in future (UnderlyingBitRepresentationsOfFloatingPointValuesUsed.ql:37,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnderlyingBitRepresentationsOfFloatingPointValuesUsed.ql:27,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnderlyingBitRepresentationsOfFloatingPointValuesUsed.ql:36,10-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnderlyingBitRepresentationsOfFloatingPointValuesUsed.ql:37,5-13) | test.cpp:5:3:5:20 | ... &= ... | Modification of bit-representation of float originated at $@ | test.cpp:4:24:4:60 | reinterpret_cast... | cast | | test.cpp:12:3:12:14 | ... &= ... | Modification of bit-representation of float originated at $@ | test.cpp:11:18:11:30 | (uint8_t *)... | cast | diff --git a/cpp/autosar/test/rules/M9-3-1/ConstMemberFunctionReturnsNonConstPointer.expected b/cpp/autosar/test/rules/M9-3-1/ConstMemberFunctionReturnsNonConstPointer.expected index eee85d22c0..af7e9efc36 100644 --- a/cpp/autosar/test/rules/M9-3-1/ConstMemberFunctionReturnsNonConstPointer.expected +++ b/cpp/autosar/test/rules/M9-3-1/ConstMemberFunctionReturnsNonConstPointer.expected @@ -1,5 +1,5 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (ConstMemberFunctionReturnsNonConstPointer.ql:53,7-15) -WARNING: Module DataFlow has been deprecated and may be removed in future (ConstMemberFunctionReturnsNonConstPointer.ql:55,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ConstMemberFunctionReturnsNonConstPointer.ql:53,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ConstMemberFunctionReturnsNonConstPointer.ql:55,7-15) | test.cpp:8:8:8:11 | getA | Const member function returns a pointer to class data $@. | test.cpp:3:8:3:8 | a | a | | test.cpp:9:8:9:11 | getB | Const member function returns a pointer to class data $@. | test.cpp:4:8:4:8 | b | b | | test.cpp:11:6:11:12 | getThis | Const member function returns a pointer to class data $@. | test.cpp:11:36:11:39 | this | this | diff --git a/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected b/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected index 9259112890..209d81ba8b 100644 --- a/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected +++ b/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected @@ -1,12 +1,12 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:88,7-15) -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:88,27-35) -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:89,9-17) -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:93,9-17) -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:93,29-37) -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:94,11-19) -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:104,35-43) -WARNING: Module DataFlow has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:105,11-19) -WARNING: Module TaintTracking has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:104,9-22) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:88,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:88,27-35) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:89,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:93,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:93,29-37) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:94,11-19) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:104,35-43) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:105,11-19) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:104,9-22) | test.cpp:8:42:8:46 | call to begin | Output iterator for $@ is not guaranteed to be large enough for the input iterator. | test.cpp:8:3:8:11 | call to copy | call to copy | | test.cpp:17:42:17:46 | call to begin | Output iterator for $@ is not guaranteed to be large enough for the input iterator. | test.cpp:17:3:17:11 | call to copy | call to copy | | test.cpp:55:42:55:46 | call to begin | Output iterator for $@ is not guaranteed to be large enough for the input iterator. | test.cpp:55:3:55:11 | call to copy | call to copy | diff --git a/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected b/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected index 5730a54b2c..b5c36727f5 100644 --- a/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected +++ b/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected @@ -1,9 +1,9 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (UseValidIteratorRanges.ql:23,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (UseValidIteratorRanges.ql:23,25-33) -WARNING: Module DataFlow has been deprecated and may be removed in future (UseValidIteratorRanges.ql:24,7-15) -WARNING: Module DataFlow has been deprecated and may be removed in future (UseValidIteratorRanges.ql:30,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (UseValidIteratorRanges.ql:30,25-33) -WARNING: Module DataFlow has been deprecated and may be removed in future (UseValidIteratorRanges.ql:31,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:23,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:23,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:24,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:30,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:30,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:31,7-15) | test.cpp:7:3:7:15 | call to for_each | The $@ of iterator range function does not point to the end of an iterator. | test.cpp:7:28:7:32 | call to begin | argument | | test.cpp:7:3:7:15 | call to for_each | The $@ of iterator range function does not point to the start of an iterator. | test.cpp:7:19:7:21 | call to end | argument | | test.cpp:8:3:8:15 | call to for_each | The $@ of iterator range function does not point to the end of an iterator. | test.cpp:8:30:8:34 | call to begin | argument | diff --git a/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected b/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected index be69b2024d..0ba2fad433 100644 --- a/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected +++ b/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected @@ -1,12 +1,12 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:38,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:38,25-33) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:38,51-59) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:39,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:39,25-33) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:39,52-60) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:74,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:74,25-33) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:75,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:38,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:38,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:38,51-59) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:39,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:39,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:39,52-60) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:74,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:74,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:75,7-15) | test.cpp:8:7:8:7 | i | Increment of iterator may overflow since its bounds are not checked. | | test.cpp:9:9:9:9 | i | Increment of iterator may overflow since its bounds are not checked. | | test.cpp:10:9:10:9 | i | Increment of iterator may overflow since its bounds are not checked. | diff --git a/cpp/cert/test/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.expected b/cpp/cert/test/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.expected index 1f97f2ca40..59caaa22d8 100644 --- a/cpp/cert/test/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.expected +++ b/cpp/cert/test/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.expected @@ -1,7 +1,7 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:41,62-70) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:42,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:51,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:57,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:41,62-70) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:42,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:51,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:57,3-11) edges | test.cpp:15:19:15:21 | foo | test.cpp:16:24:16:26 | foo | provenance | | | test.cpp:15:19:15:21 | foo | test.cpp:16:51:16:53 | foo | provenance | | diff --git a/cpp/cert/test/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.expected b/cpp/cert/test/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.expected index 243602e104..00f1a6ba03 100644 --- a/cpp/cert/test/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.expected +++ b/cpp/cert/test/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.expected @@ -1,27 +1,27 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:24,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:24,59-67) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:27,33-41) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:27,57-65) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:31,33-41) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:31,59-67) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:40,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:40,25-33) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:40,53-61) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:43,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:43,57-65) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:52,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:52,55-63) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:59,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:59,57-65) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:71,31-39) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:71,55-63) -WARNING: Module TaintTracking has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:24,5-18) -WARNING: Module TaintTracking has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:27,7-20) -WARNING: Module TaintTracking has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:31,7-20) -WARNING: Module TaintTracking has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:43,5-18) -WARNING: Module TaintTracking has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:52,5-18) -WARNING: Module TaintTracking has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:59,5-18) -WARNING: Module TaintTracking has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:71,5-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:24,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:24,59-67) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:27,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:27,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:31,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:31,59-67) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:40,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:40,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:40,53-61) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:43,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:43,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:52,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:52,55-63) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:59,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:59,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:71,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:71,55-63) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:24,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:27,7-20) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:31,7-20) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:43,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:52,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:59,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:71,5-18) | test.cpp:82:3:82:4 | call to f2 | Depending on the order of evaluation for the arguments $@ and $@ for side effects on shared state is unspecified and can result in unexpected behavior. | test.cpp:82:6:82:7 | call to f5 | call to f5 | test.cpp:82:12:82:13 | call to f6 | call to f6 | | test.cpp:84:3:84:4 | call to f2 | Depending on the order of evaluation for the arguments $@ and $@ for side effects on shared state is unspecified and can result in unexpected behavior. | test.cpp:84:6:84:7 | call to f5 | call to f5 | test.cpp:84:12:84:13 | call to f7 | call to f7 | | test.cpp:87:3:87:4 | call to f2 | Depending on the order of evaluation for the arguments $@ and $@ for side effects on shared state is unspecified and can result in unexpected behavior. | test.cpp:87:9:87:10 | call to m1 | call to m1 | test.cpp:87:18:87:19 | call to m1 | call to m1 | diff --git a/cpp/cert/test/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.expected b/cpp/cert/test/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.expected index a3c0c08011..c271269ab8 100644 --- a/cpp/cert/test/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.expected +++ b/cpp/cert/test/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.expected @@ -1,7 +1,7 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:19,44-52) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:20,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:22,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:27,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:19,44-52) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:20,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:22,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:27,33-41) edges | test.cpp:6:19:6:37 | new[] | test.cpp:9:12:9:13 | l1 | provenance | | | test.cpp:7:22:7:40 | new[] | test.cpp:10:12:10:13 | l2 | provenance | | diff --git a/cpp/cert/test/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.expected b/cpp/cert/test/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.expected index b30e94a38e..b7b4891776 100644 --- a/cpp/cert/test/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.expected +++ b/cpp/cert/test/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.expected @@ -1,9 +1,9 @@ -WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:59,5-13) -WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:61,36-44) -WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:77,46-54) -WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:78,22-30) -WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:82,20-28) -WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:85,35-43) -WARNING: Module DataFlow has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:90,38-46) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:59,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:61,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:77,46-54) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:78,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:82,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:85,35-43) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:90,38-46) | test.cpp:24:7:24:34 | new | nothrow new allocation of $@ returns here without a subsequent check to see whether the pointer is valid. | test.cpp:24:7:24:34 | new | StructA * | | test.cpp:40:17:40:38 | call to allocate_without_check | nothrow new allocation of $@ returns here without a subsequent check to see whether the pointer is valid. | test.cpp:35:17:35:44 | new | StructA * | diff --git a/cpp/cert/test/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.expected b/cpp/cert/test/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.expected index adabb21674..3743c3d414 100644 --- a/cpp/cert/test/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.expected +++ b/cpp/cert/test/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.expected @@ -1,4 +1,4 @@ -WARNING: Module TaintTracking has been deprecated and may be removed in future (BadlySeededRandomNumberGenerator.ql:37,7-20) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (BadlySeededRandomNumberGenerator.ql:37,7-20) | test.cpp:9:33:9:33 | call to linear_congruential_engine | Random number generator linear_congruential_engine is default-initialized and is therefore not properly seeded. | | test.cpp:10:30:10:31 | call to linear_congruential_engine | Random number generator linear_congruential_engine is default-initialized and is therefore not properly seeded. | | test.cpp:11:21:11:22 | call to linear_congruential_engine | Random number generator linear_congruential_engine is default-initialized and is therefore not properly seeded. | From 87fa7c1c3d9bc079d46d045a182591c2347d7aaa Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Fri, 5 Jul 2024 19:49:48 +0200 Subject: [PATCH 021/370] STR34-C: Do not consider integer type aliases in templates --- .../CastCharBeforeConvertingToLargerSizes.ql | 21 +++++---------- ...CharBeforeConvertingToLargerSizes.expected | 21 --------------- ...astCharBeforeConvertingToLargerSizes.qlref | 1 - ...tCharBeforeConvertingToLargerSizes.testref | 1 + ...oreConvertingToLargerSizes_shared.expected | 21 +++++++++++++++ ...ertingToLargerSizes_shared.expected.clang} | 14 +++++----- ...nvertingToLargerSizes_shared.expected.gcc} | 12 ++++----- ...nvertingToLargerSizes_shared.expected.qcc} | 14 +++++----- ...harBeforeConvertingToLargerSizes_shared.ql | 4 +++ .../test.c | 2 ++ ...arBeforeConvertingToLargerSizes_shared.qll | 26 +++++++++++++++++++ ...oreConvertingToLargerSizes_shared.expected | 2 ++ ...harBeforeConvertingToLargerSizes_shared.ql | 4 +++ .../test.cpp | 17 ++++++++++++ rule_packages/c/Strings3.json | 1 + 15 files changed, 105 insertions(+), 56 deletions(-) delete mode 100644 c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected delete mode 100644 c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.qlref create mode 100644 c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.testref create mode 100644 c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected rename c/{cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected.gcc => common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.clang} (75%) rename c/{cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected.clang => common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.gcc} (78%) rename c/{cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected.qcc => common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.qcc} (75%) create mode 100644 c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql rename c/{cert/test/rules/STR34-C => common/test/rules/castcharbeforeconvertingtolargersizes_shared}/test.c (95%) create mode 100644 cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.qll create mode 100644 cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected create mode 100644 cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql create mode 100644 cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/test.cpp diff --git a/c/cert/src/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.ql b/c/cert/src/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.ql index b0d4088f9f..1f2af0b588 100644 --- a/c/cert/src/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.ql +++ b/c/cert/src/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.ql @@ -14,18 +14,11 @@ import cpp import codingstandards.c.cert -import semmle.code.cpp.commons.CommonType +import codingstandards.cpp.rules.castcharbeforeconvertingtolargersizes_shared.CastCharBeforeConvertingToLargerSizes_shared -from Cast c -where - not isExcluded(c, Strings3Package::castCharBeforeConvertingToLargerSizesQuery()) and - // find cases where there is a conversion happening wherein the - // base type is a char - c.getExpr().getType() instanceof CharType and - not c.getExpr().getType() instanceof UnsignedCharType and - // it's a bigger type - c.getType().getSize() > c.getExpr().getType().getSize() and - // and it's some kind of integer type - c.getType() instanceof IntegralType -select c.getExpr(), - "Expression not converted to `unsigned char` before converting to a larger integer type." +class CastCharBeforeConvertingToLargerSizesQuery extends CastCharBeforeConvertingToLargerSizes_sharedSharedQuery +{ + CastCharBeforeConvertingToLargerSizesQuery() { + this = Strings3Package::castCharBeforeConvertingToLargerSizesQuery() + } +} diff --git a/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected b/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected deleted file mode 100644 index 1c6424dc0c..0000000000 --- a/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected +++ /dev/null @@ -1,21 +0,0 @@ -| test.c:7:7:7:14 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:28:11:28:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:29:3:29:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:29:11:29:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:31:11:31:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:32:11:32:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:33:3:33:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:33:11:33:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:34:3:34:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:34:11:34:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:35:3:35:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:35:11:35:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:36:3:36:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:36:11:36:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:37:11:37:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:38:11:38:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:39:3:39:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:39:11:39:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:40:12:40:13 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:42:11:42:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:43:11:43:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | diff --git a/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.qlref b/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.qlref deleted file mode 100644 index 379d3b3f68..0000000000 --- a/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/STR34-C/CastCharBeforeConvertingToLargerSizes.ql \ No newline at end of file diff --git a/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.testref b/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.testref new file mode 100644 index 0000000000..fefb98580c --- /dev/null +++ b/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.testref @@ -0,0 +1 @@ +c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql \ No newline at end of file diff --git a/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected b/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected new file mode 100644 index 0000000000..c318f791e9 --- /dev/null +++ b/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected @@ -0,0 +1,21 @@ +| test.c:9:7:9:14 | (int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:30:11:30:12 | (int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:31:3:31:13 | (unsigned int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:31:11:31:12 | (int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:33:11:33:12 | (int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:34:11:34:12 | (int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:35:3:35:13 | (unsigned int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:35:11:35:12 | (int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:36:3:36:13 | (unsigned int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:36:11:36:12 | (int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:37:3:37:13 | (unsigned int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:37:11:37:12 | (int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:38:3:38:13 | (unsigned int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:38:11:38:12 | (int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:39:11:39:12 | (int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:40:11:40:12 | (int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:41:3:41:13 | (unsigned int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:41:11:41:12 | (int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:42:12:42:13 | (int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:44:11:44:12 | (int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:45:11:45:12 | (int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | diff --git a/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected.gcc b/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.clang similarity index 75% rename from c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected.gcc rename to c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.clang index 1cf143a196..0378c8a6b5 100644 --- a/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected.gcc +++ b/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.clang @@ -1,8 +1,6 @@ -| test.c:7:7:7:14 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:28:3:28:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:29:3:29:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:9:7:9:14 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:30:3:30:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:31:3:31:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:32:3:32:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:33:3:33:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:34:3:34:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:35:3:35:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | @@ -10,6 +8,8 @@ | test.c:37:3:37:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:38:3:38:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:39:3:39:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:40:3:40:14 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:42:11:42:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:43:11:43:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:40:3:40:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:41:3:41:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:42:3:42:14 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:44:11:44:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:45:11:45:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | diff --git a/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected.clang b/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.gcc similarity index 78% rename from c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected.clang rename to c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.gcc index 1cf143a196..f729c9e42d 100644 --- a/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected.clang +++ b/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.gcc @@ -1,8 +1,6 @@ -| test.c:7:7:7:14 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:28:3:28:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:29:3:29:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:9:7:9:14 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:30:3:30:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:31:3:31:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:32:3:32:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:33:3:33:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:34:3:34:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:35:3:35:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | @@ -10,6 +8,8 @@ | test.c:37:3:37:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:38:3:38:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:39:3:39:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:40:3:40:14 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:42:11:42:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:40:3:40:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:41:3:41:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:42:3:42:14 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:43:11:43:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:44:11:44:12 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | diff --git a/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected.qcc b/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.qcc similarity index 75% rename from c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected.qcc rename to c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.qcc index fec6522014..551423495c 100644 --- a/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.expected.qcc +++ b/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.qcc @@ -1,8 +1,6 @@ -| test.c:7:7:7:14 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:28:3:28:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:29:3:29:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:9:7:9:14 | * ... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:30:3:30:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:31:3:31:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:32:3:32:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:33:3:33:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:34:3:34:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:35:3:35:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | @@ -10,6 +8,8 @@ | test.c:37:3:37:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:38:3:38:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | | test.c:39:3:39:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:40:3:40:14 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:42:3:42:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | -| test.c:43:3:43:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:40:3:40:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:41:3:41:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:42:3:42:14 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:44:3:44:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.c:45:3:45:13 | (...) | Expression not converted to `unsigned char` before converting to a larger integer type. | diff --git a/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql b/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql new file mode 100644 index 0000000000..2aceff89c0 --- /dev/null +++ b/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql @@ -0,0 +1,4 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.castcharbeforeconvertingtolargersizes_shared.CastCharBeforeConvertingToLargerSizes_shared + +class TestFileQuery extends CastCharBeforeConvertingToLargerSizes_sharedSharedQuery, TestQuery { } diff --git a/c/cert/test/rules/STR34-C/test.c b/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/test.c similarity index 95% rename from c/cert/test/rules/STR34-C/test.c rename to c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/test.c index d4bd825c8e..8865e477fb 100644 --- a/c/cert/test/rules/STR34-C/test.c +++ b/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/test.c @@ -1,3 +1,5 @@ +// NOTICE: THE TEST CASES BELOW ARE ALSO INCLUDED IN THE C++ TEST CASE AND +// CHANGES SHOULD BE REFLECTED THERE AS WELL. #include #include diff --git a/cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.qll b/cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.qll new file mode 100644 index 0000000000..3ef9033910 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.qll @@ -0,0 +1,26 @@ +/** + * Provides a library which includes a `problems` predicate for reporting.... + */ + +import cpp +import codingstandards.cpp.Customizations +import codingstandards.cpp.Exclusions + +abstract class CastCharBeforeConvertingToLargerSizes_sharedSharedQuery extends Query { } + +Query getQuery() { result instanceof CastCharBeforeConvertingToLargerSizes_sharedSharedQuery } + +query predicate problems(Cast c, string message) { + not isExcluded(c, getQuery()) and + // find cases where there is a conversion happening wherein the + // base type is a char + c.getExpr().getType() instanceof CharType and + not c.getExpr().getType() instanceof UnsignedCharType and + // it's a bigger type + c.getType().getSize() > c.getExpr().getType().getSize() and + // and it's some kind of integer type + c.getType().getUnderlyingType() instanceof IntegralType and + not c.isFromTemplateInstantiation(_) and + message = + "Expression not converted to `unsigned char` before converting to a larger integer type." +} diff --git a/cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected b/cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected new file mode 100644 index 0000000000..886d03ddac --- /dev/null +++ b/cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected @@ -0,0 +1,2 @@ +| test.cpp:11:9:11:9 | (int32_t)... | Expression not converted to `unsigned char` before converting to a larger integer type. | +| test.cpp:12:41:12:41 | (signed int)... | Expression not converted to `unsigned char` before converting to a larger integer type. | diff --git a/cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql b/cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql new file mode 100644 index 0000000000..2aceff89c0 --- /dev/null +++ b/cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql @@ -0,0 +1,4 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.castcharbeforeconvertingtolargersizes_shared.CastCharBeforeConvertingToLargerSizes_shared + +class TestFileQuery extends CastCharBeforeConvertingToLargerSizes_sharedSharedQuery, TestQuery { } diff --git a/cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/test.cpp b/cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/test.cpp new file mode 100644 index 0000000000..4e5d90e714 --- /dev/null +++ b/cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/test.cpp @@ -0,0 +1,17 @@ +// NOTICE: THE TEST CASES BELOW ARE ALSO INCLUDED IN THE C TEST CASE AND +// CHANGES SHOULD BE REFLECTED THERE AS WELL. +#include + +template S get(T t) { + S s = t; // COMPLIANT + return s; +} + +void test(std::int32_t i32, std::int8_t i8, char c) { + i32 = c; // NON_COMPLIANT + i32 = get(c); // NON_COMPLIANT + i32 = get(c); // COMPLIANT + i32 = i8; // COMPLIANT + i32 = get(i8); // COMPLIANT + i32 = get(i8); // COMPLIANT +} diff --git a/rule_packages/c/Strings3.json b/rule_packages/c/Strings3.json index 9456f4b422..b0131fb55b 100644 --- a/rule_packages/c/Strings3.json +++ b/rule_packages/c/Strings3.json @@ -12,6 +12,7 @@ "precision": "very-high", "severity": "error", "short_name": "CastCharBeforeConvertingToLargerSizes", + "shared_implementation_short_name": "CastCharBeforeConvertingToLargerSizes_shared", "tags": [ "correctness", "security" From dc6bed13a81d6956856ce1c58b9aee12f3d31ab3 Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Fri, 5 Jul 2024 20:00:09 +0200 Subject: [PATCH 022/370] Add change notes --- change_notes/2024-07-05-fix-fp-576-STR34-C.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 change_notes/2024-07-05-fix-fp-576-STR34-C.md diff --git a/change_notes/2024-07-05-fix-fp-576-STR34-C.md b/change_notes/2024-07-05-fix-fp-576-STR34-C.md new file mode 100644 index 0000000000..340d8f4288 --- /dev/null +++ b/change_notes/2024-07-05-fix-fp-576-STR34-C.md @@ -0,0 +1,2 @@ +- `STR34-C` - `CastCharBeforeConvertingToLargerSizes.ql`: + - Fixes #576. Do not consider integer type aliases in templates. \ No newline at end of file From b67dc05ffa5cce5da451bd737e1ad041ef7c15b5 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 12 Jul 2024 11:11:18 +0100 Subject: [PATCH 023/370] C++: Accept test changes after #16969. --- .../ValidContainerElementAccess.expected | 2 ++ cpp/common/test/rules/validcontainerelementaccess/test.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cpp/common/test/rules/validcontainerelementaccess/ValidContainerElementAccess.expected b/cpp/common/test/rules/validcontainerelementaccess/ValidContainerElementAccess.expected index 988846beef..1738cbe330 100644 --- a/cpp/common/test/rules/validcontainerelementaccess/ValidContainerElementAccess.expected +++ b/cpp/common/test/rules/validcontainerelementaccess/ValidContainerElementAccess.expected @@ -7,4 +7,6 @@ | test.cpp:89:15:89:16 | it | Elements of $@ not accessed with valid reference, pointer, or iterator because of a prior $@. | test.cpp:86:20:86:20 | d | container | test.cpp:92:7:92:12 | call to insert | invalidation | | test.cpp:91:9:91:10 | it | Elements of $@ not accessed with valid reference, pointer, or iterator because of a prior $@. | test.cpp:86:20:86:20 | d | container | test.cpp:92:7:92:12 | call to insert | invalidation | | test.cpp:98:56:98:58 | loc | Elements of $@ not accessed with valid reference, pointer, or iterator because of a prior $@. | test.cpp:96:44:96:46 | str | container | test.cpp:99:9:99:14 | call to insert | invalidation | +| test.cpp:99:5:99:7 | str | Elements of $@ not accessed with valid reference, pointer, or iterator because of a prior $@. | test.cpp:96:44:96:46 | str | container | test.cpp:99:9:99:14 | call to insert | invalidation | | test.cpp:99:16:99:18 | loc | Elements of $@ not accessed with valid reference, pointer, or iterator because of a prior $@. | test.cpp:96:44:96:46 | str | container | test.cpp:99:9:99:14 | call to insert | invalidation | +| test.cpp:106:11:106:13 | str | Elements of $@ not accessed with valid reference, pointer, or iterator because of a prior $@. | test.cpp:103:45:103:47 | str | container | test.cpp:106:15:106:20 | call to insert | invalidation | diff --git a/cpp/common/test/rules/validcontainerelementaccess/test.cpp b/cpp/common/test/rules/validcontainerelementaccess/test.cpp index 55c94cf8f1..0f40687110 100644 --- a/cpp/common/test/rules/validcontainerelementaccess/test.cpp +++ b/cpp/common/test/rules/validcontainerelementaccess/test.cpp @@ -96,14 +96,14 @@ void f8(const int *ar) { void f9(const std::string &s, std::string &str) { std::string::iterator loc = str.begin(); for (auto i = s.begin(), e = s.end(); i != e; ++i, ++loc) { // NON_COMPLIANT - str.insert(loc, 'c'); // NON_COMPLIANT + str.insert(loc, 'c'); // NON_COMPLIANT[FALSE POSITIVE for str] } } void f10(const std::string &s, std::string &str) { std::string::iterator loc = str.begin(); for (auto i = s.begin(), e = s.end(); i != e; ++i, ++loc) { // COMPLIANT - loc = str.insert(loc, 'c'); // COMPLIANT + loc = str.insert(loc, 'c'); // COMPLIANT[FALSE POSITIVE] } } From e32a4e452aa8e74733a86d710b58bb5057586c51 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 12 Jul 2024 11:17:04 +0100 Subject: [PATCH 024/370] C++: Format test file expectations. --- cpp/common/test/rules/validcontainerelementaccess/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/common/test/rules/validcontainerelementaccess/test.cpp b/cpp/common/test/rules/validcontainerelementaccess/test.cpp index 0f40687110..d9e2c2d89a 100644 --- a/cpp/common/test/rules/validcontainerelementaccess/test.cpp +++ b/cpp/common/test/rules/validcontainerelementaccess/test.cpp @@ -96,14 +96,14 @@ void f8(const int *ar) { void f9(const std::string &s, std::string &str) { std::string::iterator loc = str.begin(); for (auto i = s.begin(), e = s.end(); i != e; ++i, ++loc) { // NON_COMPLIANT - str.insert(loc, 'c'); // NON_COMPLIANT[FALSE POSITIVE for str] + str.insert(loc, 'c'); // NON_COMPLIANT[FALSE POSITIVE for str] } } void f10(const std::string &s, std::string &str) { std::string::iterator loc = str.begin(); for (auto i = s.begin(), e = s.end(); i != e; ++i, ++loc) { // COMPLIANT - loc = str.insert(loc, 'c'); // COMPLIANT[FALSE POSITIVE] + loc = str.insert(loc, 'c'); // COMPLIANT[FALSE POSITIVE] } } From cfbdc212fcbd1b5f1e5274b19a06e3ff796b7ba9 Mon Sep 17 00:00:00 2001 From: Alexandre Boulgakov Date: Tue, 16 Jul 2024 14:09:34 +0100 Subject: [PATCH 025/370] A12-8-6: Update tests around unused template special members. --- .../rules/A12-8-6/CopyAndMoveNotDeclaredProtected.expected | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cpp/autosar/test/rules/A12-8-6/CopyAndMoveNotDeclaredProtected.expected b/cpp/autosar/test/rules/A12-8-6/CopyAndMoveNotDeclaredProtected.expected index 9f85da12d6..74ed472a52 100644 --- a/cpp/autosar/test/rules/A12-8-6/CopyAndMoveNotDeclaredProtected.expected +++ b/cpp/autosar/test/rules/A12-8-6/CopyAndMoveNotDeclaredProtected.expected @@ -20,7 +20,3 @@ | test.cpp:109:3:109:12 | declaration of BaseClass8 | Move constructor for base class 'BaseClass8' is not declared protected. | | test.cpp:110:15:110:23 | declaration of operator= | Copy assignment operator for base class 'BaseClass8' is not declared protected. | | test.cpp:111:15:111:23 | declaration of operator= | Move assignment operator for base class 'BaseClass8' is not declared protected. | -| test.cpp:124:26:124:26 | declaration of BaseClass9 | Implicit copy constructor for base class 'BaseClass9' is not declared deleted. | -| test.cpp:124:26:124:26 | declaration of BaseClass9 | Implicit move constructor for base class 'BaseClass9' is not declared deleted. | -| test.cpp:124:26:124:26 | declaration of operator= | Implicit copy assignment operator for base class 'BaseClass9' is not declared deleted. | -| test.cpp:124:26:124:26 | declaration of operator= | Implicit move assignment operator for base class 'BaseClass9' is not declared deleted. | From 80ab9a6954315c6c70b37d257e4b269406b5e01c Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 23 Jul 2024 21:57:11 +0100 Subject: [PATCH 026/370] Add change note --- change_notes/2024-06-03-a3-1-5-trivial-defs.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 change_notes/2024-06-03-a3-1-5-trivial-defs.md diff --git a/change_notes/2024-06-03-a3-1-5-trivial-defs.md b/change_notes/2024-06-03-a3-1-5-trivial-defs.md new file mode 100644 index 0000000000..29a7f48eb5 --- /dev/null +++ b/change_notes/2024-06-03-a3-1-5-trivial-defs.md @@ -0,0 +1,4 @@ + - `A3-1-5` - `TrivialOrTemplateFunctionDefinedOutsideClassDefinition.ql`: + - Query deleted - rule was never intended to cover this case (see https://forum.misra.org.uk/archive/index.php?thread-1588.html). + - `A3-1-5` - `NonTrivialNonTemplateFunctionDefinedInsideClassDefinition.ql`: + - Removed false positives caused by flagging member functions in template instantiations From dfe7dca65eb02779b9004607f9e2832e2eaeec3c Mon Sep 17 00:00:00 2001 From: Luke Cartey <5377966+lcartey@users.noreply.github.com> Date: Tue, 23 Jul 2024 22:02:33 +0100 Subject: [PATCH 027/370] Update cpp/common/src/codingstandards/cpp/Class.qll Co-authored-by: Kristen Newbury --- cpp/common/src/codingstandards/cpp/Class.qll | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/Class.qll b/cpp/common/src/codingstandards/cpp/Class.qll index 09d39ce6f8..73c0930f09 100644 --- a/cpp/common/src/codingstandards/cpp/Class.qll +++ b/cpp/common/src/codingstandards/cpp/Class.qll @@ -193,8 +193,11 @@ class TrivialMemberFunction extends IntrospectedMemberFunction { */ class TemplateOrTemplateClassMemberFunction extends MemberFunction { TemplateOrTemplateClassMemberFunction() { - isFromUninstantiatedTemplate(_) or - isFromTemplateInstantiation(_) +( + isFromUninstantiatedTemplate(_) or + isFromTemplateInstantiation(_) + ) and + not this.isCompilerGenerated() } } From 1de5223159e72821e9d5a8eb4215cf00b372d217 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Wed, 24 Jul 2024 22:26:49 +0100 Subject: [PATCH 028/370] Remove extra line --- cpp/autosar/test/rules/A3-1-5/test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/cpp/autosar/test/rules/A3-1-5/test.cpp b/cpp/autosar/test/rules/A3-1-5/test.cpp index 0bff554785..1b2898bf63 100644 --- a/cpp/autosar/test/rules/A3-1-5/test.cpp +++ b/cpp/autosar/test/rules/A3-1-5/test.cpp @@ -172,7 +172,6 @@ void test_FooBar() { foobar.complexCalculation(); } - FooBar::~FooBar() {} // COMPLIANT want to ignore pImpl uses of destructors int FooBar::f1(int a, int b) { // COMPLIANT not a trivial function From 52c7e45ccf8efcb8459cbeb7be779e591e4c3c87 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Wed, 24 Jul 2024 22:30:25 +0100 Subject: [PATCH 029/370] Remove A3-1-5 deleted query --- .../cpp/exclusions/cpp/Classes.qll | 17 ----------------- rule_packages/cpp/Classes.json | 9 --------- 2 files changed, 26 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/Classes.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Classes.qll index 92c7a4280e..3daf48c696 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/cpp/Classes.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Classes.qll @@ -13,7 +13,6 @@ newtype ClassesQuery = TClassDataMembersInitializationConditionQuery() or TRedundantMemberFunctionsShouldBeDefaultedOrLeftUndefinedQuery() or TNonTemplateMemberDefinedInTemplateQuery() or - TTrivialOrTemplateFunctionDefinedOutsideClassDefinitionQuery() or TNonTrivialNonTemplateFunctionDefinedInsideClassDefinitionQuery() or TInParametersForNotCheapToCopyTypesNotPassedByReferenceQuery() or TInParametersForCheapToCopyTypesNotPassedByValueQuery() or @@ -105,15 +104,6 @@ predicate isClassesQueryMetadata(Query query, string queryId, string ruleId, str ruleId = "A14-5-2" and category = "advisory" or - query = - // `Query` instance for the `trivialOrTemplateFunctionDefinedOutsideClassDefinition` query - ClassesPackage::trivialOrTemplateFunctionDefinedOutsideClassDefinitionQuery() and - queryId = - // `@id` for the `trivialOrTemplateFunctionDefinedOutsideClassDefinition` query - "cpp/autosar/trivial-or-template-function-defined-outside-class-definition" and - ruleId = "A3-1-5" and - category = "required" - or query = // `Query` instance for the `nonTrivialNonTemplateFunctionDefinedInsideClassDefinition` query ClassesPackage::nonTrivialNonTemplateFunctionDefinedInsideClassDefinitionQuery() and @@ -251,13 +241,6 @@ module ClassesPackage { TQueryCPP(TClassesPackageQuery(TNonTemplateMemberDefinedInTemplateQuery())) } - Query trivialOrTemplateFunctionDefinedOutsideClassDefinitionQuery() { - //autogenerate `Query` type - result = - // `Query` type for `trivialOrTemplateFunctionDefinedOutsideClassDefinition` query - TQueryCPP(TClassesPackageQuery(TTrivialOrTemplateFunctionDefinedOutsideClassDefinitionQuery())) - } - Query nonTrivialNonTemplateFunctionDefinedInsideClassDefinitionQuery() { //autogenerate `Query` type result = diff --git a/rule_packages/cpp/Classes.json b/rule_packages/cpp/Classes.json index 61eab45081..6dd130a55b 100644 --- a/rule_packages/cpp/Classes.json +++ b/rule_packages/cpp/Classes.json @@ -178,15 +178,6 @@ "obligation": "required" }, "queries": [ - { - "description": "A function that is either trivial, a template function, or a member of a template class may not be defined outside of a class body.", - "kind": "problem", - "name": "A function shall be defined with a class body if and only if it is intended to be inlined", - "precision": "very-high", - "severity": "recommendation", - "short_name": "TrivialOrTemplateFunctionDefinedOutsideClassDefinition", - "tags": [] - }, { "description": "A function that is not either trivial, a template function, or a member of a template class may not be defined within a class body.", "kind": "problem", From 099dbb85308413ee319f42df22c6d3f870dee221 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Wed, 24 Jul 2024 23:28:04 +0100 Subject: [PATCH 030/370] Fix Class.qll formatting. --- cpp/common/src/codingstandards/cpp/Class.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/Class.qll b/cpp/common/src/codingstandards/cpp/Class.qll index 3aa7719fb8..6f730736f9 100644 --- a/cpp/common/src/codingstandards/cpp/Class.qll +++ b/cpp/common/src/codingstandards/cpp/Class.qll @@ -192,7 +192,7 @@ class TrivialMemberFunction extends IntrospectedMemberFunction { */ class TemplateOrTemplateClassMemberFunction extends MemberFunction { TemplateOrTemplateClassMemberFunction() { -( + ( isFromUninstantiatedTemplate(_) or isFromTemplateInstantiation(_) ) and From e3a5b8cdd87726a0faa4862e24ee1db9b5257b08 Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Thu, 25 Jul 2024 20:13:49 +0200 Subject: [PATCH 031/370] renamed the shared query --- .../CastCharBeforeConvertingToLargerSizes.ql | 4 +-- ...tCharBeforeConvertingToLargerSizes.testref | 2 +- ...harBeforeConvertingToLargerSizes.expected} | 0 ...oreConvertingToLargerSizes.expected.clang} | 0 ...eforeConvertingToLargerSizes.expected.gcc} | 0 ...eforeConvertingToLargerSizes.expected.qcc} | 0 .../CastCharBeforeConvertingToLargerSizes.ql} | 4 +-- .../test.c | 0 .../CastCharBeforeConvertingToLargerSizes.qll | 27 +++++++++++++++++++ ...arBeforeConvertingToLargerSizes_shared.qll | 26 ------------------ ...harBeforeConvertingToLargerSizes.expected} | 0 .../CastCharBeforeConvertingToLargerSizes.ql} | 4 +-- .../test.cpp | 0 rule_packages/c/Strings3.json | 2 +- 14 files changed, 35 insertions(+), 34 deletions(-) rename c/common/test/rules/{castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected => castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.expected} (100%) rename c/common/test/rules/{castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.clang => castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.expected.clang} (100%) rename c/common/test/rules/{castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.gcc => castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.expected.gcc} (100%) rename c/common/test/rules/{castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.qcc => castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.expected.qcc} (100%) rename c/common/test/rules/{castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql => castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.ql} (63%) rename c/common/test/rules/{castcharbeforeconvertingtolargersizes_shared => castcharbeforeconvertingtolargersizes}/test.c (100%) create mode 100644 cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.qll delete mode 100644 cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.qll rename cpp/common/test/rules/{castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected => castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.expected} (100%) rename cpp/common/test/rules/{castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql => castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.ql} (63%) rename cpp/common/test/rules/{castcharbeforeconvertingtolargersizes_shared => castcharbeforeconvertingtolargersizes}/test.cpp (100%) diff --git a/c/cert/src/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.ql b/c/cert/src/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.ql index 1f2af0b588..394df49d99 100644 --- a/c/cert/src/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.ql +++ b/c/cert/src/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.ql @@ -14,9 +14,9 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.rules.castcharbeforeconvertingtolargersizes_shared.CastCharBeforeConvertingToLargerSizes_shared +import codingstandards.cpp.rules.castcharbeforeconvertingtolargersizes.CastCharBeforeConvertingToLargerSizes -class CastCharBeforeConvertingToLargerSizesQuery extends CastCharBeforeConvertingToLargerSizes_sharedSharedQuery +class CastCharBeforeConvertingToLargerSizesQuery extends CastCharBeforeConvertingToLargerSizesSharedQuery { CastCharBeforeConvertingToLargerSizesQuery() { this = Strings3Package::castCharBeforeConvertingToLargerSizesQuery() diff --git a/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.testref b/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.testref index fefb98580c..0e13e05dc3 100644 --- a/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.testref +++ b/c/cert/test/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.testref @@ -1 +1 @@ -c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql \ No newline at end of file +c/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.ql \ No newline at end of file diff --git a/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected b/c/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.expected similarity index 100% rename from c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected rename to c/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.expected diff --git a/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.clang b/c/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.expected.clang similarity index 100% rename from c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.clang rename to c/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.expected.clang diff --git a/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.gcc b/c/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.expected.gcc similarity index 100% rename from c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.gcc rename to c/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.expected.gcc diff --git a/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.qcc b/c/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.expected.qcc similarity index 100% rename from c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected.qcc rename to c/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.expected.qcc diff --git a/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql b/c/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.ql similarity index 63% rename from c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql rename to c/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.ql index 2aceff89c0..2a1e49774f 100644 --- a/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql +++ b/c/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.ql @@ -1,4 +1,4 @@ // GENERATED FILE - DO NOT MODIFY -import codingstandards.cpp.rules.castcharbeforeconvertingtolargersizes_shared.CastCharBeforeConvertingToLargerSizes_shared +import codingstandards.cpp.rules.castcharbeforeconvertingtolargersizes.CastCharBeforeConvertingToLargerSizes -class TestFileQuery extends CastCharBeforeConvertingToLargerSizes_sharedSharedQuery, TestQuery { } +class TestFileQuery extends CastCharBeforeConvertingToLargerSizesSharedQuery, TestQuery { } diff --git a/c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/test.c b/c/common/test/rules/castcharbeforeconvertingtolargersizes/test.c similarity index 100% rename from c/common/test/rules/castcharbeforeconvertingtolargersizes_shared/test.c rename to c/common/test/rules/castcharbeforeconvertingtolargersizes/test.c diff --git a/cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.qll b/cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.qll new file mode 100644 index 0000000000..5d396f9a42 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.qll @@ -0,0 +1,27 @@ +/** + * Provides a library which includes a `problems` predicate for reporting.... + */ + + import cpp + import codingstandards.cpp.Customizations + import codingstandards.cpp.Exclusions + + abstract class CastCharBeforeConvertingToLargerSizesSharedQuery extends Query { } + + Query getQuery() { result instanceof CastCharBeforeConvertingToLargerSizesSharedQuery } + + query predicate problems(Cast c, string message) { + not isExcluded(c, getQuery()) and + // find cases where there is a conversion happening wherein the + // base type is a char + c.getExpr().getType() instanceof CharType and + not c.getExpr().getType() instanceof UnsignedCharType and + // it's a bigger type + c.getType().getSize() > c.getExpr().getType().getSize() and + // and it's some kind of integer type + c.getType().getUnderlyingType() instanceof IntegralType and + not c.isFromTemplateInstantiation(_) and + message = + "Expression not converted to `unsigned char` before converting to a larger integer type." + } + \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.qll b/cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.qll deleted file mode 100644 index 3ef9033910..0000000000 --- a/cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.qll +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Provides a library which includes a `problems` predicate for reporting.... - */ - -import cpp -import codingstandards.cpp.Customizations -import codingstandards.cpp.Exclusions - -abstract class CastCharBeforeConvertingToLargerSizes_sharedSharedQuery extends Query { } - -Query getQuery() { result instanceof CastCharBeforeConvertingToLargerSizes_sharedSharedQuery } - -query predicate problems(Cast c, string message) { - not isExcluded(c, getQuery()) and - // find cases where there is a conversion happening wherein the - // base type is a char - c.getExpr().getType() instanceof CharType and - not c.getExpr().getType() instanceof UnsignedCharType and - // it's a bigger type - c.getType().getSize() > c.getExpr().getType().getSize() and - // and it's some kind of integer type - c.getType().getUnderlyingType() instanceof IntegralType and - not c.isFromTemplateInstantiation(_) and - message = - "Expression not converted to `unsigned char` before converting to a larger integer type." -} diff --git a/cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected b/cpp/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.expected similarity index 100% rename from cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.expected rename to cpp/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.expected diff --git a/cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql b/cpp/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.ql similarity index 63% rename from cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql rename to cpp/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.ql index 2aceff89c0..2a1e49774f 100644 --- a/cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/CastCharBeforeConvertingToLargerSizes_shared.ql +++ b/cpp/common/test/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.ql @@ -1,4 +1,4 @@ // GENERATED FILE - DO NOT MODIFY -import codingstandards.cpp.rules.castcharbeforeconvertingtolargersizes_shared.CastCharBeforeConvertingToLargerSizes_shared +import codingstandards.cpp.rules.castcharbeforeconvertingtolargersizes.CastCharBeforeConvertingToLargerSizes -class TestFileQuery extends CastCharBeforeConvertingToLargerSizes_sharedSharedQuery, TestQuery { } +class TestFileQuery extends CastCharBeforeConvertingToLargerSizesSharedQuery, TestQuery { } diff --git a/cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/test.cpp b/cpp/common/test/rules/castcharbeforeconvertingtolargersizes/test.cpp similarity index 100% rename from cpp/common/test/rules/castcharbeforeconvertingtolargersizes_shared/test.cpp rename to cpp/common/test/rules/castcharbeforeconvertingtolargersizes/test.cpp diff --git a/rule_packages/c/Strings3.json b/rule_packages/c/Strings3.json index b0131fb55b..1cecf390ec 100644 --- a/rule_packages/c/Strings3.json +++ b/rule_packages/c/Strings3.json @@ -12,7 +12,7 @@ "precision": "very-high", "severity": "error", "short_name": "CastCharBeforeConvertingToLargerSizes", - "shared_implementation_short_name": "CastCharBeforeConvertingToLargerSizes_shared", + "shared_implementation_short_name": "CastCharBeforeConvertingToLargerSizes", "tags": [ "correctness", "security" From 946d5dfcc98f602be23a7cdfc3a0c10dcb258c30 Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Thu, 25 Jul 2024 20:26:02 +0200 Subject: [PATCH 032/370] Fix formatting --- .../CastCharBeforeConvertingToLargerSizes.qll | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.qll b/cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.qll index 5d396f9a42..66f1006d17 100644 --- a/cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.qll +++ b/cpp/common/src/codingstandards/cpp/rules/castcharbeforeconvertingtolargersizes/CastCharBeforeConvertingToLargerSizes.qll @@ -2,26 +2,25 @@ * Provides a library which includes a `problems` predicate for reporting.... */ - import cpp - import codingstandards.cpp.Customizations - import codingstandards.cpp.Exclusions - - abstract class CastCharBeforeConvertingToLargerSizesSharedQuery extends Query { } - - Query getQuery() { result instanceof CastCharBeforeConvertingToLargerSizesSharedQuery } - - query predicate problems(Cast c, string message) { - not isExcluded(c, getQuery()) and - // find cases where there is a conversion happening wherein the - // base type is a char - c.getExpr().getType() instanceof CharType and - not c.getExpr().getType() instanceof UnsignedCharType and - // it's a bigger type - c.getType().getSize() > c.getExpr().getType().getSize() and - // and it's some kind of integer type - c.getType().getUnderlyingType() instanceof IntegralType and - not c.isFromTemplateInstantiation(_) and - message = - "Expression not converted to `unsigned char` before converting to a larger integer type." - } - \ No newline at end of file +import cpp +import codingstandards.cpp.Customizations +import codingstandards.cpp.Exclusions + +abstract class CastCharBeforeConvertingToLargerSizesSharedQuery extends Query { } + +Query getQuery() { result instanceof CastCharBeforeConvertingToLargerSizesSharedQuery } + +query predicate problems(Cast c, string message) { + not isExcluded(c, getQuery()) and + // find cases where there is a conversion happening wherein the + // base type is a char + c.getExpr().getType() instanceof CharType and + not c.getExpr().getType() instanceof UnsignedCharType and + // it's a bigger type + c.getType().getSize() > c.getExpr().getType().getSize() and + // and it's some kind of integer type + c.getType().getUnderlyingType() instanceof IntegralType and + not c.isFromTemplateInstantiation(_) and + message = + "Expression not converted to `unsigned char` before converting to a larger integer type." +} From 94d711461dd6c7df5578614a854c8a423dee866b Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 3 Sep 2024 15:54:23 +0200 Subject: [PATCH 033/370] Update expected test results after merge from main --- ...sedPointerToRestrictQualifiedParamShared.expected | 12 ------------ .../A18-5-8/UnnecessaryUseOfDynamicStorage.expected | 7 ++++--- .../test/rules/M0-1-2/InfeasiblePath.expected | 3 --- .../ConstLikeReturnValue.expected | 10 +++++----- 4 files changed, 9 insertions(+), 23 deletions(-) diff --git a/c/common/test/rules/donotpassaliasedpointertorestrictqualifiedparamshared/DoNotPassAliasedPointerToRestrictQualifiedParamShared.expected b/c/common/test/rules/donotpassaliasedpointertorestrictqualifiedparamshared/DoNotPassAliasedPointerToRestrictQualifiedParamShared.expected index 1c8a649094..4d4c20a39c 100644 --- a/c/common/test/rules/donotpassaliasedpointertorestrictqualifiedparamshared/DoNotPassAliasedPointerToRestrictQualifiedParamShared.expected +++ b/c/common/test/rules/donotpassaliasedpointertorestrictqualifiedparamshared/DoNotPassAliasedPointerToRestrictQualifiedParamShared.expected @@ -1,15 +1,3 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:103,36-44) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:118,51-59) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:119,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:121,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:127,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:132,40-48) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:146,41-49) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:147,7-15) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:150,43-51) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:151,9-17) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:158,43-51) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassAliasedPointerToRestrictQualifiedParam.ql:159,9-17) | test.c:59:3:59:6 | call to copy | Call to 'copy' passes an $@ to a $@ (pointer value derived from a pair of address-of expressions ($@, $@). | test.c:59:13:59:15 | & ... | aliased pointer | test.c:59:8:59:10 | & ... | restrict-qualified parameter | test.c:59:8:59:10 | & ... | addressof1 | test.c:59:13:59:15 | & ... | addressof2 | | test.c:65:3:65:6 | call to copy | Call to 'copy' passes an $@ to a $@ (pointer value derived from a pair of address-of expressions ($@, $@). | test.c:65:15:65:19 | & ... | aliased pointer | test.c:65:8:65:12 | & ... | restrict-qualified parameter | test.c:65:8:65:12 | & ... | addressof1 | test.c:65:15:65:19 | & ... | addressof2 | | test.c:67:3:67:6 | call to copy | Call to 'copy' passes an $@ to a $@ (pointer value derived from a pair of address-of expressions ($@, $@). | test.c:67:15:67:16 | px | aliased pointer | test.c:67:8:67:12 | & ... | restrict-qualified parameter | test.c:67:8:67:12 | & ... | addressof1 | test.c:63:13:63:17 | & ... | addressof2 | diff --git a/cpp/autosar/test/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.expected b/cpp/autosar/test/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.expected index 6ab75d989e..68cab835fa 100644 --- a/cpp/autosar/test/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.expected +++ b/cpp/autosar/test/rules/A18-5-8/UnnecessaryUseOfDynamicStorage.expected @@ -1,7 +1,8 @@ WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:55,34-42) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:57,26-34) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:71,5-18) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:76,41-54) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:58,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:60,26-34) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:74,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (UnnecessaryUseOfDynamicStorage.ql:79,41-54) | test.cpp:17:17:17:29 | new | StructA object of size 8 bytes does not appear to outlive the function, but is created on the heap instead of the stack. | | test.cpp:21:17:21:32 | new[] | StructA[] object of size 800 bytes does not appear to outlive the function, but is created on the heap instead of the stack. | | test.cpp:35:20:35:44 | call to make_shared | StructA object of size 8 bytes does not appear to outlive the function, but is created on the heap instead of the stack. | diff --git a/cpp/autosar/test/rules/M0-1-2/InfeasiblePath.expected b/cpp/autosar/test/rules/M0-1-2/InfeasiblePath.expected index 9cb237e8b3..d0a819a794 100644 --- a/cpp/autosar/test/rules/M0-1-2/InfeasiblePath.expected +++ b/cpp/autosar/test/rules/M0-1-2/InfeasiblePath.expected @@ -2,9 +2,6 @@ | test.cpp:7:7:7:22 | ... <= ... | The false path is infeasible because a (max value: 4294967295) is always less than or equal to 4294967295 (minimum value: 4294967295). | | test.cpp:15:7:15:13 | ... < ... | The false path is infeasible because l1 (max value: 2) is always less than l2 (minimum value: 10). | | test.cpp:19:9:19:14 | ... < ... | The false path is infeasible because a (max value: 1) is always less than l2 (minimum value: 10). | -| test.cpp:33:7:33:7 | 0 | The path is unreachable in a template. | | test.cpp:77:9:77:14 | ... < ... | The true path is infeasible because 0 (max value: 0) is always less than or equal to a (minimum value: 0). | | test.cpp:80:9:80:15 | ... >= ... | The false path is infeasible because 0 (max value: 0) is always less than or equal to a (minimum value: 0). | | test.cpp:86:9:86:14 | ... < ... | The true path is infeasible because 0 (max value: 0) is always less than or equal to a (minimum value: 0). | -| test.cpp:117:7:117:7 | 0 | The path is unreachable in a template. | -| test.cpp:123:7:123:8 | ! ... | The path is unreachable in a template. | diff --git a/cpp/common/test/rules/constlikereturnvalue/ConstLikeReturnValue.expected b/cpp/common/test/rules/constlikereturnvalue/ConstLikeReturnValue.expected index b02aa464bb..2caa0d197c 100644 --- a/cpp/common/test/rules/constlikereturnvalue/ConstLikeReturnValue.expected +++ b/cpp/common/test/rules/constlikereturnvalue/ConstLikeReturnValue.expected @@ -3,11 +3,11 @@ problems | test.cpp:67:5:67:9 | conv4 | test.cpp:64:11:64:20 | call to localeconv | test.cpp:67:5:67:9 | conv4 | The object returned by the function localeconv should not be modified. | | test.cpp:76:5:76:8 | conv | test.cpp:72:25:72:34 | call to localeconv | test.cpp:76:5:76:8 | conv | The object returned by the function localeconv should not be modified. | edges -| test.cpp:8:18:8:22 | c_str | test.cpp:11:8:11:12 | c_str | -| test.cpp:18:16:18:21 | call to getenv | test.cpp:24:9:24:12 | env1 | -| test.cpp:24:9:24:12 | env1 | test.cpp:8:18:8:22 | c_str | -| test.cpp:64:11:64:20 | call to localeconv | test.cpp:67:5:67:9 | conv4 | -| test.cpp:72:25:72:34 | call to localeconv | test.cpp:76:5:76:8 | conv | +| test.cpp:8:18:8:22 | c_str | test.cpp:11:8:11:12 | c_str | provenance | | +| test.cpp:18:16:18:21 | call to getenv | test.cpp:24:9:24:12 | env1 | provenance | | +| test.cpp:24:9:24:12 | env1 | test.cpp:8:18:8:22 | c_str | provenance | | +| test.cpp:64:11:64:20 | call to localeconv | test.cpp:67:5:67:9 | conv4 | provenance | | +| test.cpp:72:25:72:34 | call to localeconv | test.cpp:76:5:76:8 | conv | provenance | | nodes | test.cpp:8:18:8:22 | c_str | semmle.label | c_str | | test.cpp:11:8:11:12 | c_str | semmle.label | c_str | From 8461696679fad63de78bcb71301b4980724f4a9f Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 13 Sep 2024 16:43:41 +0200 Subject: [PATCH 034/370] Remove data flow imports from queries that do not actually use it --- .../rules/CON30-C/CleanUpThreadSpecificStorage.ql | 1 - .../AppropriateThreadObjectStorageDurations.ql | 1 - .../ThreadObjectStorageDurationsNotInitialized.ql | 1 - c/cert/src/rules/ERR30-C/ErrnoReadBeforeReturn.ql | 1 + .../rules/ERR30-C/FunctionCallBeforeErrnoCheck.ql | 1 - c/cert/src/rules/ERR30-C/SetlocaleMightSetErrno.ql | 1 + ...ndenceOnOrderOfFunctionArgumentsForSideEffects.ql | 1 - .../SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql | 2 +- .../CON30-C/CleanUpThreadSpecificStorage.expected | 12 ++++++------ .../AppropriateThreadObjectStorageDurations.expected | 12 ++++++------ ...readObjectStorageDurationsNotInitialized.expected | 6 +++--- .../rules/ERR30-C/ErrnoReadBeforeReturn.expected | 2 +- .../rules/ERR30-C/SetlocaleMightSetErrno.expected | 2 +- c/common/src/codingstandards/c/Errno.qll | 1 - .../RULE-17-7/ValueReturnedByAFunctionNotUsed.ql | 1 - .../RULE-19-1/ObjectCopiedToAnOverlappingObject.ql | 1 - .../src/rules/A18-5-2/DoNotUseNonPlacementNew.ql | 1 - .../A8-4-4/FunctionReturnMultipleValueCondition.ql | 1 - .../PointerToAVirtualBaseClassCastToAPointer.ql | 1 - .../lifetimes/lifetimeprofile/LifetimeProfile.qll | 1 - .../AccessOfUndefinedMemberThroughNullPointer.qll | 1 - .../UnusedReturnValue.ql | 1 - .../deviations_basic_test/UnusedReturnValue.ql | 1 - .../deviations_report_deviated/UnusedReturnValue.ql | 1 - 24 files changed, 20 insertions(+), 34 deletions(-) diff --git a/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql b/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql index d55f1326bf..69b1b333be 100644 --- a/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql +++ b/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql @@ -15,7 +15,6 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.Concurrency -import semmle.code.cpp.dataflow.TaintTracking import semmle.code.cpp.dataflow.DataFlow module TssCreateToTssDeleteConfig implements DataFlow::ConfigSig { diff --git a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql index 71138f4ff8..78b5a090b2 100644 --- a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql +++ b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql @@ -15,7 +15,6 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.Concurrency -import semmle.code.cpp.dataflow.TaintTracking import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.commons.Alloc diff --git a/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql b/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql index ddcddb8dc5..fc75cb94ff 100644 --- a/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql +++ b/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql @@ -16,7 +16,6 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.Concurrency -import semmle.code.cpp.dataflow.TaintTracking import semmle.code.cpp.dataflow.DataFlow from TSSGetFunctionCall tsg, ThreadedFunction tf diff --git a/c/cert/src/rules/ERR30-C/ErrnoReadBeforeReturn.ql b/c/cert/src/rules/ERR30-C/ErrnoReadBeforeReturn.ql index df8519f13f..527529cc30 100644 --- a/c/cert/src/rules/ERR30-C/ErrnoReadBeforeReturn.ql +++ b/c/cert/src/rules/ERR30-C/ErrnoReadBeforeReturn.ql @@ -14,6 +14,7 @@ import cpp import codingstandards.c.cert import codingstandards.c.Errno +import semmle.code.cpp.dataflow.DataFlow /** * A call to an `OutOfBandErrnoSettingFunction` diff --git a/c/cert/src/rules/ERR30-C/FunctionCallBeforeErrnoCheck.ql b/c/cert/src/rules/ERR30-C/FunctionCallBeforeErrnoCheck.ql index dd2e2175f7..17714c646f 100644 --- a/c/cert/src/rules/ERR30-C/FunctionCallBeforeErrnoCheck.ql +++ b/c/cert/src/rules/ERR30-C/FunctionCallBeforeErrnoCheck.ql @@ -14,7 +14,6 @@ import cpp import codingstandards.c.cert import codingstandards.c.Errno -import semmle.code.cpp.dataflow.DataFlow /** * A call to an `OutOfBandErrnoSettingFunction` diff --git a/c/cert/src/rules/ERR30-C/SetlocaleMightSetErrno.ql b/c/cert/src/rules/ERR30-C/SetlocaleMightSetErrno.ql index 899fa49e60..9c94284841 100644 --- a/c/cert/src/rules/ERR30-C/SetlocaleMightSetErrno.ql +++ b/c/cert/src/rules/ERR30-C/SetlocaleMightSetErrno.ql @@ -13,6 +13,7 @@ import cpp import codingstandards.c.cert import codingstandards.c.Errno +import semmle.code.cpp.dataflow.DataFlow class SetlocaleFunctionCall extends FunctionCall { SetlocaleFunctionCall() { this.getTarget().hasGlobalName("setlocale") } diff --git a/c/cert/src/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.ql b/c/cert/src/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.ql index fb14515c61..a761ec7f48 100644 --- a/c/cert/src/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.ql +++ b/c/cert/src/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.ql @@ -14,7 +14,6 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.SideEffect -import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.dataflow.TaintTracking import semmle.code.cpp.valuenumbering.GlobalValueNumbering diff --git a/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql b/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql index 54f555d7cb..5945da57f4 100644 --- a/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql +++ b/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.FgetsErrorManagement import codingstandards.cpp.Dereferenced -import semmle.code.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.DataFlow /* * CFG nodes that follows a successful call to `fgets` diff --git a/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected b/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected index 2706474f29..047ed12e8e 100644 --- a/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected +++ b/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected @@ -1,9 +1,9 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:21,46-54) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:22,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:31,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:41,35-43) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:49,36-44) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:51,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:20,46-54) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:21,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:30,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:40,35-43) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:48,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:50,36-44) | test.c:27:3:27:12 | call to tss_create | Resources used by thread specific storage may not be cleaned up. | | test.c:49:3:49:12 | call to tss_create | Resources used by thread specific storage may not be cleaned up. | | test.c:71:3:71:12 | call to tss_create | Resources used by thread specific storage may not be cleaned up. | diff --git a/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected b/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected index 25cb74d7fa..7e4cf71c21 100644 --- a/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected +++ b/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected @@ -1,11 +1,11 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:28,29-37) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:28,54-62) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:35,62-70) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:27,29-37) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:27,54-62) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:34,62-70) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:39,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:39,30-38) WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:40,5-13) WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:40,30-38) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:41,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:41,30-38) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:28,3-16) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:27,3-16) | test.c:23:3:23:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:23:24:23:29 | & ... | Shared object | | test.c:74:3:74:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:74:24:74:24 | p | Shared object | | test.c:85:3:85:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:85:24:85:24 | p | Shared object | diff --git a/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected b/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected index d6b6548581..f8e86fbb51 100644 --- a/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected +++ b/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected @@ -1,6 +1,6 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:28,38-46) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:27,38-46) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:30,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:30,30-38) WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:31,5-13) WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:31,30-38) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:32,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:32,30-38) | test.c:14:7:14:13 | call to tss_get | Call to a thread specific storage function from within a threaded context on an object that may not be owned by this thread. | diff --git a/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected b/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected index 659a731d7c..e925901b47 100644 --- a/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected +++ b/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected @@ -1,4 +1,4 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ErrnoReadBeforeReturn.ql:40,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ErrnoReadBeforeReturn.ql:41,7-15) | test.c:69:7:69:11 | * ... | Do not read `errno` before checking the return value of function $@. | test.c:68:3:68:7 | call to ftell | call to ftell | | test.c:69:7:69:11 | call to __errno_location | Do not read `errno` before checking the return value of function $@. | test.c:68:3:68:7 | call to ftell | call to ftell | | test.c:70:5:70:10 | call to perror | Do not read `errno` before checking the return value of function $@. | test.c:68:3:68:7 | call to ftell | call to ftell | diff --git a/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected b/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected index d20f4a4e34..489bfc6bb0 100644 --- a/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected +++ b/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected @@ -1,3 +1,3 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (SetlocaleMightSetErrno.ql:64,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (SetlocaleMightSetErrno.ql:65,7-15) | test.c:98:3:98:11 | call to setlocale | Do not read `errno` before checking the return value of a call to `setlocale`. | | test.c:104:7:104:15 | call to setlocale | The value of `errno` may be different than `0` when `setlocale` is called. The following `errno` check might be invalid. | diff --git a/c/common/src/codingstandards/c/Errno.qll b/c/common/src/codingstandards/c/Errno.qll index d606593a1e..768927f505 100644 --- a/c/common/src/codingstandards/c/Errno.qll +++ b/c/common/src/codingstandards/c/Errno.qll @@ -1,7 +1,6 @@ /** Provides a library for errno-setting functions. */ import cpp -import semmle.code.cpp.dataflow.DataFlow /** * An errno-setting function diff --git a/c/misra/src/rules/RULE-17-7/ValueReturnedByAFunctionNotUsed.ql b/c/misra/src/rules/RULE-17-7/ValueReturnedByAFunctionNotUsed.ql index 3b224544f2..5907d00769 100644 --- a/c/misra/src/rules/RULE-17-7/ValueReturnedByAFunctionNotUsed.ql +++ b/c/misra/src/rules/RULE-17-7/ValueReturnedByAFunctionNotUsed.ql @@ -13,7 +13,6 @@ import cpp import codingstandards.c.misra -import semmle.code.cpp.dataflow.DataFlow from Call c where diff --git a/c/misra/src/rules/RULE-19-1/ObjectCopiedToAnOverlappingObject.ql b/c/misra/src/rules/RULE-19-1/ObjectCopiedToAnOverlappingObject.ql index fe1226dcea..0e276773dc 100644 --- a/c/misra/src/rules/RULE-19-1/ObjectCopiedToAnOverlappingObject.ql +++ b/c/misra/src/rules/RULE-19-1/ObjectCopiedToAnOverlappingObject.ql @@ -13,7 +13,6 @@ import cpp import codingstandards.c.misra import semmle.code.cpp.valuenumbering.GlobalValueNumbering -import semmle.code.cpp.dataflow.DataFlow /** * Offset in bytes of a field access diff --git a/cpp/autosar/src/rules/A18-5-2/DoNotUseNonPlacementNew.ql b/cpp/autosar/src/rules/A18-5-2/DoNotUseNonPlacementNew.ql index 1320d6e486..3cfccbf11e 100644 --- a/cpp/autosar/src/rules/A18-5-2/DoNotUseNonPlacementNew.ql +++ b/cpp/autosar/src/rules/A18-5-2/DoNotUseNonPlacementNew.ql @@ -15,7 +15,6 @@ import cpp import codingstandards.cpp.autosar -import semmle.code.cpp.dataflow.DataFlow from NewOrNewArrayExpr na where diff --git a/cpp/autosar/src/rules/A8-4-4/FunctionReturnMultipleValueCondition.ql b/cpp/autosar/src/rules/A8-4-4/FunctionReturnMultipleValueCondition.ql index ff0040f26f..03f0c3cea6 100644 --- a/cpp/autosar/src/rules/A8-4-4/FunctionReturnMultipleValueCondition.ql +++ b/cpp/autosar/src/rules/A8-4-4/FunctionReturnMultipleValueCondition.ql @@ -16,7 +16,6 @@ import cpp import codingstandards.cpp.autosar -import semmle.code.cpp.dataflow.DataFlow abstract class OutputValue extends Element { abstract string getOutputName(); diff --git a/cpp/autosar/src/rules/M5-2-2/PointerToAVirtualBaseClassCastToAPointer.ql b/cpp/autosar/src/rules/M5-2-2/PointerToAVirtualBaseClassCastToAPointer.ql index d24c4d35df..086aa40ae7 100644 --- a/cpp/autosar/src/rules/M5-2-2/PointerToAVirtualBaseClassCastToAPointer.ql +++ b/cpp/autosar/src/rules/M5-2-2/PointerToAVirtualBaseClassCastToAPointer.ql @@ -15,7 +15,6 @@ import cpp import codingstandards.cpp.autosar -import semmle.code.cpp.dataflow.DataFlow from Cast cast, VirtualBaseClass castFrom, Class castTo where diff --git a/cpp/common/src/codingstandards/cpp/lifetimes/lifetimeprofile/LifetimeProfile.qll b/cpp/common/src/codingstandards/cpp/lifetimes/lifetimeprofile/LifetimeProfile.qll index 354dccdc56..b02f51380e 100644 --- a/cpp/common/src/codingstandards/cpp/lifetimes/lifetimeprofile/LifetimeProfile.qll +++ b/cpp/common/src/codingstandards/cpp/lifetimes/lifetimeprofile/LifetimeProfile.qll @@ -1,5 +1,4 @@ import cpp -private import semmle.code.cpp.dataflow.DataFlow private import semmle.code.cpp.controlflow.Nullness private import codingstandards.cpp.Dereferenced private import codingstandards.cpp.Expr diff --git a/cpp/common/src/codingstandards/cpp/rules/accessofundefinedmemberthroughnullpointer/AccessOfUndefinedMemberThroughNullPointer.qll b/cpp/common/src/codingstandards/cpp/rules/accessofundefinedmemberthroughnullpointer/AccessOfUndefinedMemberThroughNullPointer.qll index e0fb382008..b213087c5c 100644 --- a/cpp/common/src/codingstandards/cpp/rules/accessofundefinedmemberthroughnullpointer/AccessOfUndefinedMemberThroughNullPointer.qll +++ b/cpp/common/src/codingstandards/cpp/rules/accessofundefinedmemberthroughnullpointer/AccessOfUndefinedMemberThroughNullPointer.qll @@ -7,7 +7,6 @@ import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import codingstandards.cpp.Nullness import codingstandards.cpp.Expr -import semmle.code.cpp.dataflow.DataFlow import NullPointerToPointerMemberExpressionFlow::PathGraph abstract class AccessOfUndefinedMemberThroughNullPointerSharedQuery extends Query { } diff --git a/cpp/common/test/deviations/deviation_permits_basic_test/UnusedReturnValue.ql b/cpp/common/test/deviations/deviation_permits_basic_test/UnusedReturnValue.ql index 38b75bda3c..469a7f7f73 100644 --- a/cpp/common/test/deviations/deviation_permits_basic_test/UnusedReturnValue.ql +++ b/cpp/common/test/deviations/deviation_permits_basic_test/UnusedReturnValue.ql @@ -16,7 +16,6 @@ import cpp import codingstandards.cpp.CodingStandards -import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.exclusions.cpp.RuleMetadata /* This is a copy of an AUTOSAR rule, which we are using for testing purposes. */ diff --git a/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.ql b/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.ql index 38b75bda3c..469a7f7f73 100644 --- a/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.ql +++ b/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.ql @@ -16,7 +16,6 @@ import cpp import codingstandards.cpp.CodingStandards -import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.exclusions.cpp.RuleMetadata /* This is a copy of an AUTOSAR rule, which we are using for testing purposes. */ diff --git a/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.ql b/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.ql index 38b75bda3c..469a7f7f73 100644 --- a/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.ql +++ b/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.ql @@ -16,7 +16,6 @@ import cpp import codingstandards.cpp.CodingStandards -import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.exclusions.cpp.RuleMetadata /* This is a copy of an AUTOSAR rule, which we are using for testing purposes. */ From 71570a0ee3720e50d53370790b7174752e9869c1 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Mon, 16 Sep 2024 14:48:15 +0200 Subject: [PATCH 035/370] Fix expected test results after import changes --- ...OfFunctionArgumentsForSideEffects.expected | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected b/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected index 6567ef6fd1..ec791fe3e4 100644 --- a/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected +++ b/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected @@ -1,25 +1,25 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:24,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:24,59-67) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:27,33-41) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:27,57-65) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:31,33-41) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:31,59-67) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:40,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:40,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:40,53-61) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:43,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:43,57-65) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:52,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:52,55-63) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:59,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:59,57-65) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:71,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:71,55-63) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:24,5-18) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:27,7-20) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:31,7-20) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:43,5-18) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:52,5-18) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:59,5-18) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:71,5-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:23,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:23,59-67) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:26,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:26,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:30,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:30,59-67) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:39,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:39,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:39,53-61) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:42,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:42,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:51,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:51,55-63) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:58,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:58,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:70,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:70,55-63) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:23,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:26,7-20) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:30,7-20) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:42,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:51,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:58,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:70,5-18) | test.c:20:3:20:4 | call to f1 | Depending on the order of evaluation for the arguments $@ and $@ for side effects on shared state is unspecified and can result in unexpected behavior. | test.c:20:6:20:7 | call to f2 | call to f2 | test.c:20:12:20:13 | call to f3 | call to f3 | From 3387893fc378ac8b7c670745538ac15eade0372d Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 24 Sep 2024 09:03:08 +0200 Subject: [PATCH 036/370] Adapt to `sourceLocationPrefix` change in `qltest` --- .../cpp/deviations/Deviations.qll | 8 ++++-- .../ListDeviationRecords.expected | 4 +-- .../InvalidDeviationPermits.expected | 4 +-- .../InvalidDeviationRecords.expected | 28 +++++++++---------- ...InvalidGuidelineRecategorizations.expected | 10 +++---- 5 files changed, 28 insertions(+), 26 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll b/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll index 4dfadd12eb..403a5b61c6 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll @@ -365,17 +365,19 @@ class DeviationRecord extends XmlElement { /** Gets a path to which this deviation applies. */ string getADeviationPath() { - ( + exists(string res | if exists(getPathAContainer()) then // Use the path, which will be relative to this file, if specified - result = getPathAContainer().getRelativePath() + res = getPathAContainer().getRelativePath() else ( // Otherwise, if no code identifier was supplied, it applies to the parent container of the // file itself not exists(getCodeIdentifier()) and - result = this.getFile().getParentContainer().getRelativePath() + res = this.getFile().getParentContainer().getRelativePath() ) + | + if res = "" then result = "(root)" else result = res ) } diff --git a/cpp/common/test/deviations/deviations_basic_test/ListDeviationRecords.expected b/cpp/common/test/deviations/deviations_basic_test/ListDeviationRecords.expected index 3a095d8fb9..5115cc8a70 100644 --- a/cpp/common/test/deviations/deviations_basic_test/ListDeviationRecords.expected +++ b/cpp/common/test/deviations/deviations_basic_test/ListDeviationRecords.expected @@ -1,3 +1,3 @@ -| A0-1-1 | cpp/autosar/useless-assignment | Applies to the following file paths: deviations/deviations_basic_test | | This useless assignment is required. | | | -| A0-1-2 | cpp/autosar/unused-return-value | Applies to the following file paths: deviations/deviations_basic_test/nested/nested1,deviations/deviations_basic_test/nested/nested2 | | Unused return value. | | | +| A0-1-1 | cpp/autosar/useless-assignment | Applies to the following file paths: (root) | | This useless assignment is required. | | | +| A0-1-2 | cpp/autosar/unused-return-value | Applies to the following file paths: nested/nested1,nested/nested2 | | Unused return value. | | | | A0-4-2 | cpp/autosar/type-long-double-used | Identified by the use of the code-identifier: a-0-4-2-deviation | | long double is required for interaction with third-party libraries. | | | diff --git a/cpp/common/test/deviations/invalid_deviations/InvalidDeviationPermits.expected b/cpp/common/test/deviations/invalid_deviations/InvalidDeviationPermits.expected index 433dc8a342..609d517c05 100644 --- a/cpp/common/test/deviations/invalid_deviations/InvalidDeviationPermits.expected +++ b/cpp/common/test/deviations/invalid_deviations/InvalidDeviationPermits.expected @@ -1,2 +1,2 @@ -| coding-standards.xml:100:7:103:33 | deviation-permits-entry | deviations/invalid_deviations/coding-standards.xml: Deviation permit does not specify a permit identifier. | -| coding-standards.xml:104:7:107:33 | deviation-permits-entry | deviations/invalid_deviations/coding-standards.xml: Deviation permit specifies unknown property `invalid-property`. | +| coding-standards.xml:100:7:103:33 | deviation-permits-entry | coding-standards.xml: Deviation permit does not specify a permit identifier. | +| coding-standards.xml:104:7:107:33 | deviation-permits-entry | coding-standards.xml: Deviation permit specifies unknown property `invalid-property`. | diff --git a/cpp/common/test/deviations/invalid_deviations/InvalidDeviationRecords.expected b/cpp/common/test/deviations/invalid_deviations/InvalidDeviationRecords.expected index c4f66eeaf5..2cd438c5c6 100644 --- a/cpp/common/test/deviations/invalid_deviations/InvalidDeviationRecords.expected +++ b/cpp/common/test/deviations/invalid_deviations/InvalidDeviationRecords.expected @@ -1,14 +1,14 @@ -| coding-standards.xml:5:7:5:27 | deviations-entry | deviations/invalid_deviations/coding-standards.xml: No rule-id and query-id specified for this deviation record. | -| coding-standards.xml:6:7:8:26 | deviations-entry | deviations/invalid_deviations/coding-standards.xml: The rule-id `bad rule id` for this deviation matches none of the available queries. | -| coding-standards.xml:9:7:11:26 | deviations-entry | deviations/invalid_deviations/coding-standards.xml: A query-id of `bad rule id` is specified for this deviation, but not rule-id is specified. | -| coding-standards.xml:15:7:17:26 | deviations-entry | deviations/invalid_deviations/coding-standards.xml: A query-id of `cpp/autosar/useless-assignment` is specified for this deviation, but not rule-id is specified. | -| coding-standards.xml:22:7:26:26 | deviations-entry | deviations/invalid_deviations/coding-standards.xml: A deviation `raised-by` is specified without providing an `approved-by`. | -| coding-standards.xml:22:7:26:26 | deviations-entry | deviations/invalid_deviations/coding-standards.xml: A deviation `raised-by` is specified without providing both a `name` and `date`. | -| coding-standards.xml:27:7:33:26 | deviations-entry | deviations/invalid_deviations/coding-standards.xml: A deviation `raised-by` is specified without providing an `approved-by`. | -| coding-standards.xml:27:7:33:26 | deviations-entry | deviations/invalid_deviations/coding-standards.xml: A deviation `raised-by` is specified without providing both a `name` and `date`. | -| coding-standards.xml:34:7:41:26 | deviations-entry | deviations/invalid_deviations/coding-standards.xml: A deviation `raised-by` is specified without providing an `approved-by`. | -| coding-standards.xml:42:7:50:26 | deviations-entry | deviations/invalid_deviations/coding-standards.xml: A deviation `approved-by` is specified without providing both a `name` and `date`. | -| coding-standards.xml:51:7:61:26 | deviations-entry | deviations/invalid_deviations/coding-standards.xml: A deviation `approved-by` is specified without providing both a `name` and `date`. | -| coding-standards.xml:74:7:78:26 | deviations-entry | deviations/invalid_deviations/coding-standards.xml: There is no deviation permit with id `non-existing-permit`. | -| coding-standards.xml:79:7:81:26 | deviations-entry | deviations/invalid_deviations/coding-standards.xml: No rule-id and query-id specified for this deviation record. | -| coding-standards.xml:85:7:88:26 | deviations-entry | deviations/invalid_deviations/coding-standards.xml: The deviation is applied to a query with the rule category 'mandatory' that does not permit a deviation. | +| coding-standards.xml:5:7:5:27 | deviations-entry | coding-standards.xml: No rule-id and query-id specified for this deviation record. | +| coding-standards.xml:6:7:8:26 | deviations-entry | coding-standards.xml: The rule-id `bad rule id` for this deviation matches none of the available queries. | +| coding-standards.xml:9:7:11:26 | deviations-entry | coding-standards.xml: A query-id of `bad rule id` is specified for this deviation, but not rule-id is specified. | +| coding-standards.xml:15:7:17:26 | deviations-entry | coding-standards.xml: A query-id of `cpp/autosar/useless-assignment` is specified for this deviation, but not rule-id is specified. | +| coding-standards.xml:22:7:26:26 | deviations-entry | coding-standards.xml: A deviation `raised-by` is specified without providing an `approved-by`. | +| coding-standards.xml:22:7:26:26 | deviations-entry | coding-standards.xml: A deviation `raised-by` is specified without providing both a `name` and `date`. | +| coding-standards.xml:27:7:33:26 | deviations-entry | coding-standards.xml: A deviation `raised-by` is specified without providing an `approved-by`. | +| coding-standards.xml:27:7:33:26 | deviations-entry | coding-standards.xml: A deviation `raised-by` is specified without providing both a `name` and `date`. | +| coding-standards.xml:34:7:41:26 | deviations-entry | coding-standards.xml: A deviation `raised-by` is specified without providing an `approved-by`. | +| coding-standards.xml:42:7:50:26 | deviations-entry | coding-standards.xml: A deviation `approved-by` is specified without providing both a `name` and `date`. | +| coding-standards.xml:51:7:61:26 | deviations-entry | coding-standards.xml: A deviation `approved-by` is specified without providing both a `name` and `date`. | +| coding-standards.xml:74:7:78:26 | deviations-entry | coding-standards.xml: There is no deviation permit with id `non-existing-permit`. | +| coding-standards.xml:79:7:81:26 | deviations-entry | coding-standards.xml: No rule-id and query-id specified for this deviation record. | +| coding-standards.xml:85:7:88:26 | deviations-entry | coding-standards.xml: The deviation is applied to a query with the rule category 'mandatory' that does not permit a deviation. | diff --git a/cpp/common/test/guideline_recategorizations/InvalidGuidelineRecategorizations.expected b/cpp/common/test/guideline_recategorizations/InvalidGuidelineRecategorizations.expected index 971c70a9b6..32a9837e46 100644 --- a/cpp/common/test/guideline_recategorizations/InvalidGuidelineRecategorizations.expected +++ b/cpp/common/test/guideline_recategorizations/InvalidGuidelineRecategorizations.expected @@ -1,5 +1,5 @@ -| invalid/coding-standards.xml:5:7:8:43 | guideline-recategorizations-entry | guideline_recategorizations/invalid/coding-standards.xml: 'Invalid recategorization from 'required' to 'advisory'.' for rule A0-1-1. | -| invalid/coding-standards.xml:9:7:12:43 | guideline-recategorizations-entry | guideline_recategorizations/invalid/coding-standards.xml: 'Invalid recategorization from 'required' to 'disapplied'.' for rule A0-1-2. | -| invalid/coding-standards.xml:13:7:16:43 | guideline-recategorizations-entry | guideline_recategorizations/invalid/coding-standards.xml: 'Unknown rule id 'A1-4-3'.' for rule A1-4-3. | -| invalid/coding-standards.xml:17:7:20:43 | guideline-recategorizations-entry | guideline_recategorizations/invalid/coding-standards.xml: 'Invalid recategorization from 'mandatory' to 'required'.' for rule RULE-13-6. | -| invalid/coding-standards.xml:21:7:24:43 | guideline-recategorizations-entry | guideline_recategorizations/invalid/coding-standards.xml: 'Invalid recategorization from 'rule' to 'required'.' for rule CON50-CPP. | +| invalid/coding-standards.xml:5:7:8:43 | guideline-recategorizations-entry | invalid/coding-standards.xml: 'Invalid recategorization from 'required' to 'advisory'.' for rule A0-1-1. | +| invalid/coding-standards.xml:9:7:12:43 | guideline-recategorizations-entry | invalid/coding-standards.xml: 'Invalid recategorization from 'required' to 'disapplied'.' for rule A0-1-2. | +| invalid/coding-standards.xml:13:7:16:43 | guideline-recategorizations-entry | invalid/coding-standards.xml: 'Unknown rule id 'A1-4-3'.' for rule A1-4-3. | +| invalid/coding-standards.xml:17:7:20:43 | guideline-recategorizations-entry | invalid/coding-standards.xml: 'Invalid recategorization from 'mandatory' to 'required'.' for rule RULE-13-6. | +| invalid/coding-standards.xml:21:7:24:43 | guideline-recategorizations-entry | invalid/coding-standards.xml: 'Invalid recategorization from 'rule' to 'required'.' for rule CON50-CPP. | From 9b1667ed924ca28ad54139ad015ab702fb67aa2f Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 4 Oct 2024 14:38:07 +0200 Subject: [PATCH 037/370] Fix `isDeviated` predicate --- .../cpp/deviations/Deviations.qll | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll b/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll index 403a5b61c6..99b9a33fe6 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll @@ -363,20 +363,23 @@ class DeviationRecord extends XmlElement { result.getRelativePath() = getAChild("paths").getAChild("paths-entry").getTextValue() } + private string getADeviationPath0() { + if exists(getPathAContainer()) + then + // Use the path, which will be relative to this file, if specified + result = getPathAContainer().getRelativePath() + else ( + // Otherwise, if no code identifier was supplied, it applies to the parent container of the + // file itself + not exists(getCodeIdentifier()) and + result = this.getFile().getParentContainer().getRelativePath() + ) + } + /** Gets a path to which this deviation applies. */ string getADeviationPath() { exists(string res | - if exists(getPathAContainer()) - then - // Use the path, which will be relative to this file, if specified - res = getPathAContainer().getRelativePath() - else ( - // Otherwise, if no code identifier was supplied, it applies to the parent container of the - // file itself - not exists(getCodeIdentifier()) and - res = this.getFile().getParentContainer().getRelativePath() - ) - | + res = getADeviationPath0() and if res = "" then result = "(root)" else result = res ) } @@ -384,6 +387,6 @@ class DeviationRecord extends XmlElement { cached predicate isDeviated(Query query, string deviationPath) { query = getQuery() and - deviationPath = getADeviationPath() + deviationPath = getADeviationPath0() } } From cf5dc696022020aa61781dbe03585a285496a96a Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Wed, 16 Oct 2024 11:01:33 +0200 Subject: [PATCH 038/370] Update expected test results after merging `main` --- ...rrayFunctionArgumentNumberOfElements.expected | 12 ++++++------ ...mpUsedToCompareNullTerminatedStrings.expected | 8 ++++---- ...penForReadAndWriteOnDifferentStreams.expected | 2 +- .../AttemptToWriteToAReadOnlyStream.expected | 12 ++++++------ ...BeComparedWithUnmodifiedReturnValues.expected | 16 ++++++++-------- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected b/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected index cb4422f5f1..174c6aa40f 100644 --- a/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected +++ b/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected @@ -1,9 +1,9 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:47,36-44) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:48,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:50,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:55,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:71,28-36) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:71,51-59) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:48,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:49,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:51,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:56,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:72,28-36) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:72,51-59) | test.c:18:6:18:6 | 0 | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter | | test.c:19:6:19:7 | ar | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter | | test.c:21:6:21:9 | ar2p | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter | diff --git a/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected b/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected index cf45b21eb4..5ae49919a9 100644 --- a/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected +++ b/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected @@ -1,7 +1,7 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:22,54-62) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:23,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:49,20-28) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:57,43-56) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:23,54-62) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:24,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:50,20-28) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:58,43-56) edges | test.c:12:13:12:15 | a | test.c:14:10:14:10 | a | provenance | | | test.c:12:13:12:15 | a | test.c:23:13:23:13 | a | provenance | | diff --git a/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected b/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected index 6360b21973..0365f4980d 100644 --- a/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected +++ b/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected @@ -1,4 +1,4 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (FileOpenForReadAndWriteOnDifferentStreams.ql:38,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (FileOpenForReadAndWriteOnDifferentStreams.ql:39,9-17) | test.c:6:14:6:18 | call to fopen | The same file was already opened $@. Files should not be read and written at the same time using different streams. | test.c:5:14:5:18 | call to fopen | here | | test.c:17:14:17:18 | call to fopen | The same file was already opened $@. Files should not be read and written at the same time using different streams. | test.c:16:14:16:18 | call to fopen | here | | test.c:33:14:33:18 | call to fopen | The same file was already opened $@. Files should not be read and written at the same time using different streams. | test.c:32:14:32:18 | call to fopen | here | diff --git a/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected b/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected index 88dca316a2..dbf08e3d3d 100644 --- a/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected +++ b/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected @@ -1,8 +1,8 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:18,32-40) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:19,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:24,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:30,21-29) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:32,6-14) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:35,28-36) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:19,32-40) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:20,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:25,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:31,21-29) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:33,6-14) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:36,28-36) | test.c:10:3:10:9 | call to fprintf | Attempt to write to a $@ opened as read-only. | test.c:9:14:9:18 | call to fopen | stream | | test.c:15:3:15:9 | call to fprintf | Attempt to write to a $@ opened as read-only. | test.c:18:14:18:18 | call to fopen | stream | diff --git a/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected b/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected index a7ee20c0b0..83a10a46fb 100644 --- a/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected +++ b/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected @@ -1,10 +1,10 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:22,28-36) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:23,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:27,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:36,23-31) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:41,17-25) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:50,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:58,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:58,46-54) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:23,28-36) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:24,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:28,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:37,23-31) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:42,17-25) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:51,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:59,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:59,46-54) | test.c:6:7:6:20 | ... != ... | The check is not reliable as the type of the return value of $@ is converted. | test.c:5:14:5:20 | call to getchar | call to getchar | | test.c:13:7:13:15 | ... != ... | The check is not reliable as the type of the return value of $@ is converted. | test.c:12:14:12:20 | call to getchar | call to getchar | From 2778d662e2cf701b351b2466916e9e0f03dd31f8 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Wed, 16 Oct 2024 13:12:54 +0200 Subject: [PATCH 039/370] Update test results after QL library changes --- .../identifierhidden/IdentifierHidden.expected | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/cpp/common/test/rules/identifierhidden/IdentifierHidden.expected b/cpp/common/test/rules/identifierhidden/IdentifierHidden.expected index fd657590ef..47d191d758 100644 --- a/cpp/common/test/rules/identifierhidden/IdentifierHidden.expected +++ b/cpp/common/test/rules/identifierhidden/IdentifierHidden.expected @@ -4,10 +4,21 @@ | test.cpp:23:13:23:15 | id1 | Variable is hiding variable $@. | test.cpp:1:5:1:7 | id1 | id1 | | test.cpp:26:12:26:14 | id1 | Variable is hiding variable $@. | test.cpp:1:5:1:7 | id1 | id1 | | test.cpp:27:14:27:16 | id1 | Variable is hiding variable $@. | test.cpp:26:12:26:14 | id1 | id1 | +| test.cpp:48:11:48:11 | i | Variable is hiding variable $@. | test.cpp:58:16:58:16 | i | i | +| test.cpp:48:11:48:11 | i | Variable is hiding variable $@. | test.cpp:75:16:75:16 | i | i | +| test.cpp:50:9:50:9 | i | Variable is hiding variable $@. | test.cpp:58:16:58:16 | i | i | +| test.cpp:50:9:50:9 | i | Variable is hiding variable $@. | test.cpp:75:16:75:16 | i | i | +| test.cpp:53:12:53:12 | i | Variable is hiding variable $@. | test.cpp:58:16:58:16 | i | i | +| test.cpp:53:12:53:12 | i | Variable is hiding variable $@. | test.cpp:75:16:75:16 | i | i | +| test.cpp:65:11:65:11 | i | Variable is hiding variable $@. | test.cpp:58:16:58:16 | i | i | | test.cpp:65:11:65:11 | i | Variable is hiding variable $@. | test.cpp:61:7:61:7 | i | i | +| test.cpp:65:11:65:11 | i | Variable is hiding variable $@. | test.cpp:75:16:75:16 | i | i | +| test.cpp:67:9:67:9 | i | Variable is hiding variable $@. | test.cpp:58:16:58:16 | i | i | | test.cpp:67:9:67:9 | i | Variable is hiding variable $@. | test.cpp:61:7:61:7 | i | i | +| test.cpp:67:9:67:9 | i | Variable is hiding variable $@. | test.cpp:75:16:75:16 | i | i | +| test.cpp:70:12:70:12 | i | Variable is hiding variable $@. | test.cpp:58:16:58:16 | i | i | | test.cpp:70:12:70:12 | i | Variable is hiding variable $@. | test.cpp:61:7:61:7 | i | i | -| test.cpp:75:16:75:16 | i | Variable is hiding variable $@. | test.cpp:61:7:61:7 | i | i | +| test.cpp:70:12:70:12 | i | Variable is hiding variable $@. | test.cpp:75:16:75:16 | i | i | | test.cpp:86:9:86:9 | b | Variable is hiding variable $@. | test.cpp:80:11:80:11 | b | b | | test.cpp:94:9:94:17 | globalvar | Variable is hiding variable $@. | test.cpp:91:5:91:13 | globalvar | globalvar | | test.cpp:113:11:113:11 | b | Variable is hiding variable $@. | test.cpp:107:13:107:13 | b | b | From 1340cdbcef49a5f7b99fa65370a5fef97e5977db Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 24 Oct 2024 23:23:50 -0700 Subject: [PATCH 040/370] Implement RULE-2-8, project should not contain unused object definitions. Also add a new AlertReporting shared query library for deduplicating results across macro definitions/invocations/etc. Split __attribute__((unused)) variables (and similar) to a Strict pair of queries. --- .../rules/RULE-2-8/UnusedObjectDefinition.ql | 24 ++ .../RULE-2-8/UnusedObjectDefinitionInMacro.ql | 24 ++ .../UnusedObjectDefinitionInMacroStrict.ql | 27 ++ .../RULE-2-8/UnusedObjectDefinitionStrict.ql | 26 ++ .../RULE-2-8/UnusedObjectDefinition.expected | 8 + .../RULE-2-8/UnusedObjectDefinition.qlref | 1 + .../UnusedObjectDefinitionInMacro.expected | 2 + .../UnusedObjectDefinitionInMacro.qlref | 1 + ...usedObjectDefinitionInMacroStrict.expected | 2 + .../UnusedObjectDefinitionInMacroStrict.qlref | 1 + .../UnusedObjectDefinitionStrict.expected | 2 + .../UnusedObjectDefinitionStrict.qlref | 1 + c/misra/test/rules/RULE-2-8/test.c | 113 ++++++ .../codingstandards/cpp/AlertReporting.qll | 28 +- .../DeduplicateMacroResults.qll | 379 ++++++++++++++++++ .../cpp/deadcode/UnusedObjects.qll | 176 ++++++++ .../cpp/exclusions/c/DeadCode2.qll | 78 ++++ .../cpp/exclusions/c/RuleMetadata.qll | 3 + .../DeduplicateMacroResults.expected | 6 + .../alertreporting/DeduplicateMacroResults.ql | 32 ++ .../deduplicatemacroresults.cpp | 53 +++ rule_packages/c/DeadCode2.json | 66 +++ 22 files changed, 1050 insertions(+), 3 deletions(-) create mode 100644 c/misra/src/rules/RULE-2-8/UnusedObjectDefinition.ql create mode 100644 c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacro.ql create mode 100644 c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.ql create mode 100644 c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionStrict.ql create mode 100644 c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected create mode 100644 c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.qlref create mode 100644 c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.expected create mode 100644 c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.qlref create mode 100644 c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.expected create mode 100644 c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.qlref create mode 100644 c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.expected create mode 100644 c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.qlref create mode 100644 c/misra/test/rules/RULE-2-8/test.c create mode 100644 cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll create mode 100644 cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/c/DeadCode2.qll create mode 100644 cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.expected create mode 100644 cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.ql create mode 100644 cpp/common/test/library/codingstandards/cpp/alertreporting/deduplicatemacroresults.cpp create mode 100644 rule_packages/c/DeadCode2.json diff --git a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinition.ql b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinition.ql new file mode 100644 index 0000000000..420733d4ac --- /dev/null +++ b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinition.ql @@ -0,0 +1,24 @@ +/** + * @id c/misra/unused-object-definition + * @name RULE-2-8: A project should not contain unused object definitions + * @description Object definitions which are unused should be removed. + * @kind problem + * @precision very-high + * @problem.severity recommendation + * @tags external/misra/id/rule-2-8 + * maintainability + * performance + * external/misra/c/2012/amendment4 + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.deadcode.UnusedObjects + +from ReportDeadObjectAtDefinition report +where + not isExcluded(report.getPrimaryElement(), DeadCode2Package::unusedObjectDefinitionQuery()) and + not report.hasAttrUnused() +select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocation(), + report.getOptionalPlaceholderMessage() diff --git a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacro.ql b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacro.ql new file mode 100644 index 0000000000..d5c339c157 --- /dev/null +++ b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacro.ql @@ -0,0 +1,24 @@ +/** + * @id c/misra/unused-object-definition-in-macro + * @name RULE-2-8: Project macros should not include unused object definitions + * @description Macros should not have unused object definitions. + * @kind problem + * @precision very-high + * @problem.severity recommendation + * @tags external/misra/id/rule-2-8 + * maintainability + * performance + * external/misra/c/2012/amendment4 + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.deadcode.UnusedObjects + +from ReportDeadObjectInMacro report +where + not isExcluded(report.getPrimaryElement(), DeadCode2Package::unusedObjectDefinitionInMacroQuery()) and + not report.hasAttrUnused() +select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocation(), + report.getOptionalPlaceholderMessage() diff --git a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.ql b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.ql new file mode 100644 index 0000000000..7eead60424 --- /dev/null +++ b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.ql @@ -0,0 +1,27 @@ +/** + * @id c/misra/unused-object-definition-in-macro-strict + * @name RULE-2-8: Project macros should not include '__attribute__((unused))' object definitions + * @description A strict query which reports all unused object definitions in macros with + * '__attribute__((unused))'. + * @kind problem + * @precision very-high + * @problem.severity recommendation + * @tags external/misra/id/rule-2-8 + * maintainability + * performance + * external/misra/c/2012/amendment4 + * external/misra/c/strict + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.deadcode.UnusedObjects + +from ReportDeadObjectInMacro report +where + not isExcluded(report.getPrimaryElement(), + DeadCode2Package::unusedObjectDefinitionInMacroStrictQuery()) and + report.hasAttrUnused() +select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocation(), + report.getOptionalPlaceholderMessage() diff --git a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionStrict.ql b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionStrict.ql new file mode 100644 index 0000000000..ad92c79481 --- /dev/null +++ b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionStrict.ql @@ -0,0 +1,26 @@ +/** + * @id c/misra/unused-object-definition-strict + * @name RULE-2-8: A project should not contain '__attribute__((unused))' object definitions + * @description A strict query which reports all unused object definitions with + * '__attribute__((unused))'. + * @kind problem + * @precision very-high + * @problem.severity recommendation + * @tags external/misra/id/rule-2-8 + * maintainability + * performance + * external/misra/c/2012/amendment4 + * external/misra/c/strict + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.deadcode.UnusedObjects + +from ReportDeadObjectAtDefinition report +where + not isExcluded(report.getPrimaryElement(), DeadCode2Package::unusedObjectDefinitionStrictQuery()) and + report.hasAttrUnused() +select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocation(), + report.getOptionalPlaceholderMessage() diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected new file mode 100644 index 0000000000..fc6f320539 --- /dev/null +++ b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected @@ -0,0 +1,8 @@ +| test.c:6:5:6:6 | definition of g2 | Unused object definition 'g2'. | test.c:6:5:6:6 | test.c:6:5:6:6 | | +| test.c:9:5:9:6 | definition of g3 | Unused object definition 'g3'. | test.c:9:5:9:6 | test.c:9:5:9:6 | | +| test.c:20:7:20:8 | definition of l2 | Unused object definition 'l2'. | test.c:20:7:20:8 | test.c:20:7:20:8 | | +| test.c:27:7:27:8 | definition of l5 | Unused object definition 'l5'. | test.c:27:7:27:8 | test.c:27:7:27:8 | | +| test.c:37:10:37:11 | definition of g5 | Unused object definition 'g5'. | test.c:37:10:37:11 | test.c:37:10:37:11 | | +| test.c:45:9:45:10 | definition of g6 | Unused object definition 'g6'. | test.c:45:9:45:10 | test.c:45:9:45:10 | | +| test.c:51:5:51:6 | definition of g7 | Unused object definition 'g7'. | test.c:51:5:51:6 | test.c:51:5:51:6 | | +| test.c:64:3:64:18 | ONLY_DEF_VAR(x) | Unused object definition 'l2' from macro '$@'. | test.c:60:1:60:34 | test.c:60:1:60:34 | ONLY_DEF_VAR | diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.qlref b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.qlref new file mode 100644 index 0000000000..096c4c64f1 --- /dev/null +++ b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.qlref @@ -0,0 +1 @@ +rules/RULE-2-8/UnusedObjectDefinition.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.expected b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.expected new file mode 100644 index 0000000000..c25c136789 --- /dev/null +++ b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.expected @@ -0,0 +1,2 @@ +| test.c:68:1:71:5 | #define ALSO_DEF_VAR(x) int x = 0; while (1) ; | Macro 'ALSO_DEF_VAR' defines unused object of varied names, for example, '$@'. | test.c:73:16:73:17 | test.c:73:16:73:17 | l1 | +| test.c:77:1:82:3 | #define DEF_UNUSED_INNER_VAR() { int _v = 0; while (1) ; } | Macro 'DEF_UNUSED_INNER_VAR' defines unused object '_v'. | test.c:77:1:82:3 | test.c:77:1:82:3 | (ignored) | diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.qlref b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.qlref new file mode 100644 index 0000000000..057e684fd0 --- /dev/null +++ b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.qlref @@ -0,0 +1 @@ +rules/RULE-2-8/UnusedObjectDefinitionInMacro.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.expected b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.expected new file mode 100644 index 0000000000..2919c65cb7 --- /dev/null +++ b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.expected @@ -0,0 +1,2 @@ +| test.c:94:1:97:5 | #define ALSO_DEF_ATTR_UNUSED_VAR(x) __attribute__((unused)) int x = 0; while (1) ; | Macro 'ALSO_DEF_ATTR_UNUSED_VAR' defines unused object of varied names, for example, '$@'. | test.c:99:28:99:29 | test.c:99:28:99:29 | l1 | +| test.c:104:1:109:3 | #define DEF_ATTR_UNUSED_INNER_VAR() { __attribute__((unused)) int _v = 0; while (1) ; } | Macro 'DEF_ATTR_UNUSED_INNER_VAR' defines unused object '_v'. | test.c:104:1:109:3 | test.c:104:1:109:3 | (ignored) | diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.qlref b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.qlref new file mode 100644 index 0000000000..f04653dcb6 --- /dev/null +++ b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.qlref @@ -0,0 +1 @@ +rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.expected b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.expected new file mode 100644 index 0000000000..624368ac54 --- /dev/null +++ b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.expected @@ -0,0 +1,2 @@ +| test.c:87:29:87:30 | definition of g8 | Unused object definition 'g8'. | test.c:87:29:87:30 | test.c:87:29:87:30 | | +| test.c:90:3:90:30 | ONLY_DEF_ATTR_UNUSED_VAR(x) | Unused object definition 'l2' from macro '$@'. | test.c:88:1:88:70 | test.c:88:1:88:70 | ONLY_DEF_ATTR_UNUSED_VAR | diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.qlref b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.qlref new file mode 100644 index 0000000000..4aa7269881 --- /dev/null +++ b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.qlref @@ -0,0 +1 @@ +rules/RULE-2-8/UnusedObjectDefinitionStrict.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-2-8/test.c b/c/misra/test/rules/RULE-2-8/test.c new file mode 100644 index 0000000000..21a2479163 --- /dev/null +++ b/c/misra/test/rules/RULE-2-8/test.c @@ -0,0 +1,113 @@ +// Not a definition, only a declaration: +extern int g1; // COMPLIANT + +// Both declared + defined: +extern int g2; // COMPLIANT +int g2 = 1; // NON_COMPLIANT + +// Definition is only declaration: +int g3 = 1; // NON_COMPLIANT + +// Definition, but value is required for program to compile: +int g4 = 1; // COMPLIANT +void f1() { g4; } + +// Local variables: +void f2() { + int l1; // COMPLIANT + l1; + + int l2; // NON-COMPLIANT + + // Value is required for the program to compile: + int l3; // COMPLIANT + sizeof(l3); + + int l4, // COMPLIANT + l5; // NON-COMPLIANT + l4; +} + +// Struct fields are not objects: +struct s { + int x; // COMPLIANT +}; + +// Declaration of type struct is an object: +struct s g5; // NON-COMPLIANT + +// Struct fields are not objects: +union u { + int x; // COMPLIANT +}; + +// Declaration of type union is an object: +union u g6; // NON-COMPLIANT + +// Typedefs are not objects: +typedef int td1; // COMPLIANT + +// Declaration of typedef type object: +td1 g7; // NON-COMPLIANT + +// Function parameters are not objects: +void f3(int p) {} // COMPLIANT + +// Function type parameters are not objects: +typedef int td2(int x); // COMPLIANT + +// Macros that define unused vars tests: +#define ONLY_DEF_VAR(x) int x = 0; +void f4() { + ONLY_DEF_VAR(l1); // COMPLIANT + l1; + ONLY_DEF_VAR(l2); // NON-COMPLIANT +} + +// NON-COMPLIANT +#define ALSO_DEF_VAR(x) \ + int x = 0; \ + while (1) \ + ; +void f5() { + ALSO_DEF_VAR(l1); // COMPLIANT + ALSO_DEF_VAR(l2); // COMPLIANT +} + +#define DEF_UNUSED_INNER_VAR() \ + { \ + int _v = 0; \ + while (1) \ + ; \ + } // NON-COMPLIANT +void f6() { + DEF_UNUSED_INNER_VAR(); // COMPLIANT +} + +__attribute__((unused)) int g8 = 1; // NON-COMPLIANT +#define ONLY_DEF_ATTR_UNUSED_VAR(x) __attribute__((unused)) int x = 0; +void f7() { + ONLY_DEF_ATTR_UNUSED_VAR(l2); // NON-COMPLIANT +} + +// NON-COMPLIANT +#define ALSO_DEF_ATTR_UNUSED_VAR(x) \ + __attribute__((unused)) int x = 0; \ + while (1) \ + ; +void f8() { + ALSO_DEF_ATTR_UNUSED_VAR(l1); // COMPLIANT + ALSO_DEF_ATTR_UNUSED_VAR(l2); // COMPLIANT +} + +// NON-COMPLIANT +#define DEF_ATTR_UNUSED_INNER_VAR() \ + { \ + __attribute__((unused)) int _v = 0; \ + while (1) \ + ; \ + } + +void f9() { + DEF_ATTR_UNUSED_INNER_VAR(); // COMPLIANT +} diff --git a/cpp/common/src/codingstandards/cpp/AlertReporting.qll b/cpp/common/src/codingstandards/cpp/AlertReporting.qll index 4259e1b67d..3ef5315906 100644 --- a/cpp/common/src/codingstandards/cpp/AlertReporting.qll +++ b/cpp/common/src/codingstandards/cpp/AlertReporting.qll @@ -18,19 +18,24 @@ module MacroUnwrapper { } /** - * Gets the primary macro that generated the result element. + * Gets the primary macro invocation that generated the result element. */ - Macro getPrimaryMacro(ResultElement re) { + MacroInvocation getPrimaryMacroInvocation(ResultElement re) { exists(MacroInvocation mi | mi = getAMacroInvocation(re) and // No other more specific macro that expands to element not exists(MacroInvocation otherMi | otherMi = getAMacroInvocation(re) and otherMi.getParentInvocation() = mi ) and - result = mi.getMacro() + result = mi ) } + /** + * Gets the primary macro that generated the result element. + */ + Macro getPrimaryMacro(ResultElement re) { result = getPrimaryMacroInvocation(re).getMacro() } + /** * If a result element is expanded from a macro invocation, then return the "primary" macro that * generated the element, otherwise return the element itself. @@ -38,4 +43,21 @@ module MacroUnwrapper { Element unwrapElement(ResultElement re) { if exists(getPrimaryMacro(re)) then result = getPrimaryMacro(re) else result = re } + + /* Final class so we can extend it */ + final private class FinalMacroInvocation = MacroInvocation; + + /* A macro invocation that expands to create a `ResultElement` */ + class ResultMacroExpansion extends FinalMacroInvocation { + ResultElement re; + + ResultMacroExpansion() { re = getAnExpandedElement() } + + ResultElement getResultElement() { result = re } + } + + /* The most specific macro invocation that expands to create this `ResultElement`. */ + class PrimaryMacroExpansion extends ResultMacroExpansion { + PrimaryMacroExpansion() { this = getPrimaryMacroInvocation(re) } + } } diff --git a/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll b/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll new file mode 100644 index 0000000000..7c4e8ef41d --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll @@ -0,0 +1,379 @@ +import codingstandards.cpp.AlertReporting + +/** + * A configuration for deduplicating query results inside of macros. + * + * See doc comment on `DeduplicateMacroResults` module. + */ +signature module DeduplicateMacroConfigSig { + /** + * Stringify the `ResultElement`. All `ResultElement`s that share an "identity" should stringify + * to the same string to get proper results. + */ + string describe(ResultElement re); +} + +/** + * A configuration for generating reports from reports that may or may not be duplicated across + * macro expansions. + * + * See doc comment on `DeduplicateMacroResults` module. + * + * This signature is used to parameterize the module `DeduplicateMacroResults::Report`. + */ +signature module MacroReportConfigSig { + /* Create a message to describe this macro, with a string describing its `ResultElement`. */ + bindingset[description] + string getMessageSameResultInAllExpansions(Macro m, string description); + + /* Create a message to describe this macro, using '$@' to describe an example `ResultElement`. */ + string getMessageVariedResultInAllExpansions(Macro m); + + /* + * Create a message to describe this macro expansion which produces a `ResultElement`, using '$@' + * to describe the relevant macro. + */ + + string getMessageResultInIsolatedExpansion(ResultElement element); +} + +/** + * A module for taking the results of `MacroUnwrapper` and consolidating them. + * + * The module `MacroUnwrapper` is great for simple alerts such as usage of banned functions. In + * such cases, reporting "call to 'foo()' in macro 'M'" will only have one result even if the macro + * is expanded multiple times. + * + * However, other queries may have a dynamic message which can vary per macro call site due to + * token manipulation (`a ## b`), for instance, "Macro 'M' defines unused object 'generated_name_x'" + * which will lead to hundreds of results if there are hundreds of such generated names. + * + * This module can be used to find and easily report non-compliant behavior, grouped by the macro + * it originates in, regardless of whether the messages will exactly match. + * + * ## General Usage + * + * To use this macro, define a class for the relevant behavior, and a means of stringifying + * relevant elements as a config, to parameterize the `DeduplicateMacroResults` module. + * + * ``` + * class InvalidFoo extends Foo { + * InvalidFoo() { ... } + * } + * + * module DeduplicateFooInMacrosConfig implements DeduplicateMacroConfigSig { + * string describe(InvalidFoo foo) { result = ... } + * } + * + * import DeduplicateMacroResults as DeduplicateFooInMacros; + * ``` + * + * This module exposes the following classes: + * - `PrimaryMacroSameResultElementInAllInvocations extends Macro`: Every invocation of this macro + * generates an `InvalidFoo` which stringifies to the same thing. Use the method + * `getResultElementDescription()` to get that shared string. + * - `PrimaryMacroDifferentResultElementInAllInvocations extends Macro`: Every invocation of this + * macro generates an `InvalidFoo`, but they do not all stringify to the same thing. Use the + * method `getExampleResultElement()` to get an *single* example `InvalidFoo` to help users fix + * and understand the issue. + * - `IsolatedMacroExpansionWithResultElement extends MacroInvocation`: An invocation of a macro + * which in this particular instance generates an `InvalidFoo`, while other invocations of the + * same macro do not. + * + * The three above classes all attempt to resolve to the most *specific* macro to the issue at + * hand. For instance, if macro `M1` calls macro `M2` which expands to an `InvalidFoo`, then the + * problem may be with `M2` (it is the most specific macro call here), or the problem may be with + * `M2` (if all expansions of `M2` generate an `InvalidFoo` but not all expansions of `M1` do so). + * + * ## Generating Report Objects + * + * This module also can be used to more easily report issues across these cases, by implementing + * `MacroReportConfigSig` and importing `DeduplicateMacroResults::Report::ReportResultInMacro`. + * + * ``` + * module InvalidFooInMacroReportConfig implements MacroReportConfigSig { + * + * // ***Take care that usage of $@ is correct in the following predicates***!!!! + * bindingset[description] + * string getMessageSameResultInAllExpansions(Macro m, string description) { + * result = "Macro " + m.getName() + " always has invalid foo " + description + * } + * + * string getMessageVariedResultInAllExpansions(Macro m) { + * result = "Macro " + m.getName() + " always has invalid foo, for example '$@'." + * } + * + * string getMessageResultInIsolatedExpansion(InvalidFoo foo) { + * result = "Invocation of macro $@ has invalid foo '" + foo.getName() + "'." + * } + * } + * + * import DeduplicateFooInMacros::Report as Report; + * + * from Report::ReportResultInMacro report + * where not excluded(report.getPrimaryElement(), ...) + * select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocation(), + * report.getOptionalPlaceholderMessage() + * ``` + * + * Note that this does *not* (currently) generate a result for elements not contained by a macro. + * To do report such cases, either add support for that in this module, or write a separate query + * that reports `InvalidFoo` cases where not `.isInMacroExpansion()`. + */ +module DeduplicateMacroResults< + ResultType ResultElement, DeduplicateMacroConfigSig Config> +{ + /* A final class so that we may extend Macro. */ + final private class FinalMacro = Macro; + + /* Helper final class import so that we may reference/extend it. */ + final private class ResultMacroExpansion = MacroUnwrapper::ResultMacroExpansion; + + /** + * A macro for which all of its invocations produce an element that is described the same way. + * + * This is not necessarily the "primary" / most specific macro for these result elements. + * This difference is captured in `PrimarySameResultElementInAllMacroInvocations`, and the two + * classes are only separate to avoid non-monotonic recursion. + */ + private class SameResultElementInAllMacroInvocations extends FinalMacro { + string resultElementDescription; + + SameResultElementInAllMacroInvocations() { + forex(MacroInvocation mi | mi = getAnInvocation() | + Config::describe(mi.(ResultMacroExpansion).getResultElement()) = resultElementDescription + ) + } + + string getResultElementDescription() { result = resultElementDescription } + + ResultElement getAResultElement() { + result = getAnInvocation().(ResultMacroExpansion).getResultElement() + } + } + + /** + * A macro for which all of its invocations produce an element that is described the same way. + * + * This is the necessarily the "primary" / most specific macro for these result elements. + */ + class PrimaryMacroSameResultElementInAllInvocations extends SameResultElementInAllMacroInvocations + { + PrimaryMacroSameResultElementInAllInvocations() { + not exists(MacroInvocation inner | + inner.getParentInvocation() = getAnInvocation() and + inner.getMacro() instanceof SameResultElementInAllMacroInvocations + ) + } + } + + /** + * A expansion that generates a `ResultElement` that is uniquely described by the config. + * + * This is used so that we can find a single example invocation site to report as an example for + * macros which generate an array of different `ResultElement`s that are described differently. + * + * For example, two macro invocations may be given the same arguments, and generate the same + * `ResultElement`, while a third macro invocation is unique and generates a unique + * `ResultElement`. We wish to direct the user to that unique example or we will show the user + * two different reports for one underlying issue. + */ + private class UniqueResultMacroExpansion extends ResultMacroExpansion { + UniqueResultMacroExpansion() { + not exists(ResultMacroExpansion other | + not this = other and + this.getMacroName() = other.getMacroName() and + Config::describe(this.getResultElement()) = Config::describe(other.getResultElement()) + ) + } + } + + /** + * A macro for which all of its invocations produce an element, but they are not all described the + * same way. + * + * This is not necessarily the "primary" / most specific macro for these result elements. + * This difference is captured in `PrimaryDiferentResultElementInAllMacroInvocations`, and the two + * classes are only separate to avoid non-monotonic recursion. + */ + private class DifferentResultElementInAllMacroInvocations extends FinalMacro { + ResultElement exampleResultElement; + + DifferentResultElementInAllMacroInvocations() { + forex(MacroInvocation mi | mi = getAnInvocation() | mi instanceof ResultMacroExpansion) and + count(getAnInvocation().(ResultMacroExpansion).getResultElement()) > 1 and + exists(string description | + description = + rank[1](Config::describe(getAnInvocation().(UniqueResultMacroExpansion).getResultElement()) + ) and + Config::describe(exampleResultElement) = description and + exampleResultElement = getAnInvocation().(ResultMacroExpansion).getResultElement() + ) + } + + ResultElement getExampleResultElement() { result = exampleResultElement } + + ResultElement getAResultElement() { + result = getAnInvocation().(ResultMacroExpansion).getResultElement() + } + } + + /** + * A macro for which all of its invocations produce an element, but they are not all described the + * same way. + * + * This is "primary" / most specific macro for these result elements. + */ + class PrimaryMacroDifferentResultElementInAllInvocations extends DifferentResultElementInAllMacroInvocations + { + PrimaryMacroDifferentResultElementInAllInvocations() { + not exists(MacroInvocation inner | + inner.getParentInvocation() = getAnInvocation() and + inner.getMacro() instanceof DifferentResultElementInAllMacroInvocations + ) + } + } + + /* + * Convenience predicate to know when invalid macro expansions have been reported at their macro + * definition. + */ + + private predicate reported(Macro macro) { + macro instanceof PrimaryMacroSameResultElementInAllInvocations or + macro instanceof PrimaryMacroDifferentResultElementInAllInvocations + } + + /** + * A macro invocation for which the target macro does not always produce a `ResultElement`, but + * this specific invocation of it does. + * + * This is "primary" / most specific macro for these result elements. It will also does not match + * `MacroInvocation`s inside of a `MacroInvocation` of a `Macro` which always produces a + * `ResultElement`, indicating that the real problem lies with that other `Macro` instead of with + * this particular invocation. + */ + class IsolatedMacroExpansionWithResultElement extends ResultMacroExpansion { + IsolatedMacroExpansionWithResultElement() { + not reported(getParentInvocation*().getMacro()) and + not exists(MacroInvocation inner | + reported(inner.getMacro()) and + inner.getParentInvocation*() = this + ) and + not exists(ResultMacroExpansion moreSpecific | + moreSpecific.getResultElement() = getResultElement() and + moreSpecific.getParentInvocation+() = this + ) + } + } + + /** + * A module for generating reports across the various cases of problematic macros, problematic + * macro invocations. + * + * See the doc comment for the `DeduplicateMacroResults` module for more info. + */ + module Report ReportConfig> { + newtype TReportResultInMacro = + TReportMacroResultWithSameName(PrimaryMacroSameResultElementInAllInvocations def) or + TReportMacroResultWithVariedName(PrimaryMacroDifferentResultElementInAllInvocations def) or + TReportIsolatedMacroResult(IsolatedMacroExpansionWithResultElement def) + + /** + * An instance of a `ResultElement` to be reported to a user. + * + * To show a report, use the following methods: + * - `report.getPrimaryElement()` + * - `report.getMessage()` + * - `report.getOptionalPlaceholderLocation()` + * - `report.getOptionalPlaceholderMessage()` + * + * The values returned by these methods are configured by the `MacroReportConfigSig` + * signature parameter. + */ + class ReportResultInMacro extends TReportResultInMacro { + string toString() { result = getMessage() } + + string getMessage() { + exists(PrimaryMacroDifferentResultElementInAllInvocations def | + this = TReportMacroResultWithVariedName(def) and + result = ReportConfig::getMessageVariedResultInAllExpansions(def) + ) + or + exists(PrimaryMacroSameResultElementInAllInvocations def | + this = TReportMacroResultWithSameName(def) and + result = + ReportConfig::getMessageSameResultInAllExpansions(def, def.getResultElementDescription()) + ) + or + exists(IsolatedMacroExpansionWithResultElement def | + this = TReportIsolatedMacroResult(def) and + result = ReportConfig::getMessageResultInIsolatedExpansion(def.getResultElement()) + ) + } + + Element getPrimaryElement() { + this = TReportMacroResultWithSameName(result) + or + this = TReportMacroResultWithVariedName(result) + or + this = TReportIsolatedMacroResult(result) + } + + Location getOptionalPlaceholderLocation() { + exists(PrimaryMacroDifferentResultElementInAllInvocations def | + this = TReportMacroResultWithVariedName(def) and + result = def.getExampleResultElement().getLocation() + ) + or + exists(PrimaryMacroSameResultElementInAllInvocations def | + this = TReportMacroResultWithSameName(def) and + result = def.getLocation() + ) + or + exists(IsolatedMacroExpansionWithResultElement def | + this = TReportIsolatedMacroResult(def) and + result = def.getMacro().getLocation() + ) + } + + string getOptionalPlaceholderMessage() { + exists(PrimaryMacroDifferentResultElementInAllInvocations def | + this = TReportMacroResultWithVariedName(def) and + result = Config::describe(def.getExampleResultElement()) + ) + or + this = TReportMacroResultWithSameName(_) and + result = "(ignored)" + or + this = TReportIsolatedMacroResult(_) and + result = getMacro().getName() + } + + Macro getMacro() { + this = TReportMacroResultWithVariedName(result) + or + this = TReportMacroResultWithSameName(result) + or + exists(IsolatedMacroExpansionWithResultElement def | + this = TReportIsolatedMacroResult(def) and + result = def.getMacro() + ) + } + + ResultMacroExpansion getAResultMacroExpansion() { + exists(PrimaryMacroDifferentResultElementInAllInvocations def | + this = TReportMacroResultWithVariedName(def) and + result = def.getAnInvocation() + ) + or + exists(PrimaryMacroSameResultElementInAllInvocations def | + this = TReportMacroResultWithSameName(def) and + result = def.getAnInvocation() + ) + or + this = TReportIsolatedMacroResult(result) + } + } + } +} diff --git a/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll b/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll new file mode 100644 index 0000000000..70944dfad4 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll @@ -0,0 +1,176 @@ +import cpp +import codingstandards.cpp.alertreporting.HoldsForAllCopies +import codingstandards.cpp.alertreporting.DeduplicateMacroResults + +/** + * An unused object definition is an object, meaning a place in memory, whose definition could be + * removed and the program would still compile. + * + * Technically, parameters may be considered objects, but they are covered by their own rule. + * Similarly, members of structs are an addressable place in memory, and may be considered objects. + * However, the member declaration is nothing but a layout offset, which is not an object. + * + * This therefore only reports variables (local or top level) which have a definition, and are + * unused. + */ +class UnusedObjectDefinition extends VariableDeclarationEntry { + UnusedObjectDefinition() { + not exists(VariableAccess access | access.getTarget() = getVariable()) and + getVariable().getDefinition() = this and + not this instanceof ParameterDeclarationEntry and + not getVariable() instanceof MemberVariable + } + + /* Dead objects with these attributes are reported in the "strict" queries. */ + predicate hasAttrUnused() { + getVariable().getAnAttribute().hasName(["unused", "used", "maybe_unused", "cleanup"]) + } +} + +/* Configuration to use the `DedupMacroResults` module to reduce alert noise */ +module UnusedObjectDefinitionDedupeConfig implements + DeduplicateMacroConfigSig +{ + string describe(UnusedObjectDefinition def) { result = def.getName() } +} + +import DeduplicateMacroResults as DeduplicateUnusedMacroObjects + +/** + * A macro invocation that only defines one unused variable. + * + * These are reported at the invocation site when the variable is unused. + */ +class MacroExpansionWithOnlyUnusedObjectDefinition extends MacroInvocation { + UnusedObjectDefinition unusedObject; + + MacroExpansionWithOnlyUnusedObjectDefinition() { + exists(DeclStmt stmt, Declaration decl | + stmt = getStmt() and + count(getStmt()) = 1 and + count(stmt.getADeclaration()) = 1 and + decl = stmt.getADeclaration() and + count(decl.getADeclarationEntry()) = 1 and + unusedObject = decl.getADeclarationEntry() + ) and + not exists(this.getParentInvocation()) + } + + UnusedObjectDefinition getUnusedObject() { result = unusedObject } +} + +/** + * An object definition which is not from a macro, and for which all copies are unused. + * + * Extends the `HoldForAllCopies::LogicalResultElement` class, because these dead objects are often + * duplicated across defines and sometimes aren't marked used due to extractor bugs. + */ +class SimpleDeadObjectDefinition extends HoldsForAllCopies::LogicalResultElement +{ + SimpleDeadObjectDefinition() { not getAnElementInstance().isInMacroExpansion() } + + string getName() { result = getAnElementInstance().getName() } +} + +/* Make a type for reporting these two results in one query */ +newtype TReportDeadObjectAtDefinition = + TSimpleDeadObjectDefinition(SimpleDeadObjectDefinition def) or + TMacroExpansionWithOnlyUnusedObject(MacroExpansionWithOnlyUnusedObjectDefinition def) + +/** + * Class to report simple dead object definitions, and dead objects from macros that do nothing but + * define an object. + * + * To report all cases, make sure to also use the `DeduplicateUnusedMacroObjects::Report` module. + * + * To report these cases, use the methods: + * - `getMessage()` + * - `getPrimaryElement()`, + * - `getOptionalPlaceholderLocation()` + * - `getOptionalPlaceholderMessage()` + */ +class ReportDeadObjectAtDefinition extends TReportDeadObjectAtDefinition { + string toString() { result = getMessage() } + + string getMessage() { + exists(MacroExpansionWithOnlyUnusedObjectDefinition def | + this = TMacroExpansionWithOnlyUnusedObject(def) and + result = "Unused object definition '" + def.getUnusedObject().getName() + "' from macro '$@'." + ) + or + exists(SimpleDeadObjectDefinition def | + this = TSimpleDeadObjectDefinition(def) and + result = "Unused object definition '" + def.getName() + "'." + ) + } + + predicate hasAttrUnused() { + exists(MacroExpansionWithOnlyUnusedObjectDefinition def | + this = TMacroExpansionWithOnlyUnusedObject(def) and + def.getUnusedObject().hasAttrUnused() + ) + or + exists(SimpleDeadObjectDefinition def | + this = TSimpleDeadObjectDefinition(def) and + def.getAnElementInstance().hasAttrUnused() + ) + } + + Element getPrimaryElement() { + this = TMacroExpansionWithOnlyUnusedObject(result) + or + exists(SimpleDeadObjectDefinition def | + this = TSimpleDeadObjectDefinition(def) and + result = def.getAnElementInstance() + ) + } + + Location getOptionalPlaceholderLocation() { + exists(MacroExpansionWithOnlyUnusedObjectDefinition def | + this = TMacroExpansionWithOnlyUnusedObject(def) and + result = def.getMacro().getLocation() + ) + or + exists(SimpleDeadObjectDefinition def | + this = TSimpleDeadObjectDefinition(def) and + result = def.getAnElementInstance().getLocation() + ) + } + + string getOptionalPlaceholderMessage() { + exists(MacroExpansionWithOnlyUnusedObjectDefinition def | + this = TMacroExpansionWithOnlyUnusedObject(def) and + result = def.getMacroName() + ) + or + this = TSimpleDeadObjectDefinition(_) and + result = "" + } +} + +/* Module config to use the `DeduplicateUnusedMacroObjects::Report` module */ +module ReportDeadObjectInMacroConfig implements MacroReportConfigSig { + bindingset[description] + string getMessageSameResultInAllExpansions(Macro m, string description) { + result = "Macro '" + m.getName() + "' defines unused object '" + description + "'." + } + + string getMessageVariedResultInAllExpansions(Macro m) { + result = "Macro '" + m.getName() + "' defines unused object of varied names, for example, '$@'." + } + + string getMessageResultInIsolatedExpansion(UnusedObjectDefinition unused) { + result = "Invocation of macro '$@' defines unused object '" + unused.getName() + "'." + } +} + +/* The object to report in queries of dead objects used in macros */ +class ReportDeadObjectInMacro extends DeduplicateUnusedMacroObjects::Report::ReportResultInMacro +{ + ReportDeadObjectInMacro() { + // `MacroExpansionWithOnlyUnusedObjectDefinition` is reported by class `ReportDeadObjectAtDefinition` + not getAResultMacroExpansion() instanceof MacroExpansionWithOnlyUnusedObjectDefinition + } + + predicate hasAttrUnused() { getAResultMacroExpansion().getResultElement().hasAttrUnused() } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/DeadCode2.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/DeadCode2.qll new file mode 100644 index 0000000000..8f8edc03fa --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/DeadCode2.qll @@ -0,0 +1,78 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype DeadCode2Query = + TUnusedObjectDefinitionQuery() or + TUnusedObjectDefinitionInMacroQuery() or + TUnusedObjectDefinitionStrictQuery() or + TUnusedObjectDefinitionInMacroStrictQuery() + +predicate isDeadCode2QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `unusedObjectDefinition` query + DeadCode2Package::unusedObjectDefinitionQuery() and + queryId = + // `@id` for the `unusedObjectDefinition` query + "c/misra/unused-object-definition" and + ruleId = "RULE-2-8" and + category = "advisory" + or + query = + // `Query` instance for the `unusedObjectDefinitionInMacro` query + DeadCode2Package::unusedObjectDefinitionInMacroQuery() and + queryId = + // `@id` for the `unusedObjectDefinitionInMacro` query + "c/misra/unused-object-definition-in-macro" and + ruleId = "RULE-2-8" and + category = "advisory" + or + query = + // `Query` instance for the `unusedObjectDefinitionStrict` query + DeadCode2Package::unusedObjectDefinitionStrictQuery() and + queryId = + // `@id` for the `unusedObjectDefinitionStrict` query + "c/misra/unused-object-definition-strict" and + ruleId = "RULE-2-8" and + category = "advisory" + or + query = + // `Query` instance for the `unusedObjectDefinitionInMacroStrict` query + DeadCode2Package::unusedObjectDefinitionInMacroStrictQuery() and + queryId = + // `@id` for the `unusedObjectDefinitionInMacroStrict` query + "c/misra/unused-object-definition-in-macro-strict" and + ruleId = "RULE-2-8" and + category = "advisory" +} + +module DeadCode2Package { + Query unusedObjectDefinitionQuery() { + //autogenerate `Query` type + result = + // `Query` type for `unusedObjectDefinition` query + TQueryC(TDeadCode2PackageQuery(TUnusedObjectDefinitionQuery())) + } + + Query unusedObjectDefinitionInMacroQuery() { + //autogenerate `Query` type + result = + // `Query` type for `unusedObjectDefinitionInMacro` query + TQueryC(TDeadCode2PackageQuery(TUnusedObjectDefinitionInMacroQuery())) + } + + Query unusedObjectDefinitionStrictQuery() { + //autogenerate `Query` type + result = + // `Query` type for `unusedObjectDefinitionStrict` query + TQueryC(TDeadCode2PackageQuery(TUnusedObjectDefinitionStrictQuery())) + } + + Query unusedObjectDefinitionInMacroStrictQuery() { + //autogenerate `Query` type + result = + // `Query` type for `unusedObjectDefinitionInMacroStrict` query + TQueryC(TDeadCode2PackageQuery(TUnusedObjectDefinitionInMacroStrictQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index 3833533d50..75aad6f02c 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -19,6 +19,7 @@ import Contracts5 import Contracts6 import Contracts7 import DeadCode +import DeadCode2 import Declarations1 import Declarations2 import Declarations3 @@ -95,6 +96,7 @@ newtype TCQuery = TContracts6PackageQuery(Contracts6Query q) or TContracts7PackageQuery(Contracts7Query q) or TDeadCodePackageQuery(DeadCodeQuery q) or + TDeadCode2PackageQuery(DeadCode2Query q) or TDeclarations1PackageQuery(Declarations1Query q) or TDeclarations2PackageQuery(Declarations2Query q) or TDeclarations3PackageQuery(Declarations3Query q) or @@ -171,6 +173,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isContracts6QueryMetadata(query, queryId, ruleId, category) or isContracts7QueryMetadata(query, queryId, ruleId, category) or isDeadCodeQueryMetadata(query, queryId, ruleId, category) or + isDeadCode2QueryMetadata(query, queryId, ruleId, category) or isDeclarations1QueryMetadata(query, queryId, ruleId, category) or isDeclarations2QueryMetadata(query, queryId, ruleId, category) or isDeclarations3QueryMetadata(query, queryId, ruleId, category) or diff --git a/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.expected b/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.expected new file mode 100644 index 0000000000..eb55b83924 --- /dev/null +++ b/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.expected @@ -0,0 +1,6 @@ +| deduplicatemacroresults.cpp:10:1:10:34 | SOMETIMES_HAS_RESULTS1(type,name) | Invocation of macro $@ has findme var 'g3'. | deduplicatemacroresults.cpp:6:1:6:52 | deduplicatemacroresults.cpp:6:1:6:52 | SOMETIMES_HAS_RESULTS1 | +| deduplicatemacroresults.cpp:13:1:13:34 | SOMETIMES_HAS_RESULTS2(type,name) | Invocation of macro $@ has findme var 'g5'. | deduplicatemacroresults.cpp:7:1:7:53 | deduplicatemacroresults.cpp:7:1:7:53 | SOMETIMES_HAS_RESULTS2 | +| deduplicatemacroresults.cpp:15:1:15:50 | #define ALWAYS_HAS_SAME_RESULT() extern findme g6; | Macro ALWAYS_HAS_SAME_RESULT always has findme var named g6 | deduplicatemacroresults.cpp:15:1:15:50 | deduplicatemacroresults.cpp:15:1:15:50 | (ignored) | +| deduplicatemacroresults.cpp:21:1:21:70 | #define ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(name) extern findme name; | Macro ALWAYS_HAS_RESULT_VARIED_DESCRIPTION always has findme var, for example '$@'. | deduplicatemacroresults.cpp:23:38:23:39 | deduplicatemacroresults.cpp:23:38:23:39 | g7 | +| deduplicatemacroresults.cpp:30:1:31:50 | #define OUTER_ALWAYS_HAS_SAME_RESULT() extern INNER_SOMETIMES_HAS_RESULTS(findme, g10); | Macro OUTER_ALWAYS_HAS_SAME_RESULT always has findme var named g10 | deduplicatemacroresults.cpp:30:1:31:50 | deduplicatemacroresults.cpp:30:1:31:50 | (ignored) | +| deduplicatemacroresults.cpp:37:1:38:52 | #define OUTER_ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(name) INNER_SOMETIMES_HAS_RESULTS(findme, name ## suffix); | Macro OUTER_ALWAYS_HAS_RESULT_VARIED_DESCRIPTION always has findme var, for example '$@'. | deduplicatemacroresults.cpp:40:44:40:47 | deduplicatemacroresults.cpp:40:44:40:47 | g11suffix | diff --git a/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.ql b/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.ql new file mode 100644 index 0000000000..cd999d72c9 --- /dev/null +++ b/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.ql @@ -0,0 +1,32 @@ +import cpp +import codingstandards.cpp.alertreporting.DeduplicateMacroResults + +class FindMe extends VariableDeclarationEntry { + FindMe() { getType().toString() = "findme" } +} + +module FindMeDedupeConfig implements DeduplicateMacroConfigSig { + string describe(FindMe def) { result = def.getName() } +} + +module FindMeReportConfig implements MacroReportConfigSig { + bindingset[description] + string getMessageSameResultInAllExpansions(Macro m, string description) { + result = "Macro " + m.getName() + " always has findme var named " + description + } + + string getMessageVariedResultInAllExpansions(Macro m) { + result = "Macro " + m.getName() + " always has findme var, for example '$@'." + } + + string getMessageResultInIsolatedExpansion(FindMe f) { + result = "Invocation of macro $@ has findme var '" + f.getName() + "'." + } +} + +import DeduplicateMacroResults +import DeduplicateMacroResults::Report + +from ReportResultInMacro report +select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocation(), + report.getOptionalPlaceholderMessage() diff --git a/cpp/common/test/library/codingstandards/cpp/alertreporting/deduplicatemacroresults.cpp b/cpp/common/test/library/codingstandards/cpp/alertreporting/deduplicatemacroresults.cpp new file mode 100644 index 0000000000..3c5d8bca5b --- /dev/null +++ b/cpp/common/test/library/codingstandards/cpp/alertreporting/deduplicatemacroresults.cpp @@ -0,0 +1,53 @@ +typedef struct { +} findme; + +findme g1; // ignore -- not in a macro + +#define SOMETIMES_HAS_RESULTS1(type, name) type name // ignore +#define SOMETIMES_HAS_RESULTS2(type, name) type name; // ignore + +SOMETIMES_HAS_RESULTS1(int, g2); // ignore +SOMETIMES_HAS_RESULTS1(findme, g3); // RESULT + +SOMETIMES_HAS_RESULTS2(int, g4) // ignore +SOMETIMES_HAS_RESULTS2(findme, g5) // RESULT + +#define ALWAYS_HAS_SAME_RESULT() extern findme g6; // RESULT + +ALWAYS_HAS_SAME_RESULT() // ignore +ALWAYS_HAS_SAME_RESULT() // ignore +ALWAYS_HAS_SAME_RESULT() // ignore + +#define ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(name) extern findme name; // RESULT + +ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(g7) // ignore +ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(g8) // ignore +ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(g9) // ignore +ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(g9) // ignore +ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(g9) // ignore + +#define INNER_SOMETIMES_HAS_RESULTS(type, name) type name; // ignore +#define OUTER_ALWAYS_HAS_SAME_RESULT() \ + extern INNER_SOMETIMES_HAS_RESULTS(findme, g10); // RESULT + +OUTER_ALWAYS_HAS_SAME_RESULT() // ignore +OUTER_ALWAYS_HAS_SAME_RESULT() // ignore + +// 'name ## suffix' required to work around extractor bug. +#define OUTER_ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(name) \ + INNER_SOMETIMES_HAS_RESULTS(findme, name##suffix); // RESULT + +OUTER_ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(g11) // ignore +OUTER_ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(g12) // ignore + +#define OUTER_OUTER_ALWAYS_HAS_SAME_RESULT() \ + OUTER_ALWAYS_HAS_SAME_RESULT(); // ignore +OUTER_OUTER_ALWAYS_HAS_SAME_RESULT() // ignore +OUTER_OUTER_ALWAYS_HAS_SAME_RESULT() // ignore + +// 'name ## suffix' required to work around extractor bug. +#define OUTER_OUTER_ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(name) \ + OUTER_ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(name##suffix); // ignore + +OUTER_OUTER_ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(g13) // ignore +OUTER_OUTER_ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(g14) // ignore \ No newline at end of file diff --git a/rule_packages/c/DeadCode2.json b/rule_packages/c/DeadCode2.json new file mode 100644 index 0000000000..da114a2349 --- /dev/null +++ b/rule_packages/c/DeadCode2.json @@ -0,0 +1,66 @@ +{ + "MISRA-C-2012": { + "RULE-2-8": { + "properties": { + "obligation": "advisory" + }, + "queries": [ + { + "description": "Object definitions which are unused should be removed.", + "kind": "problem", + "name": "A project should not contain unused object definitions", + "precision": "very-high", + "severity": "recommendation", + "short_name": "UnusedObjectDefinition", + "tags": [ + "maintainability", + "performance", + "external/misra/c/2012/amendment4" + ] + }, + { + "description": "Macros should not have unused object definitions.", + "kind": "problem", + "name": "Project macros should not include unused object definitions", + "precision": "very-high", + "severity": "recommendation", + "short_name": "UnusedObjectDefinitionInMacro", + "tags": [ + "maintainability", + "performance", + "external/misra/c/2012/amendment4" + ] + }, + { + "description": "A strict query which reports all unused object definitions with '__attribute__((unused))'.", + "kind": "problem", + "name": "A project should not contain '__attribute__((unused))' object definitions", + "precision": "very-high", + "severity": "recommendation", + "short_name": "UnusedObjectDefinitionStrict", + "tags": [ + "maintainability", + "performance", + "external/misra/c/2012/amendment4", + "external/misra/c/strict" + ] + }, + { + "description": "A strict query which reports all unused object definitions in macros with '__attribute__((unused))'.", + "kind": "problem", + "name": "Project macros should not include '__attribute__((unused))' object definitions", + "precision": "very-high", + "severity": "recommendation", + "short_name": "UnusedObjectDefinitionInMacroStrict", + "tags": [ + "maintainability", + "performance", + "external/misra/c/2012/amendment4", + "external/misra/c/strict" + ] + } + ], + "title": "A project should not contain unused object definitions" + } + } +} \ No newline at end of file From ff562f9e93d803242cc0a8413277daad64f3d376 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 24 Oct 2024 23:31:58 -0700 Subject: [PATCH 041/370] Fix strict misra tag in rules schema --- schemas/rule-package.schema.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/schemas/rule-package.schema.json b/schemas/rule-package.schema.json index b27815163e..b27136634f 100644 --- a/schemas/rule-package.schema.json +++ b/schemas/rule-package.schema.json @@ -342,7 +342,8 @@ "external/misra/c/2012/third-edition-first-revision", "external/misra/c/2012/amendment2", "external/misra/c/2012/amendment3", - "external/misra/c/2012/amendment4" + "external/misra/c/2012/amendment4", + "external/misra/c/strict" ] }, "minLength": 1 From 8f81b4e7dcef93295bb1f486f12cdb4bf2bc9a03 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 27 Oct 2024 14:50:03 +0000 Subject: [PATCH 042/370] EssentialTypes: Correct handling of bitwise binary expressions They shouldn't have the standard type if either both the operands are signed or they are both unsigned. --- .../c/misra/EssentialTypes.qll | 49 +++- c/misra/test/c/misra/EssentialTypes.expected | 275 ++++++++++++++++++ c/misra/test/c/misra/test.c | 80 +++++ 3 files changed, 402 insertions(+), 2 deletions(-) diff --git a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll index 4783547ed2..4dbe8dbb34 100644 --- a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll +++ b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll @@ -192,8 +192,8 @@ class EssentialEqualityOperationExpr extends EssentialExpr, EqualityOperation { override Type getEssentialType() { result instanceof BoolType } } -class EssentialBinaryBitwiseOperationExpr extends EssentialExpr, BinaryBitwiseOperation { - EssentialBinaryBitwiseOperationExpr() { +class EssentialShiftOperationExpr extends EssentialExpr, BinaryBitwiseOperation { + EssentialShiftOperationExpr() { this instanceof LShiftExpr or this instanceof RShiftExpr } @@ -353,6 +353,51 @@ class EssentialBinaryArithmeticExpr extends EssentialExpr, BinaryArithmeticOpera } } +class EssentialBinaryBitwiseExpr extends EssentialExpr, BinaryBitwiseOperation { + EssentialBinaryBitwiseExpr() { + not this instanceof LShiftExpr and + not this instanceof RShiftExpr + } + + override Type getEssentialType() { + exists( + Type leftEssentialType, Type rightEssentialType, + EssentialTypeCategory leftEssentialTypeCategory, + EssentialTypeCategory rightEssentialTypeCategory + | + leftEssentialType = getEssentialType(getLeftOperand()) and + rightEssentialType = getEssentialType(getRightOperand()) and + leftEssentialTypeCategory = getEssentialTypeCategory(leftEssentialType) and + rightEssentialTypeCategory = getEssentialTypeCategory(rightEssentialType) + | + if + leftEssentialTypeCategory = EssentiallySignedType() and + rightEssentialTypeCategory = EssentiallySignedType() + then + if exists(getValue()) + then result = stlr(this) + else ( + if leftEssentialType.getSize() > rightEssentialType.getSize() + then result = leftEssentialType + else result = rightEssentialType + ) + else + if + leftEssentialTypeCategory = EssentiallyUnsignedType() and + rightEssentialTypeCategory = EssentiallyUnsignedType() + then + if exists(getValue()) + then result = utlr(this) + else ( + if leftEssentialType.getSize() > rightEssentialType.getSize() + then result = leftEssentialType + else result = rightEssentialType + ) + else result = this.getStandardType() + ) + } +} + /** * A named Enum type, as per D.5. */ diff --git a/c/misra/test/c/misra/EssentialTypes.expected b/c/misra/test/c/misra/EssentialTypes.expected index c0e010b8e4..19a7090fe9 100644 --- a/c/misra/test/c/misra/EssentialTypes.expected +++ b/c/misra/test/c/misra/EssentialTypes.expected @@ -90,3 +90,278 @@ | test.c:79:3:79:5 | 97 | char | char | essentially Character type | | test.c:80:3:80:6 | 10 | char | char | essentially Character type | | test.c:81:3:81:6 | 0 | char | char | essentially Character type | +| test.c:87:16:87:16 | 0 | signed char | signed char | essentially Signed type | +| test.c:87:16:87:16 | (uint8_t)... | uint8_t | uint8_t | essentially Unsigned type | +| test.c:88:18:88:18 | 0 | signed char | signed char | essentially Signed type | +| test.c:88:18:88:18 | (uint16_t)... | uint16_t | uint16_t | essentially Unsigned type | +| test.c:89:18:89:18 | 0 | signed char | signed char | essentially Signed type | +| test.c:89:18:89:18 | (uint32_t)... | uint32_t | uint32_t | essentially Unsigned type | +| test.c:90:15:90:15 | 0 | signed char | signed char | essentially Signed type | +| test.c:90:15:90:15 | (int8_t)... | int8_t | int8_t | essentially Signed type | +| test.c:91:17:91:17 | 0 | signed char | signed char | essentially Signed type | +| test.c:91:17:91:17 | (int16_t)... | int16_t | int16_t | essentially Signed type | +| test.c:92:16:92:17 | 0 | signed char | signed char | essentially Signed type | +| test.c:94:3:94:4 | (int)... | int | int | essentially Signed type | +| test.c:94:3:94:4 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:94:3:94:9 | ... & ... | uint8_t | uint8_t | essentially Unsigned type | +| test.c:94:8:94:9 | (int)... | int | int | essentially Signed type | +| test.c:94:8:94:9 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:95:3:95:5 | (int)... | int | int | essentially Signed type | +| test.c:95:3:95:5 | u16 | uint16_t | uint16_t | essentially Unsigned type | +| test.c:95:3:95:10 | ... & ... | uint16_t | uint16_t | essentially Unsigned type | +| test.c:95:9:95:10 | (int)... | int | int | essentially Signed type | +| test.c:95:9:95:10 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:96:3:96:4 | (int)... | int | int | essentially Signed type | +| test.c:96:3:96:4 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:96:3:96:10 | ... & ... | uint16_t | uint16_t | essentially Unsigned type | +| test.c:96:8:96:10 | (int)... | int | int | essentially Signed type | +| test.c:96:8:96:10 | u16 | uint16_t | uint16_t | essentially Unsigned type | +| test.c:97:3:97:5 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:97:3:97:10 | ... & ... | uint32_t | uint32_t | essentially Unsigned type | +| test.c:97:9:97:10 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:97:9:97:10 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:98:3:98:4 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:98:3:98:4 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:98:3:98:10 | ... & ... | uint32_t | uint32_t | essentially Unsigned type | +| test.c:98:8:98:10 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:99:3:99:5 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:99:3:99:11 | ... & ... | uint32_t | uint32_t | essentially Unsigned type | +| test.c:99:9:99:11 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:99:9:99:11 | u16 | uint16_t | uint16_t | essentially Unsigned type | +| test.c:100:3:100:5 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:100:3:100:5 | u16 | uint16_t | uint16_t | essentially Unsigned type | +| test.c:100:3:100:11 | ... & ... | uint32_t | uint32_t | essentially Unsigned type | +| test.c:100:9:100:11 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:102:3:102:4 | (int)... | int | int | essentially Signed type | +| test.c:102:3:102:4 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:102:3:102:9 | ... \| ... | uint8_t | uint8_t | essentially Unsigned type | +| test.c:102:8:102:9 | (int)... | int | int | essentially Signed type | +| test.c:102:8:102:9 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:103:3:103:5 | (int)... | int | int | essentially Signed type | +| test.c:103:3:103:5 | u16 | uint16_t | uint16_t | essentially Unsigned type | +| test.c:103:3:103:10 | ... \| ... | uint16_t | uint16_t | essentially Unsigned type | +| test.c:103:9:103:10 | (int)... | int | int | essentially Signed type | +| test.c:103:9:103:10 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:104:3:104:4 | (int)... | int | int | essentially Signed type | +| test.c:104:3:104:4 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:104:3:104:10 | ... \| ... | uint16_t | uint16_t | essentially Unsigned type | +| test.c:104:8:104:10 | (int)... | int | int | essentially Signed type | +| test.c:104:8:104:10 | u16 | uint16_t | uint16_t | essentially Unsigned type | +| test.c:105:3:105:5 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:105:3:105:10 | ... \| ... | uint32_t | uint32_t | essentially Unsigned type | +| test.c:105:9:105:10 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:105:9:105:10 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:106:3:106:4 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:106:3:106:4 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:106:3:106:10 | ... \| ... | uint32_t | uint32_t | essentially Unsigned type | +| test.c:106:8:106:10 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:107:3:107:5 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:107:3:107:11 | ... \| ... | uint32_t | uint32_t | essentially Unsigned type | +| test.c:107:9:107:11 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:107:9:107:11 | u16 | uint16_t | uint16_t | essentially Unsigned type | +| test.c:108:3:108:5 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:108:3:108:5 | u16 | uint16_t | uint16_t | essentially Unsigned type | +| test.c:108:3:108:11 | ... \| ... | uint32_t | uint32_t | essentially Unsigned type | +| test.c:108:9:108:11 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:110:3:110:4 | (int)... | int | int | essentially Signed type | +| test.c:110:3:110:4 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:110:3:110:9 | ... ^ ... | uint8_t | uint8_t | essentially Unsigned type | +| test.c:110:8:110:9 | (int)... | int | int | essentially Signed type | +| test.c:110:8:110:9 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:111:3:111:5 | (int)... | int | int | essentially Signed type | +| test.c:111:3:111:5 | u16 | uint16_t | uint16_t | essentially Unsigned type | +| test.c:111:3:111:10 | ... ^ ... | uint16_t | uint16_t | essentially Unsigned type | +| test.c:111:9:111:10 | (int)... | int | int | essentially Signed type | +| test.c:111:9:111:10 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:112:3:112:4 | (int)... | int | int | essentially Signed type | +| test.c:112:3:112:4 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:112:3:112:10 | ... ^ ... | uint16_t | uint16_t | essentially Unsigned type | +| test.c:112:8:112:10 | (int)... | int | int | essentially Signed type | +| test.c:112:8:112:10 | u16 | uint16_t | uint16_t | essentially Unsigned type | +| test.c:113:3:113:5 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:113:3:113:10 | ... ^ ... | uint32_t | uint32_t | essentially Unsigned type | +| test.c:113:9:113:10 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:113:9:113:10 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:114:3:114:4 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:114:3:114:4 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:114:3:114:10 | ... ^ ... | uint32_t | uint32_t | essentially Unsigned type | +| test.c:114:8:114:10 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:115:3:115:5 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:115:3:115:11 | ... ^ ... | uint32_t | uint32_t | essentially Unsigned type | +| test.c:115:9:115:11 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:115:9:115:11 | u16 | uint16_t | uint16_t | essentially Unsigned type | +| test.c:116:3:116:5 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:116:3:116:5 | u16 | uint16_t | uint16_t | essentially Unsigned type | +| test.c:116:3:116:11 | ... ^ ... | uint32_t | uint32_t | essentially Unsigned type | +| test.c:116:9:116:11 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:118:3:118:4 | (int)... | int | int | essentially Signed type | +| test.c:118:3:118:4 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:118:3:118:9 | ... & ... | int8_t | int8_t | essentially Signed type | +| test.c:118:8:118:9 | (int)... | int | int | essentially Signed type | +| test.c:118:8:118:9 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:119:3:119:5 | (int)... | int | int | essentially Signed type | +| test.c:119:3:119:5 | s16 | int16_t | int16_t | essentially Signed type | +| test.c:119:3:119:10 | ... & ... | int16_t | int16_t | essentially Signed type | +| test.c:119:9:119:10 | (int)... | int | int | essentially Signed type | +| test.c:119:9:119:10 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:120:3:120:4 | (int)... | int | int | essentially Signed type | +| test.c:120:3:120:4 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:120:3:120:10 | ... & ... | int16_t | int16_t | essentially Signed type | +| test.c:120:8:120:10 | (int)... | int | int | essentially Signed type | +| test.c:120:8:120:10 | s16 | int16_t | int16_t | essentially Signed type | +| test.c:121:3:121:5 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:121:3:121:10 | ... & ... | int32_t | int32_t | essentially Signed type | +| test.c:121:9:121:10 | (int)... | int | int | essentially Signed type | +| test.c:121:9:121:10 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:122:3:122:4 | (int)... | int | int | essentially Signed type | +| test.c:122:3:122:4 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:122:3:122:10 | ... & ... | int32_t | int32_t | essentially Signed type | +| test.c:122:8:122:10 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:123:3:123:5 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:123:3:123:11 | ... & ... | int32_t | int32_t | essentially Signed type | +| test.c:123:9:123:11 | (int)... | int | int | essentially Signed type | +| test.c:123:9:123:11 | s16 | int16_t | int16_t | essentially Signed type | +| test.c:124:3:124:5 | (int)... | int | int | essentially Signed type | +| test.c:124:3:124:5 | s16 | int16_t | int16_t | essentially Signed type | +| test.c:124:3:124:11 | ... & ... | int32_t | int32_t | essentially Signed type | +| test.c:124:9:124:11 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:126:3:126:4 | (int)... | int | int | essentially Signed type | +| test.c:126:3:126:4 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:126:3:126:9 | ... \| ... | int8_t | int8_t | essentially Signed type | +| test.c:126:8:126:9 | (int)... | int | int | essentially Signed type | +| test.c:126:8:126:9 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:127:3:127:5 | (int)... | int | int | essentially Signed type | +| test.c:127:3:127:5 | s16 | int16_t | int16_t | essentially Signed type | +| test.c:127:3:127:10 | ... \| ... | int16_t | int16_t | essentially Signed type | +| test.c:127:9:127:10 | (int)... | int | int | essentially Signed type | +| test.c:127:9:127:10 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:128:3:128:4 | (int)... | int | int | essentially Signed type | +| test.c:128:3:128:4 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:128:3:128:10 | ... \| ... | int16_t | int16_t | essentially Signed type | +| test.c:128:8:128:10 | (int)... | int | int | essentially Signed type | +| test.c:128:8:128:10 | s16 | int16_t | int16_t | essentially Signed type | +| test.c:129:3:129:5 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:129:3:129:10 | ... \| ... | int32_t | int32_t | essentially Signed type | +| test.c:129:9:129:10 | (int)... | int | int | essentially Signed type | +| test.c:129:9:129:10 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:130:3:130:4 | (int)... | int | int | essentially Signed type | +| test.c:130:3:130:4 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:130:3:130:10 | ... \| ... | int32_t | int32_t | essentially Signed type | +| test.c:130:8:130:10 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:131:3:131:5 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:131:3:131:11 | ... \| ... | int32_t | int32_t | essentially Signed type | +| test.c:131:9:131:11 | (int)... | int | int | essentially Signed type | +| test.c:131:9:131:11 | s16 | int16_t | int16_t | essentially Signed type | +| test.c:132:3:132:5 | (int)... | int | int | essentially Signed type | +| test.c:132:3:132:5 | s16 | int16_t | int16_t | essentially Signed type | +| test.c:132:3:132:11 | ... \| ... | int32_t | int32_t | essentially Signed type | +| test.c:132:9:132:11 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:134:3:134:4 | (int)... | int | int | essentially Signed type | +| test.c:134:3:134:4 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:134:3:134:9 | ... ^ ... | int8_t | int8_t | essentially Signed type | +| test.c:134:8:134:9 | (int)... | int | int | essentially Signed type | +| test.c:134:8:134:9 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:135:3:135:5 | (int)... | int | int | essentially Signed type | +| test.c:135:3:135:5 | s16 | int16_t | int16_t | essentially Signed type | +| test.c:135:3:135:10 | ... ^ ... | int16_t | int16_t | essentially Signed type | +| test.c:135:9:135:10 | (int)... | int | int | essentially Signed type | +| test.c:135:9:135:10 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:136:3:136:4 | (int)... | int | int | essentially Signed type | +| test.c:136:3:136:4 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:136:3:136:10 | ... ^ ... | int16_t | int16_t | essentially Signed type | +| test.c:136:8:136:10 | (int)... | int | int | essentially Signed type | +| test.c:136:8:136:10 | s16 | int16_t | int16_t | essentially Signed type | +| test.c:137:3:137:5 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:137:3:137:10 | ... ^ ... | int32_t | int32_t | essentially Signed type | +| test.c:137:9:137:10 | (int)... | int | int | essentially Signed type | +| test.c:137:9:137:10 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:138:3:138:4 | (int)... | int | int | essentially Signed type | +| test.c:138:3:138:4 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:138:3:138:10 | ... ^ ... | int32_t | int32_t | essentially Signed type | +| test.c:138:8:138:10 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:139:3:139:5 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:139:3:139:11 | ... ^ ... | int32_t | int32_t | essentially Signed type | +| test.c:139:9:139:11 | (int)... | int | int | essentially Signed type | +| test.c:139:9:139:11 | s16 | int16_t | int16_t | essentially Signed type | +| test.c:140:3:140:5 | (int)... | int | int | essentially Signed type | +| test.c:140:3:140:5 | s16 | int16_t | int16_t | essentially Signed type | +| test.c:140:3:140:11 | ... ^ ... | int32_t | int32_t | essentially Signed type | +| test.c:140:9:140:11 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:142:3:142:5 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:142:3:142:11 | ... & ... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:142:9:142:11 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:142:9:142:11 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:143:3:143:5 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:143:3:143:5 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:143:3:143:11 | ... & ... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:143:9:143:11 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:144:3:144:4 | (int)... | int | int | essentially Signed type | +| test.c:144:3:144:4 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:144:3:144:10 | ... & ... | int | int | essentially Signed type | +| test.c:144:8:144:10 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:145:3:145:5 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:145:3:145:10 | ... & ... | int | int | essentially Signed type | +| test.c:145:9:145:10 | (int)... | int | int | essentially Signed type | +| test.c:145:9:145:10 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:146:3:146:4 | (int)... | int | int | essentially Signed type | +| test.c:146:3:146:4 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:146:3:146:9 | ... & ... | int | int | essentially Signed type | +| test.c:146:8:146:9 | (int)... | int | int | essentially Signed type | +| test.c:146:8:146:9 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:147:3:147:4 | (int)... | int | int | essentially Signed type | +| test.c:147:3:147:4 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:147:3:147:9 | ... & ... | int | int | essentially Signed type | +| test.c:147:8:147:9 | (int)... | int | int | essentially Signed type | +| test.c:147:8:147:9 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:149:3:149:5 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:149:3:149:11 | ... \| ... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:149:9:149:11 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:149:9:149:11 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:150:3:150:5 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:150:3:150:5 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:150:3:150:11 | ... \| ... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:150:9:150:11 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:151:3:151:4 | (int)... | int | int | essentially Signed type | +| test.c:151:3:151:4 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:151:3:151:10 | ... \| ... | int | int | essentially Signed type | +| test.c:151:8:151:10 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:152:3:152:5 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:152:3:152:10 | ... \| ... | int | int | essentially Signed type | +| test.c:152:9:152:10 | (int)... | int | int | essentially Signed type | +| test.c:152:9:152:10 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:153:3:153:4 | (int)... | int | int | essentially Signed type | +| test.c:153:3:153:4 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:153:3:153:9 | ... \| ... | int | int | essentially Signed type | +| test.c:153:8:153:9 | (int)... | int | int | essentially Signed type | +| test.c:153:8:153:9 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:154:3:154:4 | (int)... | int | int | essentially Signed type | +| test.c:154:3:154:4 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:154:3:154:9 | ... \| ... | int | int | essentially Signed type | +| test.c:154:8:154:9 | (int)... | int | int | essentially Signed type | +| test.c:154:8:154:9 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:156:3:156:5 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:156:3:156:11 | ... ^ ... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:156:9:156:11 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:156:9:156:11 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:157:3:157:5 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:157:3:157:5 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:157:3:157:11 | ... ^ ... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:157:9:157:11 | u32 | uint32_t | uint32_t | essentially Unsigned type | +| test.c:158:3:158:4 | (int)... | int | int | essentially Signed type | +| test.c:158:3:158:4 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:158:3:158:10 | ... ^ ... | int | int | essentially Signed type | +| test.c:158:8:158:10 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:159:3:159:5 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:159:3:159:10 | ... ^ ... | int | int | essentially Signed type | +| test.c:159:9:159:10 | (int)... | int | int | essentially Signed type | +| test.c:159:9:159:10 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:160:3:160:4 | (int)... | int | int | essentially Signed type | +| test.c:160:3:160:4 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:160:3:160:9 | ... ^ ... | int | int | essentially Signed type | +| test.c:160:8:160:9 | (int)... | int | int | essentially Signed type | +| test.c:160:8:160:9 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:161:3:161:4 | (int)... | int | int | essentially Signed type | +| test.c:161:3:161:4 | s8 | int8_t | int8_t | essentially Signed type | +| test.c:161:3:161:9 | ... ^ ... | int | int | essentially Signed type | +| test.c:161:8:161:9 | (int)... | int | int | essentially Signed type | +| test.c:161:8:161:9 | u8 | uint8_t | uint8_t | essentially Unsigned type | diff --git a/c/misra/test/c/misra/test.c b/c/misra/test/c/misra/test.c index b3fdddd591..dcdfef4eb4 100644 --- a/c/misra/test/c/misra/test.c +++ b/c/misra/test/c/misra/test.c @@ -79,4 +79,84 @@ void testControlChar() { 'a'; // Essentially char '\n'; // Essentially char '\0'; // Essentially char +} + +#include + +void testBitwise() { + uint8_t u8 = 0; + uint16_t u16 = 0; + uint32_t u32 = 0; + int8_t s8 = 0; + int16_t s16 = 0; + int32_t s32 = 0; + + u8 & u8; // Essentially unsigned, char + u16 & u8; // Essentially unsigned, short + u8 & u16; // Essentially unsigned, short + u32 & u8; // Essentially unsigned, int + u8 & u32; // Essentially unsigned, int + u32 & u16; // Essentially unsigned, int + u16 & u32; // Essentially unsigned, int + + u8 | u8; // Essentially unsigned, char + u16 | u8; // Essentially unsigned, short + u8 | u16; // Essentially unsigned, short + u32 | u8; // Essentially unsigned, int + u8 | u32; // Essentially unsigned, int + u32 | u16; // Essentially unsigned, int + u16 | u32; // Essentially unsigned, int + + u8 ^ u8; // Essentially unsigned, char + u16 ^ u8; // Essentially unsigned, short + u8 ^ u16; // Essentially unsigned, short + u32 ^ u8; // Essentially unsigned, int + u8 ^ u32; // Essentially unsigned, int + u32 ^ u16; // Essentially unsigned, int + u16 ^ u32; // Essentially unsigned, int + + s8 & s8; // Essentially signed, char + s16 & s8; // Essentially signed, short + s8 & s16; // Essentially signed, short + s32 & s8; // Essentially signed, int + s8 & s32; // Essentially signed, int + s32 & s16; // Essentially signed, int + s16 & s32; // Essentially signed, int + + s8 | s8; // Essentially signed, char + s16 | s8; // Essentially signed, short + s8 | s16; // Essentially signed, short + s32 | s8; // Essentially signed, int + s8 | s32; // Essentially signed, int + s32 | s16; // Essentially signed, int + s16 | s32; // Essentially signed, int + + s8 ^ s8; // Essentially signed, char + s16 ^ s8; // Essentially signed, short + s8 ^ s16; // Essentially signed, short + s32 ^ s8; // Essentially signed, int + s8 ^ s32; // Essentially signed, int + s32 ^ s16; // Essentially signed, int + s16 ^ s32; // Essentially signed, int + + u32 & s32; // Essentially signed, int + s32 & u32; // Essentially signed, int + u8 & s32; // Essentially signed, int + s32 & u8; // Essentially signed, int + u8 & s8; // Essentially signed, int + s8 & u8; // Essentially signed, int + + u32 | s32; // Essentially signed, int + s32 | u32; // Essentially signed, int + u8 | s32; // Essentially signed, int + s32 | u8; // Essentially signed, int + u8 | s8; // Essentially signed, int + s8 | u8; // Essentially signed, int + + u32 ^ s32; // Essentially signed, int + s32 ^ u32; // Essentially signed, int + u8 ^ s32; // Essentially signed, int + s32 ^ u8; // Essentially signed, int + u8 ^ s8; // Essentially signed, int + s8 ^ u8; // Essentially signed, int } \ No newline at end of file From a5ed461557c57b44df2f6a420e6ecc1bd89cbed2 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 27 Oct 2024 15:28:27 +0000 Subject: [PATCH 043/370] EssentialTypes: Add test cases for shifts --- c/misra/test/c/misra/EssentialTypes.expected | 73 ++++++++++++++++++++ c/misra/test/c/misra/test.c | 38 ++++++++++ 2 files changed, 111 insertions(+) diff --git a/c/misra/test/c/misra/EssentialTypes.expected b/c/misra/test/c/misra/EssentialTypes.expected index 19a7090fe9..95976fe2ab 100644 --- a/c/misra/test/c/misra/EssentialTypes.expected +++ b/c/misra/test/c/misra/EssentialTypes.expected @@ -365,3 +365,76 @@ | test.c:161:3:161:9 | ... ^ ... | int | int | essentially Signed type | | test.c:161:8:161:9 | (int)... | int | int | essentially Signed type | | test.c:161:8:161:9 | u8 | uint8_t | uint8_t | essentially Unsigned type | +| test.c:165:16:165:17 | 1 | signed char | signed char | essentially Signed type | +| test.c:170:3:170:4 | 1 | unsigned char | unsigned char | essentially Unsigned type | +| test.c:170:3:170:9 | ... << ... | unsigned char | unsigned char | essentially Unsigned type | +| test.c:170:9:170:9 | 1 | signed char | signed char | essentially Signed type | +| test.c:171:3:171:6 | 256 | unsigned short | unsigned short | essentially Unsigned type | +| test.c:171:3:171:11 | ... << ... | unsigned short | unsigned short | essentially Unsigned type | +| test.c:171:11:171:11 | 1 | signed char | signed char | essentially Signed type | +| test.c:172:3:172:8 | 65536 | unsigned int | unsigned int | essentially Unsigned type | +| test.c:172:3:172:13 | ... << ... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:172:13:172:13 | 1 | signed char | signed char | essentially Signed type | +| test.c:173:3:173:4 | 2 | unsigned char | unsigned char | essentially Unsigned type | +| test.c:173:3:173:9 | ... >> ... | unsigned char | unsigned char | essentially Unsigned type | +| test.c:173:9:173:9 | 1 | signed char | signed char | essentially Signed type | +| test.c:174:3:174:8 | 32768 | unsigned short | unsigned short | essentially Unsigned type | +| test.c:174:3:174:13 | ... >> ... | unsigned short | unsigned short | essentially Unsigned type | +| test.c:174:13:174:13 | 1 | signed char | signed char | essentially Signed type | +| test.c:175:3:175:13 | 2147483648 | unsigned int | unsigned int | essentially Unsigned type | +| test.c:175:3:175:18 | ... >> ... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:175:18:175:18 | 1 | signed char | signed char | essentially Signed type | +| test.c:176:3:176:14 | 4294967295 | unsigned long | unsigned long | essentially Unsigned type | +| test.c:176:3:176:19 | ... << ... | unsigned long | unsigned long | essentially Unsigned type | +| test.c:176:3:176:19 | ... << ... | unsigned long | unsigned long long | essentially Unsigned type | +| test.c:176:3:176:19 | ... << ... | unsigned long long | unsigned long | essentially Unsigned type | +| test.c:176:3:176:19 | ... << ... | unsigned long long | unsigned long long | essentially Unsigned type | +| test.c:176:19:176:19 | 1 | signed char | signed char | essentially Signed type | +| test.c:181:3:181:6 | 256 | unsigned short | unsigned short | essentially Unsigned type | +| test.c:181:3:181:11 | ... >> ... | unsigned char | unsigned char | essentially Unsigned type | +| test.c:181:11:181:11 | 1 | signed char | signed char | essentially Signed type | +| test.c:182:3:182:8 | 65536 | unsigned int | unsigned int | essentially Unsigned type | +| test.c:182:3:182:13 | ... >> ... | unsigned short | unsigned short | essentially Unsigned type | +| test.c:182:13:182:13 | 1 | signed char | signed char | essentially Signed type | +| test.c:183:3:183:13 | 4294967296 | unsigned long | unsigned long | essentially Unsigned type | +| test.c:183:3:183:18 | ... >> ... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:183:18:183:18 | 1 | signed char | signed char | essentially Signed type | +| test.c:184:3:184:6 | 255 | unsigned char | unsigned char | essentially Unsigned type | +| test.c:184:3:184:11 | ... << ... | unsigned short | unsigned short | essentially Unsigned type | +| test.c:184:11:184:11 | 1 | signed char | signed char | essentially Signed type | +| test.c:185:3:185:8 | 65535 | unsigned short | unsigned short | essentially Unsigned type | +| test.c:185:3:185:13 | ... << ... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:185:13:185:13 | 1 | signed char | signed char | essentially Signed type | +| test.c:189:3:189:6 | 255 | unsigned char | unsigned char | essentially Unsigned type | +| test.c:189:3:189:13 | ... >> ... | unsigned char | unsigned char | essentially Unsigned type | +| test.c:189:11:189:13 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:190:3:190:8 | 65535 | unsigned short | unsigned short | essentially Unsigned type | +| test.c:190:3:190:15 | ... >> ... | unsigned short | unsigned short | essentially Unsigned type | +| test.c:190:13:190:15 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:191:3:191:13 | 4294967295 | unsigned int | unsigned int | essentially Unsigned type | +| test.c:191:3:191:20 | ... >> ... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:191:18:191:20 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:192:3:192:6 | 255 | unsigned char | unsigned char | essentially Unsigned type | +| test.c:192:3:192:13 | ... << ... | unsigned char | unsigned char | essentially Unsigned type | +| test.c:192:11:192:13 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:193:3:193:8 | 65535 | unsigned short | unsigned short | essentially Unsigned type | +| test.c:193:3:193:15 | ... << ... | unsigned short | unsigned short | essentially Unsigned type | +| test.c:193:13:193:15 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:194:3:194:13 | 4294967295 | unsigned int | unsigned int | essentially Unsigned type | +| test.c:194:3:194:20 | ... << ... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:194:18:194:20 | s32 | int32_t | int32_t | essentially Signed type | +| test.c:197:3:197:5 | 257 | short | short | essentially Signed type | +| test.c:197:3:197:5 | 257 | short | signed short | essentially Signed type | +| test.c:197:3:197:5 | 257 | signed short | short | essentially Signed type | +| test.c:197:3:197:5 | 257 | signed short | signed short | essentially Signed type | +| test.c:197:3:197:10 | ... >> ... | int | int | essentially Signed type | +| test.c:197:10:197:10 | 1 | signed char | signed char | essentially Signed type | +| test.c:198:3:198:7 | 65537 | int | int | essentially Signed type | +| test.c:198:3:198:7 | 65537 | int | signed int | essentially Signed type | +| test.c:198:3:198:7 | 65537 | signed int | int | essentially Signed type | +| test.c:198:3:198:7 | 65537 | signed int | signed int | essentially Signed type | +| test.c:198:3:198:12 | ... >> ... | int | int | essentially Signed type | +| test.c:198:12:198:12 | 1 | signed char | signed char | essentially Signed type | +| test.c:199:3:199:12 | 4294967297 | long | long | essentially Signed type | +| test.c:199:3:199:17 | ... >> ... | long | long | essentially Signed type | +| test.c:199:17:199:17 | 1 | signed char | signed char | essentially Signed type | diff --git a/c/misra/test/c/misra/test.c b/c/misra/test/c/misra/test.c index dcdfef4eb4..e271a67e30 100644 --- a/c/misra/test/c/misra/test.c +++ b/c/misra/test/c/misra/test.c @@ -159,4 +159,42 @@ void testBitwise() { s32 ^ u8; // Essentially signed, int u8 ^ s8; // Essentially signed, int s8 ^ u8; // Essentially signed, int +} + +void testShifts() { + int32_t s32 = 1; + + // Left hand is unsigned and both are constants, so UTLR + // In these cases the UTLR is the same as the essential type of + // the left operand + 1U << 1; // Essentially unsigned char + 256U << 1; // Essentially unsigned short + 65536U << 1; // Essentially unsigned int + 2U >> 1; // Essentially unsigned char + 32768U >> 1; // Essentially unsigned short - 2^15 >> 1 = 2^14 + 2147483648U >> 1; // Essentially unsigned int - 2^31 >> 1 = 2^30 + 4294967295LU << 1; // Essentially unsigned long + + // Left hand is unsigned and both are constants, so UTLR + // In these cases the UTLR is not the same as the essential type of + // the left operand + 256U >> 1; // Essentially unsigned char + 65536U >> 1; // Essentially unsigned short + 4294967296U >> 1; // Essentially unsigned int + 255U << 1; // Essentially unsigned short + 65535U << 1; // Essentially unsigned int + + // Left hand is unsigned, but left isn't a constant, so essential type of left + // operand + 255U >> s32; // Essentially unsigned char + 65535U >> s32; // Essentially unsigned short + 4294967295U >> s32; // Essentially unsigned int + 255U << s32; // Essentially unsigned char + 65535U << s32; // Essentially unsigned short + 4294967295U << s32; // Essentially unsigned int + + // Left hand operand signed int, so result is standard type + 257 >> 1; // Essentially signed int + 65537 >> 1; // Essentially signed int + 4294967297 >> 1; // Essentially signed long } \ No newline at end of file From aba9528b7341251ee35555a32be7e04f5cfa226d Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 27 Oct 2024 15:41:21 +0000 Subject: [PATCH 044/370] RULE-10-3: Expand test cases for binary bitwise operators --- ...gnmentOfIncompatibleEssentialType.expected | 6 +++++ c/misra/test/rules/RULE-10-3/test.c | 25 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/c/misra/test/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.expected b/c/misra/test/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.expected index 3867abd0ca..b64f970bfe 100644 --- a/c/misra/test/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.expected +++ b/c/misra/test/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.expected @@ -131,3 +131,9 @@ | test.c:356:10:356:11 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | | test.c:357:10:357:10 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | | test.c:358:10:358:10 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | +| test.c:369:12:369:20 | ... & ... | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:370:12:370:20 | ... \| ... | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:371:12:371:20 | ... ^ ... | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:376:20:376:27 | ... & ... | Assignment of value of essentially Signed type of size 2 bytes to an object narrower essential type of size 1 bytes. | +| test.c:381:23:381:30 | ... & ... | Assignment of value of essentially Unsigned type of size 2 bytes to an object narrower essential type of size 1 bytes. | +| test.c:384:22:384:29 | ... & ... | Assignment of essentially Signed type value to an object of essentially Unsigned type. | diff --git a/c/misra/test/rules/RULE-10-3/test.c b/c/misra/test/rules/RULE-10-3/test.c index 30ab2985ae..f4ad487ae1 100644 --- a/c/misra/test/rules/RULE-10-3/test.c +++ b/c/misra/test/rules/RULE-10-3/test.c @@ -357,4 +357,29 @@ void testStructAssignment() { s1.f = s; // NON_COMPLIANT s1.f = u; // NON_COMPLIANT s1.f = f; // COMPLIANT +} + +void testBinaryBitwise() { + signed int s32 = 100; // COMPLIANT - wider + signed short s16 = 0; // COMPLIANT - wider + signed char s8 = 0; // COMPLIANT - wider + unsigned int u32 = 100; // COMPLIANT - by exception 1 + unsigned char u8 = 0; // COMPLIANT - by exception 1 + unsigned short u16 = 0; // COMPLIANT - by exception 1 + int x1 = s32 & u32; // NON_COMPLIANT - integer promotion to u32 + int x2 = s32 | u32; // NON_COMPLIANT - integer promotion to u32 + int x3 = s32 ^ u32; // NON_COMPLIANT - integer promotion to u32 + int x4 = s16 & s32; // COMPLIANT + int x5 = s16 & u16; // COMPLIANT + int x6 = s16 & s8; // COMPLIANT + signed short x7 = s16 & s8; // COMPLIANT + signed char x8 = s16 & s8; // NON_COMPLIANT + signed char x9 = s8 & s8; // COMPLIANT + signed short x10 = s8 & s8; // COMPLIANT + unsigned int x11 = u16 & u8; // COMPLIANT + unsigned short x12 = u16 & u8; // COMPLIANT + unsigned char x13 = u16 & u8; // NON_COMPLIANT + unsigned char x14 = u8 & u8; // COMPLIANT + unsigned short x15 = u8 & u8; // COMPLIANT + unsigned int x16 = s16 & s8; // NON_COMPLIANT } \ No newline at end of file From 5b753e0cbde1f57b22909fc05922e2c61ab032df Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 28 Oct 2024 08:47:04 -0700 Subject: [PATCH 045/370] Add change note --- change_notes/2024-10-28-essential-types-bitwise.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 change_notes/2024-10-28-essential-types-bitwise.md diff --git a/change_notes/2024-10-28-essential-types-bitwise.md b/change_notes/2024-10-28-essential-types-bitwise.md new file mode 100644 index 0000000000..a382290351 --- /dev/null +++ b/change_notes/2024-10-28-essential-types-bitwise.md @@ -0,0 +1,2 @@ + - `RULE-10-1`, `RULE-10-3`, `RULE-10-4`, `RULE-10-5`, `RULE-10-6`, `RULE-10-7`, `RULE-10-8`, `RULE-12-2` - `OperandsOfAnInappropriateEssentialType.ql`, `AssignmentOfIncompatibleEssentialType.ql`, `OperandsWithMismatchedEssentialTypeCategory.ql`, `InappropriateEssentialTypeCast.ql`, `AssignmentToWiderEssentialType,ql`, `ImplicitConversionOfCompositeExpression.ql`, `InappropriateCastOfCompositeExpression.ql`: + - False positives and false negatives removed due to fixing incorrect essential type of the binary bitwise operations `^`, `|` and `&`. Previously the standard type was used, instead of applying the essential type rules which dictate that if both arguments have the same signedness, the essential type will have the same signedness and a rank equal to the larger of the two operands. \ No newline at end of file From fb3c5e7cb804d69ba1caa7537c181ccd0bee73eb Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 31 Oct 2024 21:38:49 -0700 Subject: [PATCH 046/370] Implement Concurrency6 package -- split out Concurrency7 --- .../ThreadWasPreviouslyJoinedOrDetached.ql | 39 +--- ...hreadWasPreviouslyJoinedOrDetached.testref | 1 + .../includes/standard-library/stdatomic.h | 74 +++++++- .../JoinOrDetachThreadOnlyOnce.expected} | 0 .../JoinOrDetachThreadOnlyOnce.ql | 4 + .../rules/joinordetachthreadonlyonce}/test.c | 0 .../DIR-5-2/NotNoDeadlocksBetweenThreads.ql | 24 +++ .../DIR-5-3/BannedDynamicThreadCreation.ql | 29 +++ .../rules/DIR-5-3/ThreadCreatedByThread.ql | 45 +++++ .../AtomicAggregateObjectDirectlyAccessed.ql | 35 ++++ .../RULE-21-25/InvalidMemoryOrderArgument.ql | 176 ++++++++++++++++++ .../ThreadPreviouslyJoinedOrDetached.ql | 24 +++ .../NotNoDeadlocksBetweenThreads.testref | 1 + .../BannedDynamicThreadCreation.expected | 16 ++ .../DIR-5-3/BannedDynamicThreadCreation.qlref | 1 + .../DIR-5-3/ThreadCreatedByThread.expected | 14 ++ .../rules/DIR-5-3/ThreadCreatedByThread.qlref | 1 + c/misra/test/rules/DIR-5-3/test.c | 95 ++++++++++ ...icAggregateObjectDirectlyAccessed.expected | 4 + ...tomicAggregateObjectDirectlyAccessed.qlref | 1 + c/misra/test/rules/RULE-12-6/test.c | 59 ++++++ .../InvalidMemoryOrderArgument.expected | 99 ++++++++++ .../InvalidMemoryOrderArgument.qlref | 1 + c/misra/test/rules/RULE-21-25/test.c | 85 +++++++++ .../ThreadPreviouslyJoinedOrDetached.testref | 1 + ...hreadWasPreviouslyJoinedOrDetached.testref | 1 + .../src/codingstandards/cpp/Concurrency.qll | 31 ++- .../cpp/exclusions/c/Concurrency6.qll | 112 +++++++++++ .../cpp/exclusions/c/RuleMetadata.qll | 3 + .../JoinOrDetachThreadOnlyOnce.qll | 49 +++++ rule_packages/c/Concurrency5.json | 1 + rule_packages/c/Concurrency6.json | 132 +++++++++++++ rules.csv | 26 +-- 33 files changed, 1125 insertions(+), 59 deletions(-) create mode 100644 c/cert/test/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.testref rename c/{cert/test/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.expected => common/test/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.expected} (100%) create mode 100644 c/common/test/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.ql rename c/{cert/test/rules/CON39-C => common/test/rules/joinordetachthreadonlyonce}/test.c (100%) create mode 100644 c/misra/src/rules/DIR-5-2/NotNoDeadlocksBetweenThreads.ql create mode 100644 c/misra/src/rules/DIR-5-3/BannedDynamicThreadCreation.ql create mode 100644 c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql create mode 100644 c/misra/src/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.ql create mode 100644 c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql create mode 100644 c/misra/src/rules/RULE-22-11/ThreadPreviouslyJoinedOrDetached.ql create mode 100644 c/misra/test/rules/DIR-5-2/NotNoDeadlocksBetweenThreads.testref create mode 100644 c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.expected create mode 100644 c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.qlref create mode 100644 c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.expected create mode 100644 c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.qlref create mode 100644 c/misra/test/rules/DIR-5-3/test.c create mode 100644 c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.expected create mode 100644 c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.qlref create mode 100644 c/misra/test/rules/RULE-12-6/test.c create mode 100644 c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected create mode 100644 c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.qlref create mode 100644 c/misra/test/rules/RULE-21-25/test.c create mode 100644 c/misra/test/rules/RULE-22-11/ThreadPreviouslyJoinedOrDetached.testref create mode 100644 c/misra/test/rules/RULE-22-11/ThreadWasPreviouslyJoinedOrDetached.testref create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency6.qll create mode 100644 cpp/common/src/codingstandards/cpp/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.qll create mode 100644 rule_packages/c/Concurrency6.json diff --git a/c/cert/src/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.ql b/c/cert/src/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.ql index a8dead535d..0604d2d483 100644 --- a/c/cert/src/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.ql +++ b/c/cert/src/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.ql @@ -14,37 +14,10 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.Concurrency +import codingstandards.cpp.rules.joinordetachthreadonlyonce.JoinOrDetachThreadOnlyOnce -// OK -// 1) Thread calls detach parent DOES NOT call join -// 2) Parent calls join, thread does NOT call detach() -// NOT OK -// 1) Thread calls detach, parent calls join -// 2) Thread calls detach twice, parent does not call join -// 3) Parent calls join twice, thread does not call detach -from C11ThreadCreateCall tcc -where - not isExcluded(tcc, Concurrency5Package::threadWasPreviouslyJoinedOrDetachedQuery()) and - // Note: These cases can be simplified but they are presented like this for clarity - // case 1 - calls to `thrd_join` and `thrd_detach` within the parent or - // within the parent / child CFG. - exists(C11ThreadWait tw, C11ThreadDetach dt | - tw = getAThreadContextAwareSuccessor(tcc) and - dt = getAThreadContextAwareSuccessor(tcc) - ) - or - // case 2 - multiple calls to `thrd_detach` within the threaded CFG. - exists(C11ThreadDetach dt1, C11ThreadDetach dt2 | - dt1 = getAThreadContextAwareSuccessor(tcc) and - dt2 = getAThreadContextAwareSuccessor(tcc) and - not dt1 = dt2 - ) - or - // case 3 - multiple calls to `thrd_join` within the threaded CFG. - exists(C11ThreadWait tw1, C11ThreadWait tw2 | - tw1 = getAThreadContextAwareSuccessor(tcc) and - tw2 = getAThreadContextAwareSuccessor(tcc) and - not tw1 = tw2 - ) -select tcc, "Thread may call join or detach after the thread is joined or detached." +class ThreadWasPreviouslyJoinedOrDetachedQuery extends JoinOrDetachThreadOnlyOnceSharedQuery { + ThreadWasPreviouslyJoinedOrDetachedQuery() { + this = Concurrency5Package::threadWasPreviouslyJoinedOrDetachedQuery() + } +} diff --git a/c/cert/test/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.testref b/c/cert/test/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.testref new file mode 100644 index 0000000000..61fa88fd08 --- /dev/null +++ b/c/cert/test/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.testref @@ -0,0 +1 @@ +c/common/test/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.ql \ No newline at end of file diff --git a/c/common/test/includes/standard-library/stdatomic.h b/c/common/test/includes/standard-library/stdatomic.h index 66b74ae61a..49a5b3cfcd 100644 --- a/c/common/test/includes/standard-library/stdatomic.h +++ b/c/common/test/includes/standard-library/stdatomic.h @@ -1,9 +1,69 @@ -#define atomic_compare_exchange_weak(a, b, c) 0 -#define atomic_compare_exchange_weak_explicit(a, b, c, d, e) 0 -#define atomic_load(a) 0 -#define atomic_load_explicit(a, b) -#define atomic_store(a, b) 0 -#define atomic_store_explicit(a, b, c) 0 #define ATOMIC_VAR_INIT(value) (value) #define atomic_is_lock_free(obj) __c11_atomic_is_lock_free(sizeof(*(obj))) -typedef _Atomic(int) atomic_int; \ No newline at end of file +typedef _Atomic(int) atomic_int; + +#define __ATOMIC_RELAXED 0 +#define __ATOMIC_CONSUME 1 +#define __ATOMIC_ACQUIRE 2 +#define __ATOMIC_RELEASE 3 +#define __ATOMIC_ACQ_REL 4 +#define __ATOMIC_SEQ_CST 5 + +typedef enum memory_order { + memory_order_relaxed = __ATOMIC_RELAXED, + memory_order_consume = __ATOMIC_CONSUME, + memory_order_acquire = __ATOMIC_ACQUIRE, + memory_order_release = __ATOMIC_RELEASE, + memory_order_acq_rel = __ATOMIC_ACQ_REL, + memory_order_seq_cst = __ATOMIC_SEQ_CST +} memory_order; + +void atomic_thread_fence(memory_order); +void atomic_signal_fence(memory_order); + +#define atomic_thread_fence(order) __c11_atomic_thread_fence(order) +#define atomic_signal_fence(order) __c11_atomic_signal_fence(order) + +#define atomic_store(object, desired) __c11_atomic_store(object, desired, __ATOMIC_SEQ_CST) +#define atomic_store_explicit __c11_atomic_store + +#define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST) +#define atomic_load_explicit __c11_atomic_load + +#define atomic_exchange(object, desired) __c11_atomic_exchange(object, desired, __ATOMIC_SEQ_CST) +#define atomic_exchange_explicit __c11_atomic_exchange + +#define atomic_compare_exchange_strong(object, expected, desired) __c11_atomic_compare_exchange_strong(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) +#define atomic_compare_exchange_strong_explicit __c11_atomic_compare_exchange_strong + +#define atomic_compare_exchange_weak(object, expected, desired) __c11_atomic_compare_exchange_weak(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) +#define atomic_compare_exchange_weak_explicit __c11_atomic_compare_exchange_weak + +#define atomic_fetch_add(object, operand) __c11_atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST) +#define atomic_fetch_add_explicit __c11_atomic_fetch_add + +#define atomic_fetch_sub(object, operand) __c11_atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST) +#define atomic_fetch_sub_explicit __c11_atomic_fetch_sub + +#define atomic_fetch_or(object, operand) __c11_atomic_fetch_or(object, operand, __ATOMIC_SEQ_CST) +#define atomic_fetch_or_explicit __c11_atomic_fetch_or + +#define atomic_fetch_xor(object, operand) __c11_atomic_fetch_xor(object, operand, __ATOMIC_SEQ_CST) +#define atomic_fetch_xor_explicit __c11_atomic_fetch_xor + +#define atomic_fetch_and(object, operand) __c11_atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST) +#define atomic_fetch_and_explicit __c11_atomic_fetch_and + +typedef struct atomic_flag { _Atomic(_Bool) _Value; } atomic_flag; + +_Bool atomic_flag_test_and_set(volatile atomic_flag *); +_Bool atomic_flag_test_and_set_explicit(volatile atomic_flag *, memory_order); + +void atomic_flag_clear(volatile atomic_flag *); +void atomic_flag_clear_explicit(volatile atomic_flag *, memory_order); + +#define atomic_flag_test_and_set(object) __c11_atomic_exchange(&(object)->_Value, 1, __ATOMIC_SEQ_CST) +#define atomic_flag_test_and_set_explicit(object, order) __c11_atomic_exchange(&(object)->_Value, 1, order) + +#define atomic_flag_clear(object) __c11_atomic_store(&(object)->_Value, 0, __ATOMIC_SEQ_CST) +#define atomic_flag_clear_explicit(object, order) __c11_atomic_store(&(object)->_Value, 0, order) \ No newline at end of file diff --git a/c/cert/test/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.expected b/c/common/test/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.expected similarity index 100% rename from c/cert/test/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.expected rename to c/common/test/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.expected diff --git a/c/common/test/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.ql b/c/common/test/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.ql new file mode 100644 index 0000000000..87188403af --- /dev/null +++ b/c/common/test/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.ql @@ -0,0 +1,4 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.joinordetachthreadonlyonce.JoinOrDetachThreadOnlyOnce + +class TestFileQuery extends JoinOrDetachThreadOnlyOnceSharedQuery, TestQuery { } diff --git a/c/cert/test/rules/CON39-C/test.c b/c/common/test/rules/joinordetachthreadonlyonce/test.c similarity index 100% rename from c/cert/test/rules/CON39-C/test.c rename to c/common/test/rules/joinordetachthreadonlyonce/test.c diff --git a/c/misra/src/rules/DIR-5-2/NotNoDeadlocksBetweenThreads.ql b/c/misra/src/rules/DIR-5-2/NotNoDeadlocksBetweenThreads.ql new file mode 100644 index 0000000000..ffe30a2b6a --- /dev/null +++ b/c/misra/src/rules/DIR-5-2/NotNoDeadlocksBetweenThreads.ql @@ -0,0 +1,24 @@ +/** + * @id c/misra/not-no-deadlocks-between-threads + * @name DIR-5-2: There shall be no deadlocks between threads + * @description Circular waits leading to thread deadlocks may be avoided by locking in a predefined + * order. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/dir-5-2 + * external/misra/c/2012/amendment4 + * correctness + * concurrency + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.rules.preventdeadlockbylockinginpredefinedorder.PreventDeadlockByLockingInPredefinedOrder + +class NotNoDeadlocksBetweenThreadsQuery extends PreventDeadlockByLockingInPredefinedOrderSharedQuery { + NotNoDeadlocksBetweenThreadsQuery() { + this = Concurrency6Package::notNoDeadlocksBetweenThreadsQuery() + } +} diff --git a/c/misra/src/rules/DIR-5-3/BannedDynamicThreadCreation.ql b/c/misra/src/rules/DIR-5-3/BannedDynamicThreadCreation.ql new file mode 100644 index 0000000000..4bb526306b --- /dev/null +++ b/c/misra/src/rules/DIR-5-3/BannedDynamicThreadCreation.ql @@ -0,0 +1,29 @@ +/** + * @id c/misra/banned-dynamic-thread-creation + * @name DIR-5-3: There shall be no dynamic thread creation + * @description Creating threads outside of a well-defined program start-up phase creates + * uncertainty in program behavior and concurrency overhead costs. + * @kind problem + * @precision low + * @problem.severity error + * @tags external/misra/id/dir-5-3 + * external/misra/c/2012/amendment4 + * external/misra/c/audit + * correctness + * maintainability + * concurrency + * performance + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.Concurrency + +from CThreadCreateCall tc, Function enclosingFunction +where + not isExcluded(tc, Concurrency6Package::bannedDynamicThreadCreationQuery()) and + enclosingFunction = tc.getEnclosingFunction() and + not enclosingFunction.getName() = "main" +select tc, "Possible dynamic creation of thread outside initialization in function '$@'.", + enclosingFunction, enclosingFunction.toString() diff --git a/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql b/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql new file mode 100644 index 0000000000..cf08a0c809 --- /dev/null +++ b/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql @@ -0,0 +1,45 @@ +/** + * @id c/misra/thread-created-by-thread + * @name DIR-5-3: Threads shall not be created by other threads + * @description Creating threads within threads creates uncertainty in program behavior and + * concurrency overhead costs. + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/dir-5-3 + * external/misra/c/2012/amendment4 + * correctness + * maintainability + * concurrency + * performance + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.Concurrency + +Function callers(Function f) { result = f.getACallToThisFunction().getEnclosingFunction() } + +class ThreadReachableFunction extends Function { + /* The root threaded function from which this function is reachable */ + Function threadRoot; + + ThreadReachableFunction() { + exists(CThreadCreateCall tc | + tc.getFunction() = callers*(this) and + threadRoot = tc.getFunction() + ) + } + + /* Get the root threaded function from which this function is reachable */ + Function getThreadRoot() { result = threadRoot } +} + +from CThreadCreateCall tc, ThreadReachableFunction enclosingFunction, Function threadRoot +where + not isExcluded(tc, Concurrency6Package::threadCreatedByThreadQuery()) and + enclosingFunction = tc.getEnclosingFunction() and + threadRoot = enclosingFunction.getThreadRoot() +select tc, "Thread creation call reachable from threaded function '$@'.", threadRoot, + threadRoot.toString() \ No newline at end of file diff --git a/c/misra/src/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.ql b/c/misra/src/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.ql new file mode 100644 index 0000000000..4e65fa3f91 --- /dev/null +++ b/c/misra/src/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.ql @@ -0,0 +1,35 @@ +/** + * @id c/misra/atomic-aggregate-object-directly-accessed + * @name RULE-12-6: Structure and union members of atomic objects shall not be directly accessed + * @description Accessing a member of an atomic structure or union results in undefined behavior. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-12-6 + * external/misra/c/2012/amendment4 + * correctness + * concurrency + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra + +from Expr expr, Field field +where + not isExcluded(expr, Concurrency6Package::atomicAggregateObjectDirectlyAccessedQuery()) and + not expr.isUnevaluated() and + ( + exists(FieldAccess fa | + expr = fa and + fa.getQualifier().getUnderlyingType().hasSpecifier("atomic") and + field = fa.getTarget() + ) + or + exists(PointerFieldAccess fa | + expr = fa and + fa.getQualifier().getUnderlyingType().(PointerType).getBaseType().hasSpecifier("atomic") and + field = fa.getTarget() + ) + ) +select expr, "Invalid access to member '$@' on atomic struct or union.", field, field.getName() diff --git a/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql b/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql new file mode 100644 index 0000000000..4924c0df33 --- /dev/null +++ b/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql @@ -0,0 +1,176 @@ +/** + * @id c/misra/invalid-memory-order-argument + * @name RULE-21-25: All memory synchronization operations shall be executed in sequentially consistent order + * @description Only the memory ordering of 'memory_order_seq_cst' is fully portable and consistent. + * @kind path-problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-21-25 + * external/misra/c/2012/amendment4 + * correctness + * concurrency + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import semmle.code.cpp.dataflow.new.DataFlow + +/* A member of the set of memory orders defined in the `memory_order` enum */ +class MemoryOrder extends EnumConstant { + MemoryOrder() { getDeclaringEnum().getName() = "memory_order" } + + int getIntValue() { result = getValue().toInt() } +} + +/* This is the only standardized memory order, allowed by RULE-21-25. */ +class AllowedMemoryOrder extends MemoryOrder { + AllowedMemoryOrder() { getName() = "memory_order_seq_cst" } +} + +/* An expression referring to a memory order */ +class MemoryOrderConstantAccess extends EnumConstantAccess { + MemoryOrderConstantAccess() { getTarget() instanceof MemoryOrder } + + predicate isAllowedOrder() { getTarget() instanceof AllowedMemoryOrder } +} + +/* An expression with a constant value that equals a `MemoryOrder` constant */ +class MemoryOrderConstantExpr extends Expr { + MemoryOrder ord; + + MemoryOrderConstantExpr() { + if + this instanceof MemoryOrderConstantAccess + then + ord = this.(MemoryOrderConstantAccess).getTarget() + else + ord.getIntValue() = getValue().toInt() + } + + /* Get the name of the `MemoryOrder` this expression is valued as. */ + string getMemoryOrderString() { + result = ord.toString() + } +} + +/** + * A `stdatomic.h` function which accepts a `memory_order` value as a parameter. + */ +class MemoryOrderedStdAtomicFunction extends Function { + int orderParamIdx; + + MemoryOrderedStdAtomicFunction() { + exists(int baseParamIdx, int baseParams, string prefix, string suffix | + prefix = ["__", "__c11_"] and + suffix = ["", ".*", "_explicit"] and + ( + getName().regexpMatch(prefix + ["atomic_thread_fence", "atomic_signal_fence"] + suffix) and + baseParamIdx = 0 and + baseParams = 1 + or + getName() + .regexpMatch(prefix + ["atomic_load", "atomic_flag_clear", "atomic_flag_test_and_set"] + + suffix) and + baseParamIdx = 1 and + baseParams = 2 + or + getName().regexpMatch(prefix + ["atomic_store", "atomic_fetch_.*", "atomic_exchange"] + suffix) and + baseParamIdx = 2 and + baseParams = 3 + or + getName().regexpMatch(prefix + "atomic_compare_exchange_.*" + suffix) and + baseParamIdx = [3, 4] and + baseParams = 5 + ) and + ( + // GCC case, may have one or two inserted parameters, e.g.: + // __atomic_load(8, &repr->a, &desired, order) + // or + // __atomic_load_8(&repr->a, &desired, order) + prefix = "__" and + suffix = ".*" and + exists(int extraParams | + extraParams = getNumberOfParameters() - baseParams and + extraParams >= 0 and + orderParamIdx = baseParamIdx + extraParams + ) + or + // Clang case, no inserted parameters: + // __c11_atomic_load(object, order) + suffix = "" and + prefix = "__c11_" and + orderParamIdx = baseParamIdx + or + // Non-macro case, may occur in a subset of gcc/clang functions: + prefix = "" and + suffix = "_explicit" and + orderParamIdx = baseParamIdx + ) + ) + } + + int getOrderParameterIdx() { result = orderParamIdx } +} + +module MemoryOrderFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { + // Direct usage of memory order constant + exists(MemoryOrderConstantAccess constant | + node.asExpr() = constant and + not constant.isAllowedOrder() + ) + or + // A literal with a disallowed constant integer value + exists(Literal literal | + node.asExpr() = literal and + not literal.getValue().toInt() = any(AllowedMemoryOrder a).getValue().toInt() + ) + or + // Everything else: not a memory order constant or an integer valued literal, also exclude + // variables and functions, things that flow further back. + exists(Expr e | + node.asExpr() = e and + not e instanceof MemoryOrderConstantAccess and + not e instanceof Literal and + not e instanceof VariableAccess and + not e instanceof FunctionCall and + not DataFlow::localFlowStep(_, node) + ) + } + + predicate isSink(DataFlow::Node node) { + exists(FunctionCall fc | + node.asExpr() = + fc.getArgument(fc.getTarget().(MemoryOrderedStdAtomicFunction).getOrderParameterIdx()) + ) + } +} + +module MemoryOrderFlow = DataFlow::Global; + +import MemoryOrderFlow::PathGraph + +/** + * If the node is a memory order constant, or shares a value with a memory order constant, then + * return the name of that cnonstant. Otherwise, simply print the node. + */ +string describeMemoryOrderNode(DataFlow::Node node) { + if node.asExpr() instanceof MemoryOrderConstantExpr + then result = node.asExpr().(MemoryOrderConstantExpr).getMemoryOrderString() + else result = node.toString() +} + +from + Expr argument, Function function, string value, MemoryOrderFlow::PathNode source, + MemoryOrderFlow::PathNode sink +where + not isExcluded(argument, Concurrency6Package::invalidMemoryOrderArgumentQuery()) and + MemoryOrderFlow::flowPath(source, sink) and + argument = sink.getNode().asExpr() and + value = describeMemoryOrderNode(source.getNode()) and + // Double check that we didn't find flow from something equivalent to the allowed value. + not value = any(AllowedMemoryOrder e).getName() and + function.getACallToThisFunction().getAnArgument() = argument +select argument, source, sink, "Invalid memory order '$@' in call to function '$@'.", value, value, + function, function.toString() diff --git a/c/misra/src/rules/RULE-22-11/ThreadPreviouslyJoinedOrDetached.ql b/c/misra/src/rules/RULE-22-11/ThreadPreviouslyJoinedOrDetached.ql new file mode 100644 index 0000000000..1a6476b1a7 --- /dev/null +++ b/c/misra/src/rules/RULE-22-11/ThreadPreviouslyJoinedOrDetached.ql @@ -0,0 +1,24 @@ +/** + * @id c/misra/thread-previously-joined-or-detached + * @name RULE-22-11: A thread that was previously either joined or detached shall not be subsequently joined nor detached + * @description Joining or detaching a previously joined or detached thread can lead to undefined + * program behavior. + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-22-11 + * external/misra/c/2012/amendment4 + * correctness + * concurrency + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.rules.joinordetachthreadonlyonce.JoinOrDetachThreadOnlyOnce + +class ThreadPreviouslyJoinedOrDetachedQuery extends JoinOrDetachThreadOnlyOnceSharedQuery { + ThreadPreviouslyJoinedOrDetachedQuery() { + this = Concurrency6Package::threadPreviouslyJoinedOrDetachedQuery() + } +} diff --git a/c/misra/test/rules/DIR-5-2/NotNoDeadlocksBetweenThreads.testref b/c/misra/test/rules/DIR-5-2/NotNoDeadlocksBetweenThreads.testref new file mode 100644 index 0000000000..4625d1a24d --- /dev/null +++ b/c/misra/test/rules/DIR-5-2/NotNoDeadlocksBetweenThreads.testref @@ -0,0 +1 @@ +c/common/test/rules/preventdeadlockbylockinginpredefinedorder/PreventDeadlockByLockingInPredefinedOrder.ql \ No newline at end of file diff --git a/c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.expected b/c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.expected new file mode 100644 index 0000000000..ff829918fd --- /dev/null +++ b/c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.expected @@ -0,0 +1,16 @@ +| test.c:37:3:37:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:36:6:36:34 | make_threads_called_from_main | make_threads_called_from_main | +| test.c:38:3:38:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:36:6:36:34 | make_threads_called_from_main | make_threads_called_from_main | +| test.c:46:3:46:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:45:6:45:51 | make_threads_called_from_func_called_from_main | make_threads_called_from_func_called_from_main | +| test.c:47:3:47:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:45:6:45:51 | make_threads_called_from_func_called_from_main | make_threads_called_from_func_called_from_main | +| test.c:56:3:56:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | +| test.c:57:3:57:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | +| test.c:65:3:65:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | +| test.c:66:3:66:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | +| test.c:74:3:74:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:73:6:73:39 | make_threads_called_from_thrd_func | make_threads_called_from_thrd_func | +| test.c:75:3:75:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:73:6:73:39 | make_threads_called_from_thrd_func | make_threads_called_from_thrd_func | +| test.c:83:3:83:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:82:6:82:59 | make_threads_called_from_func_called_from_pthread_thrd | make_threads_called_from_func_called_from_pthread_thrd | +| test.c:84:3:84:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:82:6:82:59 | make_threads_called_from_func_called_from_pthread_thrd | make_threads_called_from_func_called_from_pthread_thrd | +| test.c:88:3:88:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:87:6:87:47 | make_threads_called_from_main_pthread_thrd | make_threads_called_from_main_pthread_thrd | +| test.c:89:3:89:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:87:6:87:47 | make_threads_called_from_main_pthread_thrd | make_threads_called_from_main_pthread_thrd | +| test.c:93:3:93:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:92:6:92:38 | make_threads_not_called_by_anyone | make_threads_not_called_by_anyone | +| test.c:94:3:94:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:92:6:92:38 | make_threads_not_called_by_anyone | make_threads_not_called_by_anyone | diff --git a/c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.qlref b/c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.qlref new file mode 100644 index 0000000000..16c9614cec --- /dev/null +++ b/c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.qlref @@ -0,0 +1 @@ +rules/DIR-5-3/BannedDynamicThreadCreation.ql \ No newline at end of file diff --git a/c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.expected b/c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.expected new file mode 100644 index 0000000000..74be75ffeb --- /dev/null +++ b/c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.expected @@ -0,0 +1,14 @@ +| test.c:56:3:56:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | +| test.c:57:3:57:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | +| test.c:65:3:65:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | +| test.c:66:3:66:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | +| test.c:74:3:74:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | +| test.c:75:3:75:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | +| test.c:83:3:83:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | +| test.c:83:3:83:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | +| test.c:84:3:84:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | +| test.c:84:3:84:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | +| test.c:88:3:88:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | +| test.c:88:3:88:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | +| test.c:89:3:89:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | +| test.c:89:3:89:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | diff --git a/c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.qlref b/c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.qlref new file mode 100644 index 0000000000..99cecb8311 --- /dev/null +++ b/c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.qlref @@ -0,0 +1 @@ +rules/DIR-5-3/ThreadCreatedByThread.ql \ No newline at end of file diff --git a/c/misra/test/rules/DIR-5-3/test.c b/c/misra/test/rules/DIR-5-3/test.c new file mode 100644 index 0000000000..294f79a276 --- /dev/null +++ b/c/misra/test/rules/DIR-5-3/test.c @@ -0,0 +1,95 @@ +#include "threads.h" +#include "pthread.h" + +thrd_t g1; // COMPLIANT +pthread_t g2; // COMPLIANT +thrd_t g3[10]; // COMPLIANT +pthread_t g4[10]; // COMPLIANT + +struct { + thrd_t m1; // COMPLIANT + pthread_t m2; // COMPLIANT +} g7; + +void* pthread_func(void* arg); +int thrd_func(void* arg); + +void make_threads_called_from_main(void); +void func_called_from_main(void); +void make_threads_called_from_func_called_from_main(void); +void make_threads_called_from_main_pthread_thrd(void); + +void main() { + // Main starting top level threads -- ok. + thrd_create(&g1, &thrd_func, NULL); // COMPLIANT + pthread_create(&g2, NULL, &pthread_func, NULL); // COMPLIANT + + // Starting thread in pool -- ok. + thrd_create(&g3[0], &thrd_func, NULL); // COMPLIANT + pthread_create(&g4[0], NULL, &pthread_func, NULL); // COMPLIANT + + make_threads_called_from_main(); + func_called_from_main(); + make_threads_called_from_main_pthread_thrd(); +} + +void make_threads_called_from_main() { + thrd_create(&g3[0], &thrd_func, NULL); // COMPLIANT + pthread_create(&g4[0], NULL, &pthread_func, NULL); // COMPLIANT +} + +void func_called_from_main() { + make_threads_called_from_func_called_from_main(); +} + +void make_threads_called_from_func_called_from_main() { + thrd_create(&g3[0], &thrd_func, NULL); // COMPLIANT + pthread_create(&g4[0], NULL, &pthread_func, NULL); // COMPLIANT +} + +void make_threads_called_from_pthread_func(void); +void make_threads_called_from_thrd_func(void); +void func_called_from_pthread_thrd(void); +void make_threads_called_from_func_called_from_pthread_thrd(void); + +void* pthread_func(void* arg) { + thrd_create(&g3[0], &thrd_func, NULL); // NON-COMPLIANT + pthread_create(&g4[0], NULL, &pthread_func, NULL); // NON-COMPLIANT + + make_threads_called_from_pthread_func(); + func_called_from_pthread_thrd(); + make_threads_called_from_main_pthread_thrd(); +} + +int thrd_func(void* arg) { + thrd_create(&g3[0], &thrd_func, NULL); // NON-COMPLIANT + pthread_create(&g4[0], NULL, &pthread_func, NULL); // NON-COMPLIANT + + make_threads_called_from_thrd_func(); + func_called_from_pthread_thrd(); + make_threads_called_from_main_pthread_thrd(); +} + +void make_threads_called_from_thrd_func(void) { + thrd_create(&g3[0], &thrd_func, NULL); // NON-COMPLIANT + pthread_create(&g4[0], NULL, &pthread_func, NULL); // NON-COMPLIANT +} + +void func_called_from_pthread_thrd(void) { + make_threads_called_from_func_called_from_pthread_thrd(); +} + +void make_threads_called_from_func_called_from_pthread_thrd(void) { + thrd_create(&g3[0], &thrd_func, NULL); // NON-COMPLIANT + pthread_create(&g4[0], NULL, &pthread_func, NULL); // NON-COMPLIANT +} + +void make_threads_called_from_main_pthread_thrd() { + thrd_create(&g3[0], &thrd_func, NULL); // NON-COMPLIANT + pthread_create(&g4[0], NULL, &pthread_func, NULL); // NON-COMPLIANT +} + +void make_threads_not_called_by_anyone() { + thrd_create(&g3[0], &thrd_func, NULL); // COMPLIANT + pthread_create(&g4[0], NULL, &pthread_func, NULL); // COMPLIANT +} diff --git a/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.expected b/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.expected new file mode 100644 index 0000000000..02159bef69 --- /dev/null +++ b/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.expected @@ -0,0 +1,4 @@ +| test.c:41:13:41:13 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | +| test.c:42:18:42:18 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | +| test.c:43:13:43:13 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | +| test.c:44:18:44:18 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | diff --git a/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.qlref b/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.qlref new file mode 100644 index 0000000000..2196eeace1 --- /dev/null +++ b/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.qlref @@ -0,0 +1 @@ +rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-12-6/test.c b/c/misra/test/rules/RULE-12-6/test.c new file mode 100644 index 0000000000..2b1eeb7568 --- /dev/null +++ b/c/misra/test/rules/RULE-12-6/test.c @@ -0,0 +1,59 @@ +#include "stdatomic.h" +#include "string.h" + +typedef struct s2 { + int x; +} s1; + +_Atomic s1 atomic_s1; +// A non-atomic pointer to an atomic s1 +_Atomic s1 *ptr_atomic_s1; +// An atomic pointer to a non-atomic s1 +s1 *_Atomic s1_atomic_ptr; + +_Atomic int g3; + +void takeCopy(s1 p1); + +void f1() { + s1 *l1; + l1 = atomic_load(&atomic_s1); // COMPLIANT + l1 = atomic_load(ptr_atomic_s1); // COMPLIANT + l1 = atomic_load(&s1_atomic_ptr); // COMPLIANT + l1->x = 4; // COMPLIANT + atomic_store(&atomic_s1, l1); // COMPLIANT + atomic_store(ptr_atomic_s1, l1); // COMPLIANT + atomic_store(&s1_atomic_ptr, l1); // COMPLIANT + + // Undefined behavior, but not banned by this rule. + memset(&atomic_s1, sizeof(atomic_s1), 0); // COMPLIANT + memset(ptr_atomic_s1, sizeof(*ptr_atomic_s1), 0); // COMPLIANT + + // OK: whole loads and stores are protected from data-races. + takeCopy(atomic_s1); // COMPLIANT + takeCopy(*ptr_atomic_s1); // COMPLIANT + atomic_s1 = (s1){0}; // COMPLIANT + *ptr_atomic_s1 = (s1){0}; // COMPLIANT + atomic_s1 = *l1; // COMPLIANT + ptr_atomic_s1 = l1; // COMPLIANT + + // Banned: circumvents data-race protection, results in UB. + atomic_s1.x; // NON-COMPLIANT + ptr_atomic_s1->x; // NON-COMPLIANT + atomic_s1.x = 0; // NON-COMPLIANT + ptr_atomic_s1->x = 0; // NON-COMPLIANT + + // OK: not evaluated. + sizeof(atomic_s1); // COMPLIANT + sizeof(ptr_atomic_s1); // COMPLIANT + sizeof(atomic_s1.x); // COMPLIANT + sizeof(ptr_atomic_s1->x); // COMPLIANT + + // All OK: not an atomic struct, but rather an atomic pointer to non-atomic + // struct. + memset(s1_atomic_ptr, sizeof(*s1_atomic_ptr), 0); // COMPLIANT + takeCopy(*s1_atomic_ptr); // COMPLIANT + *s1_atomic_ptr = (s1){0}; // COMPLIANT + s1_atomic_ptr = l1; // COMPLIANT + s1_atomic_ptr->x; // COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected b/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected new file mode 100644 index 0000000000..07229ff975 --- /dev/null +++ b/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected @@ -0,0 +1,99 @@ +edges +| test.c:4:5:4:6 | *g2 | test.c:53:33:53:34 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:54:29:54:30 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:55:42:55:43 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:56:35:56:36 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:57:36:57:37 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:58:54:58:55 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:59:58:59:59 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:60:52:60:53 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:61:56:61:57 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:62:37:62:38 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:63:37:63:38 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:64:36:64:37 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:65:37:65:38 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:66:37:66:38 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:67:23:67:24 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:68:23:68:24 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:71:23:71:24 | g2 | provenance | | +| test.c:4:10:4:29 | memory_order_relaxed | test.c:4:5:4:6 | *g2 | provenance | | +| test.c:5:5:5:6 | *g3 | test.c:72:23:72:24 | g3 | provenance | | +| test.c:5:10:5:29 | memory_order_acquire | test.c:5:5:5:6 | *g3 | provenance | | +| test.c:6:5:6:6 | *g4 | test.c:73:23:73:24 | g4 | provenance | | +| test.c:6:10:6:29 | memory_order_consume | test.c:6:5:6:6 | *g4 | provenance | | +| test.c:7:5:7:6 | *g5 | test.c:74:23:74:24 | g5 | provenance | | +| test.c:7:10:7:29 | memory_order_acq_rel | test.c:7:5:7:6 | *g5 | provenance | | +| test.c:8:5:8:6 | *g6 | test.c:75:23:75:24 | g6 | provenance | | +| test.c:8:10:8:29 | memory_order_release | test.c:8:5:8:6 | *g6 | provenance | | +nodes +| test.c:4:5:4:6 | *g2 | semmle.label | *g2 | +| test.c:4:10:4:29 | memory_order_relaxed | semmle.label | memory_order_relaxed | +| test.c:5:5:5:6 | *g3 | semmle.label | *g3 | +| test.c:5:10:5:29 | memory_order_acquire | semmle.label | memory_order_acquire | +| test.c:6:5:6:6 | *g4 | semmle.label | *g4 | +| test.c:6:10:6:29 | memory_order_consume | semmle.label | memory_order_consume | +| test.c:7:5:7:6 | *g5 | semmle.label | *g5 | +| test.c:7:10:7:29 | memory_order_acq_rel | semmle.label | memory_order_acq_rel | +| test.c:8:5:8:6 | *g6 | semmle.label | *g6 | +| test.c:8:10:8:29 | memory_order_release | semmle.label | memory_order_release | +| test.c:16:29:16:48 | memory_order_relaxed | semmle.label | memory_order_relaxed | +| test.c:17:29:17:48 | memory_order_acquire | semmle.label | memory_order_acquire | +| test.c:18:29:18:48 | memory_order_consume | semmle.label | memory_order_consume | +| test.c:19:29:19:48 | memory_order_acq_rel | semmle.label | memory_order_acq_rel | +| test.c:20:29:20:48 | memory_order_release | semmle.label | memory_order_release | +| test.c:53:33:53:34 | g2 | semmle.label | g2 | +| test.c:54:29:54:30 | g2 | semmle.label | g2 | +| test.c:55:42:55:43 | g2 | semmle.label | g2 | +| test.c:56:35:56:36 | g2 | semmle.label | g2 | +| test.c:57:36:57:37 | g2 | semmle.label | g2 | +| test.c:58:54:58:55 | g2 | semmle.label | g2 | +| test.c:59:58:59:59 | g2 | semmle.label | g2 | +| test.c:60:52:60:53 | g2 | semmle.label | g2 | +| test.c:61:56:61:57 | g2 | semmle.label | g2 | +| test.c:62:37:62:38 | g2 | semmle.label | g2 | +| test.c:63:37:63:38 | g2 | semmle.label | g2 | +| test.c:64:36:64:37 | g2 | semmle.label | g2 | +| test.c:65:37:65:38 | g2 | semmle.label | g2 | +| test.c:66:37:66:38 | g2 | semmle.label | g2 | +| test.c:67:23:67:24 | g2 | semmle.label | g2 | +| test.c:68:23:68:24 | g2 | semmle.label | g2 | +| test.c:71:23:71:24 | g2 | semmle.label | g2 | +| test.c:72:23:72:24 | g3 | semmle.label | g3 | +| test.c:73:23:73:24 | g4 | semmle.label | g4 | +| test.c:74:23:74:24 | g5 | semmle.label | g5 | +| test.c:75:23:75:24 | g6 | semmle.label | g6 | +| test.c:78:23:78:46 | ... * ... | semmle.label | ... * ... | +| test.c:79:23:79:23 | 1 | semmle.label | 1 | +| test.c:80:23:80:25 | 100 | semmle.label | 100 | +| test.c:81:23:81:28 | ... + ... | semmle.label | ... + ... | +subpaths +#select +| test.c:16:29:16:48 | memory_order_relaxed | test.c:16:29:16:48 | memory_order_relaxed | test.c:16:29:16:48 | memory_order_relaxed | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_load | __c11_atomic_load | +| test.c:17:29:17:48 | memory_order_acquire | test.c:17:29:17:48 | memory_order_acquire | test.c:17:29:17:48 | memory_order_acquire | Invalid memory order '$@' in call to function '$@'. | memory_order_acquire | memory_order_acquire | file://:0:0:0:0 | __c11_atomic_load | __c11_atomic_load | +| test.c:18:29:18:48 | memory_order_consume | test.c:18:29:18:48 | memory_order_consume | test.c:18:29:18:48 | memory_order_consume | Invalid memory order '$@' in call to function '$@'. | memory_order_consume | memory_order_consume | file://:0:0:0:0 | __c11_atomic_load | __c11_atomic_load | +| test.c:19:29:19:48 | memory_order_acq_rel | test.c:19:29:19:48 | memory_order_acq_rel | test.c:19:29:19:48 | memory_order_acq_rel | Invalid memory order '$@' in call to function '$@'. | memory_order_acq_rel | memory_order_acq_rel | file://:0:0:0:0 | __c11_atomic_load | __c11_atomic_load | +| test.c:20:29:20:48 | memory_order_release | test.c:20:29:20:48 | memory_order_release | test.c:20:29:20:48 | memory_order_release | Invalid memory order '$@' in call to function '$@'. | memory_order_release | memory_order_release | file://:0:0:0:0 | __c11_atomic_load | __c11_atomic_load | +| test.c:53:33:53:34 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:53:33:53:34 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_store | __c11_atomic_store | +| test.c:54:29:54:30 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:54:29:54:30 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_load | __c11_atomic_load | +| test.c:55:42:55:43 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:55:42:55:43 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_exchange | __c11_atomic_exchange | +| test.c:56:35:56:36 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:56:35:56:36 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_store | __c11_atomic_store | +| test.c:57:36:57:37 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:57:36:57:37 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_exchange | __c11_atomic_exchange | +| test.c:58:54:58:55 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:58:54:58:55 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_compare_exchange_strong | __c11_atomic_compare_exchange_strong | +| test.c:59:58:59:59 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:59:58:59:59 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_compare_exchange_strong | __c11_atomic_compare_exchange_strong | +| test.c:60:52:60:53 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:60:52:60:53 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_compare_exchange_weak | __c11_atomic_compare_exchange_weak | +| test.c:61:56:61:57 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:61:56:61:57 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_compare_exchange_weak | __c11_atomic_compare_exchange_weak | +| test.c:62:37:62:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:62:37:62:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_fetch_add | __c11_atomic_fetch_add | +| test.c:63:37:63:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:63:37:63:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_fetch_sub | __c11_atomic_fetch_sub | +| test.c:64:36:64:37 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:64:36:64:37 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_fetch_or | __c11_atomic_fetch_or | +| test.c:65:37:65:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:65:37:65:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_fetch_xor | __c11_atomic_fetch_xor | +| test.c:66:37:66:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:66:37:66:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_fetch_and | __c11_atomic_fetch_and | +| test.c:67:23:67:24 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:67:23:67:24 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | +| test.c:68:23:68:24 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:68:23:68:24 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_signal_fence | __c11_atomic_signal_fence | +| test.c:71:23:71:24 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:71:23:71:24 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | +| test.c:72:23:72:24 | g3 | test.c:5:10:5:29 | memory_order_acquire | test.c:72:23:72:24 | g3 | Invalid memory order '$@' in call to function '$@'. | memory_order_acquire | memory_order_acquire | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | +| test.c:73:23:73:24 | g4 | test.c:6:10:6:29 | memory_order_consume | test.c:73:23:73:24 | g4 | Invalid memory order '$@' in call to function '$@'. | memory_order_consume | memory_order_consume | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | +| test.c:74:23:74:24 | g5 | test.c:7:10:7:29 | memory_order_acq_rel | test.c:74:23:74:24 | g5 | Invalid memory order '$@' in call to function '$@'. | memory_order_acq_rel | memory_order_acq_rel | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | +| test.c:75:23:75:24 | g6 | test.c:8:10:8:29 | memory_order_release | test.c:75:23:75:24 | g6 | Invalid memory order '$@' in call to function '$@'. | memory_order_release | memory_order_release | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | +| test.c:79:23:79:23 | 1 | test.c:79:23:79:23 | 1 | test.c:79:23:79:23 | 1 | Invalid memory order '$@' in call to function '$@'. | memory_order_consume | memory_order_consume | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | +| test.c:80:23:80:25 | 100 | test.c:80:23:80:25 | 100 | test.c:80:23:80:25 | 100 | Invalid memory order '$@' in call to function '$@'. | 100 | 100 | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | +| test.c:81:23:81:28 | ... + ... | test.c:81:23:81:28 | ... + ... | test.c:81:23:81:28 | ... + ... | Invalid memory order '$@' in call to function '$@'. | ... + ... | ... + ... | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | diff --git a/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.qlref b/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.qlref new file mode 100644 index 0000000000..5c205adc24 --- /dev/null +++ b/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.qlref @@ -0,0 +1 @@ +rules/RULE-21-25/InvalidMemoryOrderArgument.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-25/test.c b/c/misra/test/rules/RULE-21-25/test.c new file mode 100644 index 0000000000..51df24555c --- /dev/null +++ b/c/misra/test/rules/RULE-21-25/test.c @@ -0,0 +1,85 @@ +#include "stdatomic.h" + +int g1 = memory_order_seq_cst; +int g2 = memory_order_relaxed; +int g3 = memory_order_acquire; +int g4 = memory_order_consume; +int g5 = memory_order_acq_rel; +int g6 = memory_order_release; + +void f(int p) { + _Atomic int l1; + atomic_flag l2; + + // Directly specified values: + atomic_load_explicit(&l1, memory_order_seq_cst); // COMPLIANT + atomic_load_explicit(&l1, memory_order_relaxed); // NON-COMPLIANT + atomic_load_explicit(&l1, memory_order_acquire); // NON-COMPLIANT + atomic_load_explicit(&l1, memory_order_consume); // NON-COMPLIANT + atomic_load_explicit(&l1, memory_order_acq_rel); // NON-COMPLIANT + atomic_load_explicit(&l1, memory_order_release); // NON-COMPLIANT + + // Implicit values: + atomic_store(&l1, 0); // COMPLIANT + atomic_load(&l1); // COMPLIANT + atomic_flag_test_and_set(&l2); // COMPLIANT + atomic_flag_clear(&l2); // COMPLIANT + atomic_exchange(&l1, 0); // COMPLIANT + atomic_compare_exchange_strong(&l1, 0, 1); // COMPLIANT + atomic_compare_exchange_weak(&l1, 0, 1); // COMPLIANT + atomic_fetch_add(&l1, 0); // COMPLIANT + atomic_fetch_sub(&l1, 0); // COMPLIANT + atomic_fetch_or(&l1, 0); // COMPLIANT + atomic_fetch_xor(&l1, 0); // COMPLIANT + atomic_fetch_and(&l1, 0); // COMPLIANT + + // Compliant flowed values (one test per sink): + atomic_store_explicit(&l1, 0, g1); // COMPLIANT + atomic_load_explicit(&l1, g1); // COMPLIANT + atomic_flag_test_and_set_explicit(&l2, g1); // COMPLIANT + atomic_flag_clear_explicit(&l2, g1); // COMPLIANT + atomic_exchange_explicit(&l1, 0, g1); // COMPLIANT + atomic_compare_exchange_strong_explicit(&l1, 0, 1, g1, g1); // COMPLIANT + atomic_compare_exchange_weak_explicit(&l1, 0, 1, g1, g1); // COMPLIANT + atomic_fetch_add_explicit(&l1, 0, g1); // COMPLIANT + atomic_fetch_sub_explicit(&l1, 0, g1); // COMPLIANT + atomic_fetch_or_explicit(&l1, 0, g1); // COMPLIANT + atomic_fetch_xor_explicit(&l1, 0, g1); // COMPLIANT + atomic_fetch_and_explicit(&l1, 0, g1); // COMPLIANT + atomic_thread_fence(g1); // COMPLIANT + atomic_signal_fence(g1); // COMPLIANT + + // Non-compliant flowed values (one test per sink): + atomic_store_explicit(&l1, 0, g2); // NON-COMPLIANT + atomic_load_explicit(&l1, g2); // NON-COMPLIANT + atomic_flag_test_and_set_explicit(&l2, g2); // NON-COMPLIANT + atomic_flag_clear_explicit(&l2, g2); // NON-COMPLIANT + atomic_exchange_explicit(&l1, 0, g2); // NON-COMPLIANT + atomic_compare_exchange_strong_explicit(&l1, 0, 1, g2, g1); // NON-COMPLIANT + atomic_compare_exchange_strong_explicit(&l1, 0, 1, g1, g2); // NON-COMPLIANT + atomic_compare_exchange_weak_explicit(&l1, 0, 1, g2, g1); // NON-COMPLIANT + atomic_compare_exchange_weak_explicit(&l1, 0, 1, g1, g2); // NON-COMPLIANT + atomic_fetch_add_explicit(&l1, 0, g2); // NON-COMPLIANT + atomic_fetch_sub_explicit(&l1, 0, g2); // NON-COMPLIANT + atomic_fetch_or_explicit(&l1, 0, g2); // NON-COMPLIANT + atomic_fetch_xor_explicit(&l1, 0, g2); // NON-COMPLIANT + atomic_fetch_and_explicit(&l1, 0, g2); // NON-COMPLIANT + atomic_thread_fence(g2); // NON-COMPLIANT + atomic_signal_fence(g2); // NON-COMPLIANT + + // Non-compliant flowed values (one test per source): + atomic_thread_fence(g2); // NON-COMPLIANT + atomic_thread_fence(g3); // NON-COMPLIANT + atomic_thread_fence(g4); // NON-COMPLIANT + atomic_thread_fence(g5); // NON-COMPLIANT + atomic_thread_fence(g6); // NON-COMPLIANT + + // Computed flow sources: + atomic_thread_fence(memory_order_seq_cst * 1); // COMPLIANT + atomic_thread_fence(1); // NON-COMPLIANT + atomic_thread_fence(100); // NON-COMPLIANT + atomic_thread_fence(g1 + 1); // NON-COMPLIANT + + // No unsafe flow, currently accepted: + atomic_thread_fence(p); // COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-11/ThreadPreviouslyJoinedOrDetached.testref b/c/misra/test/rules/RULE-22-11/ThreadPreviouslyJoinedOrDetached.testref new file mode 100644 index 0000000000..61fa88fd08 --- /dev/null +++ b/c/misra/test/rules/RULE-22-11/ThreadPreviouslyJoinedOrDetached.testref @@ -0,0 +1 @@ +c/common/test/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-11/ThreadWasPreviouslyJoinedOrDetached.testref b/c/misra/test/rules/RULE-22-11/ThreadWasPreviouslyJoinedOrDetached.testref new file mode 100644 index 0000000000..61fa88fd08 --- /dev/null +++ b/c/misra/test/rules/RULE-22-11/ThreadWasPreviouslyJoinedOrDetached.testref @@ -0,0 +1 @@ +c/common/test/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.ql \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/Concurrency.qll b/cpp/common/src/codingstandards/cpp/Concurrency.qll index d856fa4515..ed7519dd5d 100644 --- a/cpp/common/src/codingstandards/cpp/Concurrency.qll +++ b/cpp/common/src/codingstandards/cpp/Concurrency.qll @@ -48,19 +48,38 @@ class ThreadConstructorCall extends ConstructorCall, ThreadCreationFunction { } /** - * Models a call to a thread constructor via `thrd_create`. + * Models a call to a thread creation via `thrd_create` or `pthread_create`. */ -class C11ThreadCreateCall extends ThreadCreationFunction { +class CThreadCreateCall extends FunctionCall { Function f; + int fArgIdx; - C11ThreadCreateCall() { - getTarget().getName() = "thrd_create" and + CThreadCreateCall() { + ( + getTarget().getName() = "thrd_create" and + fArgIdx = 1 + or + getTarget().getName() = "pthread_create" and + fArgIdx = 2 + ) and ( - f = getArgument(1).(FunctionAccess).getTarget() or - f = getArgument(1).(AddressOfExpr).getOperand().(FunctionAccess).getTarget() + f = getArgument(fArgIdx).(FunctionAccess).getTarget() or + f = getArgument(fArgIdx).(AddressOfExpr).getOperand().(FunctionAccess).getTarget() ) } + /** + * Returns the function that will be invoked by this thread. + */ + Function getFunction() { result = f } +} + +/** + * Models a call to a thread constructor via `thrd_create`. + */ +class C11ThreadCreateCall extends ThreadCreationFunction, CThreadCreateCall { + C11ThreadCreateCall() { getTarget().getName() = "thrd_create" } + /** * Returns the function that will be invoked by this thread. */ diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency6.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency6.qll new file mode 100644 index 0000000000..62d9f362fe --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency6.qll @@ -0,0 +1,112 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype Concurrency6Query = + TNotNoDeadlocksBetweenThreadsQuery() or + TThreadCreatedByThreadQuery() or + TBannedDynamicThreadCreationQuery() or + TAtomicAggregateObjectDirectlyAccessedQuery() or + TInvalidMemoryOrderArgumentQuery() or + TThreadPreviouslyJoinedOrDetachedQuery() + +predicate isConcurrency6QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `notNoDeadlocksBetweenThreads` query + Concurrency6Package::notNoDeadlocksBetweenThreadsQuery() and + queryId = + // `@id` for the `notNoDeadlocksBetweenThreads` query + "c/misra/not-no-deadlocks-between-threads" and + ruleId = "DIR-5-2" and + category = "required" + or + query = + // `Query` instance for the `threadCreatedByThread` query + Concurrency6Package::threadCreatedByThreadQuery() and + queryId = + // `@id` for the `threadCreatedByThread` query + "c/misra/thread-created-by-thread" and + ruleId = "DIR-5-3" and + category = "required" + or + query = + // `Query` instance for the `bannedDynamicThreadCreation` query + Concurrency6Package::bannedDynamicThreadCreationQuery() and + queryId = + // `@id` for the `bannedDynamicThreadCreation` query + "c/misra/banned-dynamic-thread-creation" and + ruleId = "DIR-5-3" and + category = "required" + or + query = + // `Query` instance for the `atomicAggregateObjectDirectlyAccessed` query + Concurrency6Package::atomicAggregateObjectDirectlyAccessedQuery() and + queryId = + // `@id` for the `atomicAggregateObjectDirectlyAccessed` query + "c/misra/atomic-aggregate-object-directly-accessed" and + ruleId = "RULE-12-6" and + category = "required" + or + query = + // `Query` instance for the `invalidMemoryOrderArgument` query + Concurrency6Package::invalidMemoryOrderArgumentQuery() and + queryId = + // `@id` for the `invalidMemoryOrderArgument` query + "c/misra/invalid-memory-order-argument" and + ruleId = "RULE-21-25" and + category = "required" + or + query = + // `Query` instance for the `threadPreviouslyJoinedOrDetached` query + Concurrency6Package::threadPreviouslyJoinedOrDetachedQuery() and + queryId = + // `@id` for the `threadPreviouslyJoinedOrDetached` query + "c/misra/thread-previously-joined-or-detached" and + ruleId = "RULE-22-11" and + category = "required" +} + +module Concurrency6Package { + Query notNoDeadlocksBetweenThreadsQuery() { + //autogenerate `Query` type + result = + // `Query` type for `notNoDeadlocksBetweenThreads` query + TQueryC(TConcurrency6PackageQuery(TNotNoDeadlocksBetweenThreadsQuery())) + } + + Query threadCreatedByThreadQuery() { + //autogenerate `Query` type + result = + // `Query` type for `threadCreatedByThread` query + TQueryC(TConcurrency6PackageQuery(TThreadCreatedByThreadQuery())) + } + + Query bannedDynamicThreadCreationQuery() { + //autogenerate `Query` type + result = + // `Query` type for `bannedDynamicThreadCreation` query + TQueryC(TConcurrency6PackageQuery(TBannedDynamicThreadCreationQuery())) + } + + Query atomicAggregateObjectDirectlyAccessedQuery() { + //autogenerate `Query` type + result = + // `Query` type for `atomicAggregateObjectDirectlyAccessed` query + TQueryC(TConcurrency6PackageQuery(TAtomicAggregateObjectDirectlyAccessedQuery())) + } + + Query invalidMemoryOrderArgumentQuery() { + //autogenerate `Query` type + result = + // `Query` type for `invalidMemoryOrderArgument` query + TQueryC(TConcurrency6PackageQuery(TInvalidMemoryOrderArgumentQuery())) + } + + Query threadPreviouslyJoinedOrDetachedQuery() { + //autogenerate `Query` type + result = + // `Query` type for `threadPreviouslyJoinedOrDetached` query + TQueryC(TConcurrency6PackageQuery(TThreadPreviouslyJoinedOrDetachedQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index 3833533d50..ca06ec0912 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -11,6 +11,7 @@ import Concurrency2 import Concurrency3 import Concurrency4 import Concurrency5 +import Concurrency6 import Contracts1 import Contracts2 import Contracts3 @@ -87,6 +88,7 @@ newtype TCQuery = TConcurrency3PackageQuery(Concurrency3Query q) or TConcurrency4PackageQuery(Concurrency4Query q) or TConcurrency5PackageQuery(Concurrency5Query q) or + TConcurrency6PackageQuery(Concurrency6Query q) or TContracts1PackageQuery(Contracts1Query q) or TContracts2PackageQuery(Contracts2Query q) or TContracts3PackageQuery(Contracts3Query q) or @@ -163,6 +165,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isConcurrency3QueryMetadata(query, queryId, ruleId, category) or isConcurrency4QueryMetadata(query, queryId, ruleId, category) or isConcurrency5QueryMetadata(query, queryId, ruleId, category) or + isConcurrency6QueryMetadata(query, queryId, ruleId, category) or isContracts1QueryMetadata(query, queryId, ruleId, category) or isContracts2QueryMetadata(query, queryId, ruleId, category) or isContracts3QueryMetadata(query, queryId, ruleId, category) or diff --git a/cpp/common/src/codingstandards/cpp/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.qll b/cpp/common/src/codingstandards/cpp/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.qll new file mode 100644 index 0000000000..5ccbe83c72 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.qll @@ -0,0 +1,49 @@ +/** + * Provides a library with a `problems` predicate for the following issue: + * Joining or detaching a previously joined or detached thread can lead to undefined + * program behavior. + */ + +import cpp +import codingstandards.cpp.Customizations +import codingstandards.cpp.Exclusions +import codingstandards.cpp.Concurrency + +abstract class JoinOrDetachThreadOnlyOnceSharedQuery extends Query { } + +Query getQuery() { result instanceof JoinOrDetachThreadOnlyOnceSharedQuery } + +// OK +// 1) Thread calls detach parent DOES NOT call join +// 2) Parent calls join, thread does NOT call detach() +// NOT OK +// 1) Thread calls detach, parent calls join +// 2) Thread calls detach twice, parent does not call join +// 3) Parent calls join twice, thread does not call detach +query predicate problems(C11ThreadCreateCall tcc, string message) { + not isExcluded(tcc, getQuery()) and + message = "Thread may call join or detach after the thread is joined or detached." and + ( + // Note: These cases can be simplified but they are presented like this for clarity + // case 1 - calls to `thrd_join` and `thrd_detach` within the parent or + // within the parent / child CFG. + exists(C11ThreadWait tw, C11ThreadDetach dt | + tw = getAThreadContextAwareSuccessor(tcc) and + dt = getAThreadContextAwareSuccessor(tcc) + ) + or + // case 2 - multiple calls to `thrd_detach` within the threaded CFG. + exists(C11ThreadDetach dt1, C11ThreadDetach dt2 | + dt1 = getAThreadContextAwareSuccessor(tcc) and + dt2 = getAThreadContextAwareSuccessor(tcc) and + not dt1 = dt2 + ) + or + // case 3 - multiple calls to `thrd_join` within the threaded CFG. + exists(C11ThreadWait tw1, C11ThreadWait tw2 | + tw1 = getAThreadContextAwareSuccessor(tcc) and + tw2 = getAThreadContextAwareSuccessor(tcc) and + not tw1 = tw2 + ) + ) +} diff --git a/rule_packages/c/Concurrency5.json b/rule_packages/c/Concurrency5.json index 67707201fd..0cef2d8b3a 100644 --- a/rule_packages/c/Concurrency5.json +++ b/rule_packages/c/Concurrency5.json @@ -12,6 +12,7 @@ "precision": "high", "severity": "error", "short_name": "ThreadWasPreviouslyJoinedOrDetached", + "shared_implementation_short_name": "JoinOrDetachThreadOnlyOnce", "tags": [ "correctness", "concurrency" diff --git a/rule_packages/c/Concurrency6.json b/rule_packages/c/Concurrency6.json new file mode 100644 index 0000000000..cfb793877e --- /dev/null +++ b/rule_packages/c/Concurrency6.json @@ -0,0 +1,132 @@ +{ + "MISRA-C-2012": { + "DIR-5-2": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Circular waits leading to thread deadlocks may be avoided by locking in a predefined order.", + "kind": "problem", + "name": "There shall be no deadlocks between threads", + "precision": "very-high", + "severity": "error", + "short_name": "NotNoDeadlocksBetweenThreads", + "shared_implementation_short_name": "PreventDeadlockByLockingInPredefinedOrder", + "tags": [ + "external/misra/c/2012/amendment4", + "correctness", + "concurrency" + ] + } + ], + "title": "There shall be no deadlocks between threads" + }, + "DIR-5-3": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Creating threads within threads creates uncertainty in program behavior and concurrency overhead costs.", + "kind": "problem", + "name": "Threads shall not be created by other threads", + "precision": "high", + "severity": "error", + "short_name": "ThreadCreatedByThread", + "tags": [ + "external/misra/c/2012/amendment4", + "correctness", + "maintainability", + "concurrency", + "performance" + ] + }, + { + "description": "Creating threads outside of a well-defined program start-up phase creates uncertainty in program behavior and concurrency overhead costs.", + "kind": "problem", + "name": "There shall be no dynamic thread creation", + "precision": "low", + "severity": "error", + "short_name": "BannedDynamicThreadCreation", + "tags": [ + "external/misra/c/2012/amendment4", + "external/misra/c/audit", + "correctness", + "maintainability", + "concurrency", + "performance" + ] + } + ], + "title": "There shall be no dynamic thread creation" + }, + "RULE-12-6": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Accessing a member of an atomic structure or union results in undefined behavior.", + "kind": "problem", + "name": "Structure and union members of atomic objects shall not be directly accessed", + "precision": "very-high", + "severity": "error", + "short_name": "AtomicAggregateObjectDirectlyAccessed", + "tags": [ + "external/misra/c/2012/amendment4", + "correctness", + "concurrency" + ] + } + ], + "title": "Structure and union members of atomic objects shall not be directly accessed" + }, + "RULE-21-25": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Only the memory ordering of 'memory_order_seq_cst' is fully portable and consistent.", + "kind": "path-problem", + "name": "All memory synchronization operations shall be executed in sequentially consistent order", + "precision": "very-high", + "severity": "error", + "short_name": "InvalidMemoryOrderArgument", + "tags": [ + "external/misra/c/2012/amendment4", + "correctness", + "concurrency" + ] + } + ], + "title": "All memory synchronization operations shall be executed in sequentially consistent order" + }, + "RULE-22-11": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Joining or detaching a previously joined or detached thread can lead to undefined program behavior.", + "kind": "problem", + "name": "A thread that was previously either joined or detached shall not be subsequently joined nor detached", + "precision": "high", + "severity": "error", + "short_name": "ThreadPreviouslyJoinedOrDetached", + "shared_implementation_short_name": "JoinOrDetachThreadOnlyOnce", + "tags": [ + "external/misra/c/2012/amendment4", + "correctness", + "concurrency" + ], + "implementation_scope": { + "description": "This query considers problematic usages of join and detach irrespective of the execution of the program and other synchronization and interprocess communication mechanisms that may be used." + } + } + ], + "title": "A thread that was previously either joined or detached shall not be subsequently joined nor detached" + } + } +} \ No newline at end of file diff --git a/rules.csv b/rules.csv index 475ea1d66c..7648052954 100644 --- a/rules.csv +++ b/rules.csv @@ -617,7 +617,7 @@ c,MISRA-C-2012,DIR-4-12,Yes,Required,,,Dynamic memory allocation shall not be us c,MISRA-C-2012,DIR-4-13,No,Advisory,,,Functions which are designed to provide operations on a resource should be called in an appropriate sequence,,,,"Rule 22.1, 22.2 and 22.6 cover aspects of this rule. In other cases this is a design issue and needs to be checked manually." c,MISRA-C-2012,DIR-4-14,Yes,Required,,,The validity of values received from external sources shall be checked,,Contracts,Hard,This is supported by CodeQLs default C security queries. c,MISRA-C-2012,DIR-4-15,Yes,Required,,,Evaluation of floating-point expressions shall not lead to the undetected generation of infinities and NaNs,FLP32-C and FLP04-C,FloatingTypes2,Medium, -c,MISRA-C-2012,DIR-5-1,Yes,Required,,,There shall be no data races between threads,CON43-C and CON32-C,Concurrency6,Very Hard, +c,MISRA-C-2012,DIR-5-1,Yes,Required,,,There shall be no data races between threads,CON43-C and CON32-C,Concurrency7,Very Hard, c,MISRA-C-2012,DIR-5-2,Yes,Required,,,There shall be no deadlocks between threads,CON35-C,Concurrency6,Import, c,MISRA-C-2012,DIR-5-3,Yes,Required,,,There shall be no dynamic thread creation,,Concurrency6,Easy, c,MISRA-C-2012,RULE-1-1,No,Required,,,"The program shall contain no violations of the standard C syntax and constraints, and shall not exceed the implementation's translation limits",,,Easy,"This should be checked via the compiler output, rather than CodeQL, which adds unnecessary steps." @@ -678,7 +678,7 @@ c,MISRA-C-2012,RULE-9-3,Yes,Required,,,Arrays shall not be partially initialized 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,No,Required,,,Where designated initializers are used to initialize an array object the size of the array shall be specified explicitly,,,Medium, c,MISRA-C-2012,RULE-9-6,Yes,Required,,,An initializer using chained designators shall not contain initializers without designators,,Declarations9,Hard, -c,MISRA-C-2012,RULE-9-7,Yes,Mandatory,,,Atomic objects shall be appropriately initialized before being accessed,,Concurrency6,Hard, +c,MISRA-C-2012,RULE-9-7,Yes,Mandatory,,,Atomic objects shall be appropriately initialized before being accessed,,Concurrency7,Hard, c,MISRA-C-2012,RULE-10-1,Yes,Required,,,Operands shall not be of an inappropriate essential type,,EssentialTypes,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,,EssentialTypes,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,,EssentialTypes,Hard, @@ -790,8 +790,8 @@ c,MISRA-C-2012,RULE-21-21,Yes,Required,,,The Standard Library function system of c,MISRA-C-2012,RULE-21-22,Yes,Mandatory,,,All operand arguments to any type-generic macros in shall have an appropriate essential type,EXP37-C,EssentialTypes2,Hard, c,MISRA-C-2012,RULE-21-23,Yes,Required,,,All operand arguments to any multi-argument type-generic macros in shall have the same standard type,Rule-21-22,EssentialTypes2,Easy, c,MISRA-C-2012,RULE-21-24,Yes,Required,,,The random number generator functions of shall not be used,MSC30-C,Banned2,Easy, -c,MISRA-C-2012,RULE-21-25,Yes,Required,,,All memory synchronization operations shall be executed in sequentially consistent order,,Concurrency6,Medium, -c,MISRA-C-2012,RULE-21-26,Yes,Required,,,The Standard Library function mtx_timedlock() shall only be invoked on mutex objects of appropriate mutex type,,Concurrency6,Hard, +c,MISRA-C-2012,RULE-21-25,Yes,Required,,,All memory synchronization operations shall be executed in sequentially consistent order,,Concurrency7,Medium, +c,MISRA-C-2012,RULE-21-26,Yes,Required,,,The Standard Library function mtx_timedlock() shall only be invoked on mutex objects of appropriate mutex type,,Concurrency7,Hard, c,MISRA-C-2012,RULE-22-1,Yes,Required,,,All resources obtained dynamically by means of Standard Library functions shall be explicitly released,,Memory2,Hard, c,MISRA-C-2012,RULE-22-2,Yes,Mandatory,,,A block of memory shall only be freed if it was allocated by means of a Standard Library function,,Memory2,Hard, c,MISRA-C-2012,RULE-22-3,Yes,Required,,,The same file shall not be open for read and write access at the same time on different streams,,IO3,Hard, @@ -803,15 +803,15 @@ c,MISRA-C-2012,RULE-22-8,Yes,Required,,,The value of errno shall be set to zero c,MISRA-C-2012,RULE-22-9,Yes,Required,,,The value of errno shall be tested against zero after calling an errno-setting-function,,Contracts3,Medium, c,MISRA-C-2012,RULE-22-10,Yes,Required,,,The value of errno shall only be tested when the last function to be called was an errno-setting-function,,Contracts3,Medium, c,MISRA-C-2012,RULE-22-11,Yes,Required,,,A thread that was previously either joined or detached shall not be subsequently joined nor detached,CON39-C,Concurrency6,Import, -c,MISRA-C-2012,RULE-22-12,Yes,Mandatory,,,"Thread objects, thread synchronization objects, and thread-specific storage pointers shall only be accessed by the appropriate Standard Library functions",,Concurrency6,Medium, -c,MISRA-C-2012,RULE-22-13,Yes,Required,,,"Thread objects, thread synchronization objects, and thread specific storage pointers shall have appropriate storage duration",EXP54-CPP and CON34-C,Concurrency6,Medium, -c,MISRA-C-2012,RULE-22-14,Yes,Mandatory,,,Thread synchronization objects shall be initialized before being accessed,EXP53-CPP,Concurrency6,Hard, -c,MISRA-C-2012,RULE-22-15,Yes,Required,,,Thread synchronization objects and thread-specific storage pointers shall not be destroyed until after all threads accessing them have terminated,,Concurrency6,Hard, -c,MISRA-C-2012,RULE-22-16,Yes,Required,,,All mutex objects locked by a thread shall be explicitly unlocked by the same thread,MEM51-CPP,Concurrency6,Hard, -c,MISRA-C-2012,RULE-22-17,Yes,Required,,,No thread shall unlock a mutex or call cnd_wait() or cnd_timedwait() for a mutex it has not locked before,Rule 22.2,Concurrency6,Medium, -c,MISRA-C-2012,RULE-22-18,Yes,Required,,,Non-recursive mutexes shall not be recursively locked,CON56-CPP,Concurrency6,Medium, -c,MISRA-C-2012,RULE-22-19,Yes,Required,,,A condition variable shall be associated with at most one mutex object,,Concurrency6,Medium, -c,MISRA-C-2012,RULE-22-20,Yes,Mandatory,,,Thread-specific storage pointers shall be created before being accessed,,Concurrency6,Hard, +c,MISRA-C-2012,RULE-22-12,Yes,Mandatory,,,"Thread objects, thread synchronization objects, and thread-specific storage pointers shall only be accessed by the appropriate Standard Library functions",,Concurrency7,Medium, +c,MISRA-C-2012,RULE-22-13,Yes,Required,,,"Thread objects, thread synchronization objects, and thread specific storage pointers shall have appropriate storage duration",EXP54-CPP and CON34-C,Concurrency7,Medium, +c,MISRA-C-2012,RULE-22-14,Yes,Mandatory,,,Thread synchronization objects shall be initialized before being accessed,EXP53-CPP,Concurrency7,Hard, +c,MISRA-C-2012,RULE-22-15,Yes,Required,,,Thread synchronization objects and thread-specific storage pointers shall not be destroyed until after all threads accessing them have terminated,,Concurrency7,Hard, +c,MISRA-C-2012,RULE-22-16,Yes,Required,,,All mutex objects locked by a thread shall be explicitly unlocked by the same thread,MEM51-CPP,Concurrency7,Hard, +c,MISRA-C-2012,RULE-22-17,Yes,Required,,,No thread shall unlock a mutex or call cnd_wait() or cnd_timedwait() for a mutex it has not locked before,Rule 22.2,Concurrency7,Medium, +c,MISRA-C-2012,RULE-22-18,Yes,Required,,,Non-recursive mutexes shall not be recursively locked,CON56-CPP,Concurrency7,Medium, +c,MISRA-C-2012,RULE-22-19,Yes,Required,,,A condition variable shall be associated with at most one mutex object,,Concurrency7,Medium, +c,MISRA-C-2012,RULE-22-20,Yes,Mandatory,,,Thread-specific storage pointers shall be created before being accessed,,Concurrency7,Hard, c,MISRA-C-2012,RULE-23-1,Yes,Advisory,,,A generic selection should only be expanded from a macro,,Generics,Medium, c,MISRA-C-2012,RULE-23-2,Yes,Required,,,A generic selection that is not expanded from a macro shall not contain potential side effects in the controlling expression,,Generics,Hard, c,MISRA-C-2012,RULE-23-3,Yes,Advisory,,,A generic selection should contain at least one non-default association,,Generics,Easy, From 20bae2046c2d38fb4a8de54682d1d7f69922475e Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 31 Oct 2024 21:46:20 -0700 Subject: [PATCH 047/370] Fix format, remove unneeded test complexity --- .../BannedDynamicThreadCreation.expected | 32 +++++----- .../DIR-5-3/ThreadCreatedByThread.expected | 28 ++++----- c/misra/test/rules/DIR-5-3/test.c | 63 ++++++++----------- 3 files changed, 57 insertions(+), 66 deletions(-) diff --git a/c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.expected b/c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.expected index ff829918fd..fa12a62f41 100644 --- a/c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.expected +++ b/c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.expected @@ -1,16 +1,16 @@ -| test.c:37:3:37:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:36:6:36:34 | make_threads_called_from_main | make_threads_called_from_main | -| test.c:38:3:38:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:36:6:36:34 | make_threads_called_from_main | make_threads_called_from_main | -| test.c:46:3:46:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:45:6:45:51 | make_threads_called_from_func_called_from_main | make_threads_called_from_func_called_from_main | -| test.c:47:3:47:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:45:6:45:51 | make_threads_called_from_func_called_from_main | make_threads_called_from_func_called_from_main | -| test.c:56:3:56:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | -| test.c:57:3:57:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | -| test.c:65:3:65:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | -| test.c:66:3:66:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | -| test.c:74:3:74:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:73:6:73:39 | make_threads_called_from_thrd_func | make_threads_called_from_thrd_func | -| test.c:75:3:75:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:73:6:73:39 | make_threads_called_from_thrd_func | make_threads_called_from_thrd_func | -| test.c:83:3:83:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:82:6:82:59 | make_threads_called_from_func_called_from_pthread_thrd | make_threads_called_from_func_called_from_pthread_thrd | -| test.c:84:3:84:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:82:6:82:59 | make_threads_called_from_func_called_from_pthread_thrd | make_threads_called_from_func_called_from_pthread_thrd | -| test.c:88:3:88:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:87:6:87:47 | make_threads_called_from_main_pthread_thrd | make_threads_called_from_main_pthread_thrd | -| test.c:89:3:89:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:87:6:87:47 | make_threads_called_from_main_pthread_thrd | make_threads_called_from_main_pthread_thrd | -| test.c:93:3:93:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:92:6:92:38 | make_threads_not_called_by_anyone | make_threads_not_called_by_anyone | -| test.c:94:3:94:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:92:6:92:38 | make_threads_not_called_by_anyone | make_threads_not_called_by_anyone | +| test.c:28:3:28:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:27:6:27:34 | make_threads_called_from_main | make_threads_called_from_main | +| test.c:29:3:29:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:27:6:27:34 | make_threads_called_from_main | make_threads_called_from_main | +| test.c:37:3:37:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:36:6:36:51 | make_threads_called_from_func_called_from_main | make_threads_called_from_func_called_from_main | +| test.c:38:3:38:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:36:6:36:51 | make_threads_called_from_func_called_from_main | make_threads_called_from_func_called_from_main | +| test.c:47:3:47:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | +| test.c:48:3:48:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | +| test.c:56:3:56:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | +| test.c:57:3:57:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | +| test.c:65:3:65:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:64:6:64:39 | make_threads_called_from_thrd_func | make_threads_called_from_thrd_func | +| test.c:66:3:66:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:64:6:64:39 | make_threads_called_from_thrd_func | make_threads_called_from_thrd_func | +| test.c:74:3:74:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:73:6:73:59 | make_threads_called_from_func_called_from_pthread_thrd | make_threads_called_from_func_called_from_pthread_thrd | +| test.c:75:3:75:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:73:6:73:59 | make_threads_called_from_func_called_from_pthread_thrd | make_threads_called_from_func_called_from_pthread_thrd | +| test.c:79:3:79:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:78:6:78:47 | make_threads_called_from_main_pthread_thrd | make_threads_called_from_main_pthread_thrd | +| test.c:80:3:80:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:78:6:78:47 | make_threads_called_from_main_pthread_thrd | make_threads_called_from_main_pthread_thrd | +| test.c:84:3:84:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:83:6:83:38 | make_threads_not_called_by_anyone | make_threads_not_called_by_anyone | +| test.c:85:3:85:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:83:6:83:38 | make_threads_not_called_by_anyone | make_threads_not_called_by_anyone | diff --git a/c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.expected b/c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.expected index 74be75ffeb..5b73fd97aa 100644 --- a/c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.expected +++ b/c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.expected @@ -1,14 +1,14 @@ -| test.c:56:3:56:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | -| test.c:57:3:57:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | -| test.c:65:3:65:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | -| test.c:66:3:66:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | -| test.c:74:3:74:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | -| test.c:75:3:75:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | -| test.c:83:3:83:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | -| test.c:83:3:83:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | -| test.c:84:3:84:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | -| test.c:84:3:84:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | -| test.c:88:3:88:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | -| test.c:88:3:88:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | -| test.c:89:3:89:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:55:7:55:18 | pthread_func | pthread_func | -| test.c:89:3:89:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:64:5:64:13 | thrd_func | thrd_func | +| test.c:47:3:47:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | +| test.c:48:3:48:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | +| test.c:56:3:56:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | +| test.c:57:3:57:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | +| test.c:65:3:65:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | +| test.c:66:3:66:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | +| test.c:74:3:74:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | +| test.c:74:3:74:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | +| test.c:75:3:75:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | +| test.c:75:3:75:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | +| test.c:79:3:79:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | +| test.c:79:3:79:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | +| test.c:80:3:80:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | +| test.c:80:3:80:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | diff --git a/c/misra/test/rules/DIR-5-3/test.c b/c/misra/test/rules/DIR-5-3/test.c index 294f79a276..24e03d9a33 100644 --- a/c/misra/test/rules/DIR-5-3/test.c +++ b/c/misra/test/rules/DIR-5-3/test.c @@ -1,18 +1,11 @@ -#include "threads.h" #include "pthread.h" +#include "threads.h" -thrd_t g1; // COMPLIANT +thrd_t g1; // COMPLIANT pthread_t g2; // COMPLIANT -thrd_t g3[10]; // COMPLIANT -pthread_t g4[10]; // COMPLIANT -struct { - thrd_t m1; // COMPLIANT - pthread_t m2; // COMPLIANT -} g7; - -void* pthread_func(void* arg); -int thrd_func(void* arg); +void *pthread_func(void *arg); +int thrd_func(void *arg); void make_threads_called_from_main(void); void func_called_from_main(void); @@ -20,13 +13,11 @@ void make_threads_called_from_func_called_from_main(void); void make_threads_called_from_main_pthread_thrd(void); void main() { - // Main starting top level threads -- ok. - thrd_create(&g1, &thrd_func, NULL); // COMPLIANT + thrd_create(&g1, &thrd_func, NULL); // COMPLIANT pthread_create(&g2, NULL, &pthread_func, NULL); // COMPLIANT - // Starting thread in pool -- ok. - thrd_create(&g3[0], &thrd_func, NULL); // COMPLIANT - pthread_create(&g4[0], NULL, &pthread_func, NULL); // COMPLIANT + thrd_create(&g1, &thrd_func, NULL); // COMPLIANT + pthread_create(&g2, NULL, &pthread_func, NULL); // COMPLIANT make_threads_called_from_main(); func_called_from_main(); @@ -34,17 +25,17 @@ void main() { } void make_threads_called_from_main() { - thrd_create(&g3[0], &thrd_func, NULL); // COMPLIANT - pthread_create(&g4[0], NULL, &pthread_func, NULL); // COMPLIANT + thrd_create(&g1, &thrd_func, NULL); // COMPLIANT + pthread_create(&g2, NULL, &pthread_func, NULL); // COMPLIANT } void func_called_from_main() { - make_threads_called_from_func_called_from_main(); + make_threads_called_from_func_called_from_main(); } void make_threads_called_from_func_called_from_main() { - thrd_create(&g3[0], &thrd_func, NULL); // COMPLIANT - pthread_create(&g4[0], NULL, &pthread_func, NULL); // COMPLIANT + thrd_create(&g1, &thrd_func, NULL); // COMPLIANT + pthread_create(&g2, NULL, &pthread_func, NULL); // COMPLIANT } void make_threads_called_from_pthread_func(void); @@ -52,18 +43,18 @@ void make_threads_called_from_thrd_func(void); void func_called_from_pthread_thrd(void); void make_threads_called_from_func_called_from_pthread_thrd(void); -void* pthread_func(void* arg) { - thrd_create(&g3[0], &thrd_func, NULL); // NON-COMPLIANT - pthread_create(&g4[0], NULL, &pthread_func, NULL); // NON-COMPLIANT +void *pthread_func(void *arg) { + thrd_create(&g1, &thrd_func, NULL); // NON-COMPLIANT + pthread_create(&g2, NULL, &pthread_func, NULL); // NON-COMPLIANT make_threads_called_from_pthread_func(); func_called_from_pthread_thrd(); make_threads_called_from_main_pthread_thrd(); } -int thrd_func(void* arg) { - thrd_create(&g3[0], &thrd_func, NULL); // NON-COMPLIANT - pthread_create(&g4[0], NULL, &pthread_func, NULL); // NON-COMPLIANT +int thrd_func(void *arg) { + thrd_create(&g1, &thrd_func, NULL); // NON-COMPLIANT + pthread_create(&g2, NULL, &pthread_func, NULL); // NON-COMPLIANT make_threads_called_from_thrd_func(); func_called_from_pthread_thrd(); @@ -71,25 +62,25 @@ int thrd_func(void* arg) { } void make_threads_called_from_thrd_func(void) { - thrd_create(&g3[0], &thrd_func, NULL); // NON-COMPLIANT - pthread_create(&g4[0], NULL, &pthread_func, NULL); // NON-COMPLIANT + thrd_create(&g1, &thrd_func, NULL); // NON-COMPLIANT + pthread_create(&g2, NULL, &pthread_func, NULL); // NON-COMPLIANT } void func_called_from_pthread_thrd(void) { - make_threads_called_from_func_called_from_pthread_thrd(); + make_threads_called_from_func_called_from_pthread_thrd(); } void make_threads_called_from_func_called_from_pthread_thrd(void) { - thrd_create(&g3[0], &thrd_func, NULL); // NON-COMPLIANT - pthread_create(&g4[0], NULL, &pthread_func, NULL); // NON-COMPLIANT + thrd_create(&g1, &thrd_func, NULL); // NON-COMPLIANT + pthread_create(&g2, NULL, &pthread_func, NULL); // NON-COMPLIANT } void make_threads_called_from_main_pthread_thrd() { - thrd_create(&g3[0], &thrd_func, NULL); // NON-COMPLIANT - pthread_create(&g4[0], NULL, &pthread_func, NULL); // NON-COMPLIANT + thrd_create(&g1, &thrd_func, NULL); // NON-COMPLIANT + pthread_create(&g2, NULL, &pthread_func, NULL); // NON-COMPLIANT } void make_threads_not_called_by_anyone() { - thrd_create(&g3[0], &thrd_func, NULL); // COMPLIANT - pthread_create(&g4[0], NULL, &pthread_func, NULL); // COMPLIANT + thrd_create(&g1, &thrd_func, NULL); // COMPLIANT + pthread_create(&g2, NULL, &pthread_func, NULL); // COMPLIANT } From 14b7c61df9f5e4d18213b99a6a1f36c1fe1f0661 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 31 Oct 2024 21:50:31 -0700 Subject: [PATCH 048/370] Move 21-25 to Concurrency6 --- rules.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules.csv b/rules.csv index 7648052954..329d0d1bc5 100644 --- a/rules.csv +++ b/rules.csv @@ -790,7 +790,7 @@ c,MISRA-C-2012,RULE-21-21,Yes,Required,,,The Standard Library function system of c,MISRA-C-2012,RULE-21-22,Yes,Mandatory,,,All operand arguments to any type-generic macros in shall have an appropriate essential type,EXP37-C,EssentialTypes2,Hard, c,MISRA-C-2012,RULE-21-23,Yes,Required,,,All operand arguments to any multi-argument type-generic macros in shall have the same standard type,Rule-21-22,EssentialTypes2,Easy, c,MISRA-C-2012,RULE-21-24,Yes,Required,,,The random number generator functions of shall not be used,MSC30-C,Banned2,Easy, -c,MISRA-C-2012,RULE-21-25,Yes,Required,,,All memory synchronization operations shall be executed in sequentially consistent order,,Concurrency7,Medium, +c,MISRA-C-2012,RULE-21-25,Yes,Required,,,All memory synchronization operations shall be executed in sequentially consistent order,,Concurrency6,Medium, c,MISRA-C-2012,RULE-21-26,Yes,Required,,,The Standard Library function mtx_timedlock() shall only be invoked on mutex objects of appropriate mutex type,,Concurrency7,Hard, c,MISRA-C-2012,RULE-22-1,Yes,Required,,,All resources obtained dynamically by means of Standard Library functions shall be explicitly released,,Memory2,Hard, c,MISRA-C-2012,RULE-22-2,Yes,Mandatory,,,A block of memory shall only be freed if it was allocated by means of a Standard Library function,,Memory2,Hard, From 3259d17e5d699628303d64f0d52345d0f62eaeca Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 31 Oct 2024 21:53:43 -0700 Subject: [PATCH 049/370] Fix query formatting --- .../DIR-5-2/NotNoDeadlocksBetweenThreads.ql | 3 ++- .../src/rules/DIR-5-3/ThreadCreatedByThread.ql | 2 +- .../RULE-21-25/InvalidMemoryOrderArgument.ql | 16 ++++++---------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/c/misra/src/rules/DIR-5-2/NotNoDeadlocksBetweenThreads.ql b/c/misra/src/rules/DIR-5-2/NotNoDeadlocksBetweenThreads.ql index ffe30a2b6a..5d949f56ed 100644 --- a/c/misra/src/rules/DIR-5-2/NotNoDeadlocksBetweenThreads.ql +++ b/c/misra/src/rules/DIR-5-2/NotNoDeadlocksBetweenThreads.ql @@ -17,7 +17,8 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.rules.preventdeadlockbylockinginpredefinedorder.PreventDeadlockByLockingInPredefinedOrder -class NotNoDeadlocksBetweenThreadsQuery extends PreventDeadlockByLockingInPredefinedOrderSharedQuery { +class NotNoDeadlocksBetweenThreadsQuery extends PreventDeadlockByLockingInPredefinedOrderSharedQuery +{ NotNoDeadlocksBetweenThreadsQuery() { this = Concurrency6Package::notNoDeadlocksBetweenThreadsQuery() } diff --git a/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql b/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql index cf08a0c809..25b8b4cb9f 100644 --- a/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql +++ b/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql @@ -42,4 +42,4 @@ where enclosingFunction = tc.getEnclosingFunction() and threadRoot = enclosingFunction.getThreadRoot() select tc, "Thread creation call reachable from threaded function '$@'.", threadRoot, - threadRoot.toString() \ No newline at end of file + threadRoot.toString() diff --git a/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql b/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql index 4924c0df33..b0945db559 100644 --- a/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql +++ b/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql @@ -40,18 +40,13 @@ class MemoryOrderConstantExpr extends Expr { MemoryOrder ord; MemoryOrderConstantExpr() { - if - this instanceof MemoryOrderConstantAccess - then - ord = this.(MemoryOrderConstantAccess).getTarget() - else - ord.getIntValue() = getValue().toInt() + if this instanceof MemoryOrderConstantAccess + then ord = this.(MemoryOrderConstantAccess).getTarget() + else ord.getIntValue() = getValue().toInt() } /* Get the name of the `MemoryOrder` this expression is valued as. */ - string getMemoryOrderString() { - result = ord.toString() - } + string getMemoryOrderString() { result = ord.toString() } } /** @@ -75,7 +70,8 @@ class MemoryOrderedStdAtomicFunction extends Function { baseParamIdx = 1 and baseParams = 2 or - getName().regexpMatch(prefix + ["atomic_store", "atomic_fetch_.*", "atomic_exchange"] + suffix) and + getName() + .regexpMatch(prefix + ["atomic_store", "atomic_fetch_.*", "atomic_exchange"] + suffix) and baseParamIdx = 2 and baseParams = 3 or From 9ee2af69016c2bd07b39bfd48269674bd870243e Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 1 Nov 2024 02:35:55 -0700 Subject: [PATCH 050/370] Fix test issues --- .../ThreadWasPreviouslyJoinedOrDetached.qlref | 1 - .../AtomicVariableTwiceInExpression.expected | 8 ++++---- ...micAggregateObjectDirectlyAccessed.expected | 4 ++-- c/misra/test/rules/RULE-12-6/test.c | 18 ++++++++++-------- 4 files changed, 16 insertions(+), 15 deletions(-) delete mode 100644 c/cert/test/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.qlref diff --git a/c/cert/test/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.qlref b/c/cert/test/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.qlref deleted file mode 100644 index 5daa5a5046..0000000000 --- a/c/cert/test/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.ql \ No newline at end of file diff --git a/c/cert/test/rules/CON40-C/AtomicVariableTwiceInExpression.expected b/c/cert/test/rules/CON40-C/AtomicVariableTwiceInExpression.expected index ddff311b59..42d3ea924d 100644 --- a/c/cert/test/rules/CON40-C/AtomicVariableTwiceInExpression.expected +++ b/c/cert/test/rules/CON40-C/AtomicVariableTwiceInExpression.expected @@ -1,6 +1,6 @@ | test.c:7:18:7:39 | ATOMIC_VAR_INIT(value) | Atomic variable possibly referred to twice in an $@. | test.c:33:3:33:10 | ... += ... | expression | | test.c:7:18:7:39 | ATOMIC_VAR_INIT(value) | Atomic variable possibly referred to twice in an $@. | test.c:34:3:34:13 | ... = ... | expression | -| test.c:11:3:11:23 | atomic_store(a,b) | Atomic variable possibly referred to twice in an $@. | test.c:11:3:11:23 | atomic_store(a,b) | expression | -| test.c:12:3:12:35 | atomic_store_explicit(a,b,c) | Atomic variable possibly referred to twice in an $@. | test.c:12:3:12:35 | atomic_store_explicit(a,b,c) | expression | -| test.c:25:3:25:49 | atomic_compare_exchange_weak(a,b,c) | Atomic variable possibly referred to twice in an $@. | test.c:25:3:25:49 | atomic_compare_exchange_weak(a,b,c) | expression | -| test.c:26:3:27:42 | atomic_compare_exchange_weak_explicit(a,b,c,d,e) | Atomic variable possibly referred to twice in an $@. | test.c:26:3:27:42 | atomic_compare_exchange_weak_explicit(a,b,c,d,e) | expression | +| test.c:11:3:11:23 | atomic_store(object,desired) | Atomic variable possibly referred to twice in an $@. | test.c:11:3:11:23 | atomic_store(object,desired) | expression | +| test.c:12:3:12:23 | atomic_store_explicit | Atomic variable possibly referred to twice in an $@. | test.c:12:3:12:23 | atomic_store_explicit | expression | +| test.c:25:3:25:49 | atomic_compare_exchange_weak(object,expected,desired) | Atomic variable possibly referred to twice in an $@. | test.c:25:3:25:49 | atomic_compare_exchange_weak(object,expected,desired) | expression | +| test.c:26:3:26:39 | atomic_compare_exchange_weak_explicit | Atomic variable possibly referred to twice in an $@. | test.c:26:3:26:39 | atomic_compare_exchange_weak_explicit | expression | diff --git a/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.expected b/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.expected index 02159bef69..df7f149fcc 100644 --- a/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.expected +++ b/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.expected @@ -1,4 +1,4 @@ -| test.c:41:13:41:13 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | -| test.c:42:18:42:18 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | | test.c:43:13:43:13 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | | test.c:44:18:44:18 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | +| test.c:45:13:45:13 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | +| test.c:46:18:46:18 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | diff --git a/c/misra/test/rules/RULE-12-6/test.c b/c/misra/test/rules/RULE-12-6/test.c index 2b1eeb7568..ae6125da96 100644 --- a/c/misra/test/rules/RULE-12-6/test.c +++ b/c/misra/test/rules/RULE-12-6/test.c @@ -1,7 +1,7 @@ #include "stdatomic.h" #include "string.h" -typedef struct s2 { +typedef struct s1 { int x; } s1; @@ -16,14 +16,16 @@ _Atomic int g3; void takeCopy(s1 p1); void f1() { - s1 *l1; + s1 l1; + s1 *l2; l1 = atomic_load(&atomic_s1); // COMPLIANT l1 = atomic_load(ptr_atomic_s1); // COMPLIANT - l1 = atomic_load(&s1_atomic_ptr); // COMPLIANT - l1->x = 4; // COMPLIANT + l2 = atomic_load(&s1_atomic_ptr); // COMPLIANT + l1.x = 4; // COMPLIANT + l2->x = 4; // COMPLIANT atomic_store(&atomic_s1, l1); // COMPLIANT atomic_store(ptr_atomic_s1, l1); // COMPLIANT - atomic_store(&s1_atomic_ptr, l1); // COMPLIANT + atomic_store(&s1_atomic_ptr, l2); // COMPLIANT // Undefined behavior, but not banned by this rule. memset(&atomic_s1, sizeof(atomic_s1), 0); // COMPLIANT @@ -34,8 +36,8 @@ void f1() { takeCopy(*ptr_atomic_s1); // COMPLIANT atomic_s1 = (s1){0}; // COMPLIANT *ptr_atomic_s1 = (s1){0}; // COMPLIANT - atomic_s1 = *l1; // COMPLIANT - ptr_atomic_s1 = l1; // COMPLIANT + atomic_s1 = *l2; // COMPLIANT + ptr_atomic_s1 = l2; // COMPLIANT // Banned: circumvents data-race protection, results in UB. atomic_s1.x; // NON-COMPLIANT @@ -54,6 +56,6 @@ void f1() { memset(s1_atomic_ptr, sizeof(*s1_atomic_ptr), 0); // COMPLIANT takeCopy(*s1_atomic_ptr); // COMPLIANT *s1_atomic_ptr = (s1){0}; // COMPLIANT - s1_atomic_ptr = l1; // COMPLIANT + s1_atomic_ptr = l2; // COMPLIANT s1_atomic_ptr->x; // COMPLIANT } \ No newline at end of file From 1ed65cf5cd38ccb9add67211d6e8bd26401ba375 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sat, 2 Nov 2024 09:35:42 -0700 Subject: [PATCH 051/370] Fix another stdlib affected test --- .../WrapFunctionsThatCanFailSpuriouslyInLoop.expected | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/c/cert/test/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.expected b/c/cert/test/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.expected index 0c1e25cd00..b1c224173e 100644 --- a/c/cert/test/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.expected +++ b/c/cert/test/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.expected @@ -1,4 +1,4 @@ -| test.c:6:8:6:46 | atomic_compare_exchange_weak(a,b,c) | Function that can spuriously fail not wrapped in a loop. | -| test.c:10:3:10:41 | atomic_compare_exchange_weak(a,b,c) | Function that can spuriously fail not wrapped in a loop. | -| test.c:12:8:13:47 | atomic_compare_exchange_weak_explicit(a,b,c,d,e) | Function that can spuriously fail not wrapped in a loop. | -| test.c:17:3:17:56 | atomic_compare_exchange_weak_explicit(a,b,c,d,e) | Function that can spuriously fail not wrapped in a loop. | +| test.c:6:8:6:46 | atomic_compare_exchange_weak(object,expected,desired) | Function that can spuriously fail not wrapped in a loop. | +| test.c:10:3:10:41 | atomic_compare_exchange_weak(object,expected,desired) | Function that can spuriously fail not wrapped in a loop. | +| test.c:12:8:12:44 | atomic_compare_exchange_weak_explicit | Function that can spuriously fail not wrapped in a loop. | +| test.c:17:3:17:39 | atomic_compare_exchange_weak_explicit | Function that can spuriously fail not wrapped in a loop. | From 9ff699b63c073f5be42b6007864e605a01bc9dc1 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 17 Nov 2024 16:58:14 -0800 Subject: [PATCH 052/370] Implement Concurrency7 package --- .../includes/standard-library/stdatomic.h | 1 + .../TimedlockOnInappropriateMutexType.ql | 74 +++++++++++++++++++ .../RULE-9-7/UninitializedAtomicObject.ql | 73 ++++++++++++++++++ ...TimedlockOnInappropriateMutexType.expected | 45 +++++++++++ .../TimedlockOnInappropriateMutexType.qlref | 1 + c/misra/test/rules/RULE-21-26/test.c | 45 +++++++++++ .../UninitializedAtomicObject.expected | 3 + .../RULE-9-7/UninitializedAtomicObject.qlref | 1 + c/misra/test/rules/RULE-9-7/test.c | 34 +++++++++ .../cpp/exclusions/c/Concurrency7.qll | 44 +++++++++++ .../cpp/exclusions/c/RuleMetadata.qll | 3 + rule_packages/c/Concurrency7.json | 45 +++++++++++ rules.csv | 4 +- 13 files changed, 371 insertions(+), 2 deletions(-) create mode 100644 c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql create mode 100644 c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql create mode 100644 c/misra/test/rules/RULE-21-26/TimedlockOnInappropriateMutexType.expected create mode 100644 c/misra/test/rules/RULE-21-26/TimedlockOnInappropriateMutexType.qlref create mode 100644 c/misra/test/rules/RULE-21-26/test.c create mode 100644 c/misra/test/rules/RULE-9-7/UninitializedAtomicObject.expected create mode 100644 c/misra/test/rules/RULE-9-7/UninitializedAtomicObject.qlref create mode 100644 c/misra/test/rules/RULE-9-7/test.c create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency7.qll create mode 100644 rule_packages/c/Concurrency7.json diff --git a/c/common/test/includes/standard-library/stdatomic.h b/c/common/test/includes/standard-library/stdatomic.h index 66b74ae61a..229b8db906 100644 --- a/c/common/test/includes/standard-library/stdatomic.h +++ b/c/common/test/includes/standard-library/stdatomic.h @@ -5,5 +5,6 @@ #define atomic_store(a, b) 0 #define atomic_store_explicit(a, b, c) 0 #define ATOMIC_VAR_INIT(value) (value) +#define atomic_init __c11_atomic_init #define atomic_is_lock_free(obj) __c11_atomic_is_lock_free(sizeof(*(obj))) typedef _Atomic(int) atomic_int; \ No newline at end of file diff --git a/c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql b/c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql new file mode 100644 index 0000000000..d8d465045e --- /dev/null +++ b/c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql @@ -0,0 +1,74 @@ +/** + * @id c/misra/timedlock-on-inappropriate-mutex-type + * @name RULE-21-26: The Standard Library function mtx_timedlock() shall only be invoked on mutexes of type mtx_timed + * @description The Standard Library function mtx_timedlock() shall only be invoked on mutex objects + * of appropriate mutex type + * @kind path-problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-21-26 + * correctness + * concurrency + * external/misra/c/2012/amendment4 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import semmle.code.cpp.dataflow.new.DataFlow + +class MutexTimed extends EnumConstant { + MutexTimed() { hasName("mtx_timed") } +} + +class MutexInitCall extends FunctionCall { + Expr mutexExpr; + Expr mutexTypeExpr; + + MutexInitCall() { + getTarget().hasName("mtx_init") and + mutexExpr = getArgument(0) and + mutexTypeExpr = getArgument(1) + } + + predicate isTimedMutexType() { + exists(EnumConstantAccess baseTypeAccess | + ( + baseTypeAccess = mutexTypeExpr + or + baseTypeAccess = mutexTypeExpr.(BinaryBitwiseOperation).getAnOperand() + ) and + baseTypeAccess.getTarget() instanceof MutexTimed + ) + or + mutexTypeExpr.getValue().toInt() = any(MutexTimed m).getValue().toInt() + } + + Expr getMutexExpr() { result = mutexExpr } +} + +module MutexTimedlockFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { + exists(MutexInitCall init | + node.asDefiningArgument() = init.getMutexExpr() and not init.isTimedMutexType() + ) + } + + predicate isSink(DataFlow::Node node) { + exists(FunctionCall fc | + fc.getTarget().hasName("mtx_timedlock") and + node.asIndirectExpr() = fc.getArgument(0) + ) + } +} + +module Flow = DataFlow::Global; + +import Flow::PathGraph + +from Flow::PathNode source, Flow::PathNode sink +where + not isExcluded(sink.getNode().asExpr(), + Concurrency7Package::timedlockOnInappropriateMutexTypeQuery()) and + Flow::flowPath(source, sink) +select sink.getNode(), source, sink, "Call to mtx_timedlock with mutex not of type 'mtx_timed'." diff --git a/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql b/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql new file mode 100644 index 0000000000..40f833a740 --- /dev/null +++ b/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql @@ -0,0 +1,73 @@ +/** + * @id c/misra/uninitialized-atomic-object + * @name RULE-9-7: Atomic objects shall be appropriately initialized before being accessed + * @description Atomic objects that do not have static storage duration shall be initialized with a + * value or by using 'atomic_init()'. + * @kind problem + * @precision high + * @problem.severity warning + * @tags external/misra/id/rule-9-7 + * concurrency + * external/misra/c/2012/amendment4 + * external/misra/obligation/mandatory + */ + +import cpp +import codingstandards.c.misra +import semmle.code.cpp.controlflow.Dominance + +class ThreadSpawningFunction extends Function { + ThreadSpawningFunction() { + this.hasName("pthread_create") or + this.hasName("thrd_create") or + exists(FunctionCall fc | + fc.getTarget() instanceof ThreadSpawningFunction and + fc.getEnclosingFunction() = this) + } +} + +class AtomicInitAddressOfExpr extends FunctionCall { + Expr addressedExpr; + + AtomicInitAddressOfExpr() { + exists(AddressOfExpr addrOf | + getArgument(0) = addrOf and + addrOf.getOperand() = addressedExpr and + getTarget().getName() = "__c11_atomic_init" + ) + } + + Expr getAddressedExpr() { + result = addressedExpr + } +} + +ControlFlowNode getARequiredInitializationPoint(LocalScopeVariable v) { + result = v.getParentScope().(BlockStmt).getFollowingStmt() + or + exists(DeclStmt decl | + decl.getADeclaration() = v and + result = any(FunctionCall fc + | fc.getTarget() instanceof ThreadSpawningFunction and + fc.getEnclosingBlock().getEnclosingBlock*() = v.getParentScope() and + fc.getAPredecessor*() = decl + ) + ) +} + +from VariableDeclarationEntry decl, Variable v +where + not isExcluded(decl, Concurrency7Package::uninitializedAtomicObjectQuery()) and + v = decl.getVariable() and + v.getUnderlyingType().hasSpecifier("atomic") and + not v.isTopLevel() and + not exists(v.getInitializer()) and + exists(ControlFlowNode missingInitPoint | + missingInitPoint = getARequiredInitializationPoint(v) + and not exists(AtomicInitAddressOfExpr initialization | + initialization.getAddressedExpr().(VariableAccess).getTarget() = v and + dominates(initialization, missingInitPoint) + ) + ) +select decl, + "Atomic object '" + v.getName() + "' has no initializer or corresponding use of 'atomic_init()'." diff --git a/c/misra/test/rules/RULE-21-26/TimedlockOnInappropriateMutexType.expected b/c/misra/test/rules/RULE-21-26/TimedlockOnInappropriateMutexType.expected new file mode 100644 index 0000000000..442f20bf73 --- /dev/null +++ b/c/misra/test/rules/RULE-21-26/TimedlockOnInappropriateMutexType.expected @@ -0,0 +1,45 @@ +edges +| test.c:10:24:10:24 | *m | test.c:10:43:10:43 | *m | provenance | | +| test.c:13:12:13:14 | mtx_init output argument | test.c:14:17:14:19 | *& ... | provenance | | +| test.c:13:12:13:14 | mtx_init output argument | test.c:15:14:15:16 | *& ... | provenance | | +| test.c:15:14:15:16 | *& ... | test.c:10:24:10:24 | *m | provenance | | +| test.c:17:12:17:14 | mtx_init output argument | test.c:18:17:18:19 | *& ... | provenance | | +| test.c:17:12:17:14 | mtx_init output argument | test.c:19:14:19:16 | *& ... | provenance | | +| test.c:19:14:19:16 | *& ... | test.c:10:24:10:24 | *m | provenance | | +| test.c:30:12:30:14 | mtx_init output argument | test.c:31:17:31:19 | *& ... | provenance | | +| test.c:30:12:30:14 | mtx_init output argument | test.c:32:14:32:16 | *& ... | provenance | | +| test.c:32:14:32:16 | *& ... | test.c:10:24:10:24 | *m | provenance | | +| test.c:42:12:42:16 | mtx_init output argument | test.c:42:13:42:14 | *l3 [post update] [m] | provenance | | +| test.c:42:13:42:14 | *l3 [post update] [m] | test.c:43:18:43:19 | *l3 [m] | provenance | | +| test.c:42:13:42:14 | *l3 [post update] [m] | test.c:44:15:44:16 | *l3 [m] | provenance | | +| test.c:43:18:43:19 | *l3 [m] | test.c:43:17:43:21 | *& ... | provenance | | +| test.c:44:14:44:18 | *& ... | test.c:10:24:10:24 | *m | provenance | | +| test.c:44:15:44:16 | *l3 [m] | test.c:44:14:44:18 | *& ... | provenance | | +nodes +| test.c:10:24:10:24 | *m | semmle.label | *m | +| test.c:10:43:10:43 | *m | semmle.label | *m | +| test.c:13:12:13:14 | mtx_init output argument | semmle.label | mtx_init output argument | +| test.c:14:17:14:19 | *& ... | semmle.label | *& ... | +| test.c:15:14:15:16 | *& ... | semmle.label | *& ... | +| test.c:17:12:17:14 | mtx_init output argument | semmle.label | mtx_init output argument | +| test.c:18:17:18:19 | *& ... | semmle.label | *& ... | +| test.c:19:14:19:16 | *& ... | semmle.label | *& ... | +| test.c:30:12:30:14 | mtx_init output argument | semmle.label | mtx_init output argument | +| test.c:31:17:31:19 | *& ... | semmle.label | *& ... | +| test.c:32:14:32:16 | *& ... | semmle.label | *& ... | +| test.c:42:12:42:16 | mtx_init output argument | semmle.label | mtx_init output argument | +| test.c:42:13:42:14 | *l3 [post update] [m] | semmle.label | *l3 [post update] [m] | +| test.c:43:17:43:21 | *& ... | semmle.label | *& ... | +| test.c:43:18:43:19 | *l3 [m] | semmle.label | *l3 [m] | +| test.c:44:14:44:18 | *& ... | semmle.label | *& ... | +| test.c:44:15:44:16 | *l3 [m] | semmle.label | *l3 [m] | +subpaths +#select +| test.c:10:43:10:43 | *m | test.c:13:12:13:14 | mtx_init output argument | test.c:10:43:10:43 | *m | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | +| test.c:10:43:10:43 | *m | test.c:17:12:17:14 | mtx_init output argument | test.c:10:43:10:43 | *m | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | +| test.c:10:43:10:43 | *m | test.c:30:12:30:14 | mtx_init output argument | test.c:10:43:10:43 | *m | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | +| test.c:10:43:10:43 | *m | test.c:42:12:42:16 | mtx_init output argument | test.c:10:43:10:43 | *m | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | +| test.c:14:17:14:19 | *& ... | test.c:13:12:13:14 | mtx_init output argument | test.c:14:17:14:19 | *& ... | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | +| test.c:18:17:18:19 | *& ... | test.c:17:12:17:14 | mtx_init output argument | test.c:18:17:18:19 | *& ... | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | +| test.c:31:17:31:19 | *& ... | test.c:30:12:30:14 | mtx_init output argument | test.c:31:17:31:19 | *& ... | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | +| test.c:43:17:43:21 | *& ... | test.c:42:12:42:16 | mtx_init output argument | test.c:43:17:43:21 | *& ... | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | diff --git a/c/misra/test/rules/RULE-21-26/TimedlockOnInappropriateMutexType.qlref b/c/misra/test/rules/RULE-21-26/TimedlockOnInappropriateMutexType.qlref new file mode 100644 index 0000000000..9ffe7e7494 --- /dev/null +++ b/c/misra/test/rules/RULE-21-26/TimedlockOnInappropriateMutexType.qlref @@ -0,0 +1 @@ +rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-26/test.c b/c/misra/test/rules/RULE-21-26/test.c new file mode 100644 index 0000000000..d26f9c1f2f --- /dev/null +++ b/c/misra/test/rules/RULE-21-26/test.c @@ -0,0 +1,45 @@ +#include "threads.h" + +mtx_t g1; +mtx_t g2; +mtx_t g3; +mtx_t g4; + +struct timespec ts = {0, 0}; + +void doTimeLock(mtx_t *m) { mtx_timedlock(m, &ts); } + +void main(void) { + mtx_init(&g1, mtx_plain); + mtx_timedlock(&g1, &ts); // NON-COMPLIANT + doTimeLock(&g1); // NON-COMPLIANT + + mtx_init(&g2, mtx_plain | mtx_recursive); + mtx_timedlock(&g2, &ts); // NON-COMPLIANT + doTimeLock(&g2); // NON-COMPLIANT + + mtx_init(&g3, mtx_timed); + mtx_timedlock(&g3, &ts); // COMPLIANT + doTimeLock(&g3); // COMPLIANT + + mtx_init(&g4, mtx_timed | mtx_recursive); + mtx_timedlock(&g4, &ts); // COMPLIANT + doTimeLock(&g4); // COMPLIANT + + mtx_t l1; + mtx_init(&l1, mtx_plain); + mtx_timedlock(&l1, &ts); // NON-COMPLIANT + doTimeLock(&l1); // NON-COMPLIANT + + mtx_t l2; + mtx_init(&l2, mtx_timed); + mtx_timedlock(&l2, &ts); // COMPLIANT + doTimeLock(&l2); // COMPLIANT + + struct s { + mtx_t m; + } l3; + mtx_init(&l3.m, mtx_plain); + mtx_timedlock(&l3.m, &ts); // NON-COMPLIANT + doTimeLock(&l3.m); // NON-COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-9-7/UninitializedAtomicObject.expected b/c/misra/test/rules/RULE-9-7/UninitializedAtomicObject.expected new file mode 100644 index 0000000000..89facda9bb --- /dev/null +++ b/c/misra/test/rules/RULE-9-7/UninitializedAtomicObject.expected @@ -0,0 +1,3 @@ +| test.c:22:15:22:16 | definition of l3 | Atomic object 'l3' has no initializer or corresponding use of 'atomic_init()'. | +| test.c:25:15:25:16 | definition of l4 | Atomic object 'l4' has no initializer or corresponding use of 'atomic_init()'. | +| test.c:29:15:29:16 | definition of l5 | Atomic object 'l5' has no initializer or corresponding use of 'atomic_init()'. | diff --git a/c/misra/test/rules/RULE-9-7/UninitializedAtomicObject.qlref b/c/misra/test/rules/RULE-9-7/UninitializedAtomicObject.qlref new file mode 100644 index 0000000000..11219b0741 --- /dev/null +++ b/c/misra/test/rules/RULE-9-7/UninitializedAtomicObject.qlref @@ -0,0 +1 @@ +rules/RULE-9-7/UninitializedAtomicObject.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-9-7/test.c b/c/misra/test/rules/RULE-9-7/test.c new file mode 100644 index 0000000000..5b3d8e36ec --- /dev/null +++ b/c/misra/test/rules/RULE-9-7/test.c @@ -0,0 +1,34 @@ +#include "stdatomic.h" +#include "threads.h" + +_Atomic int g1; // COMPLIANT +_Atomic int g2 = 0; // COMPLIANT + +void f_thread(void *x); + +void f_starts_thread() { + thrd_t t; + thrd_create(&t, f_thread, 0); +} + +void main() { + _Atomic int l1 = 1; // COMPLIANT + f_starts_thread(); + + _Atomic int l2; // COMPLIANT + atomic_init(&l2, 0); + f_starts_thread(); + + _Atomic int l3; // NON-COMPLIANT + f_starts_thread(); + + _Atomic int l4; // NON-COMPLIANT + f_starts_thread(); + atomic_init(&l4, 0); + + _Atomic int l5; // NON-COMPLIANT + if (g1 == 0) { + atomic_init(&l5, 0); + } + f_starts_thread(); +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency7.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency7.qll new file mode 100644 index 0000000000..ba492b2a6b --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency7.qll @@ -0,0 +1,44 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype Concurrency7Query = + TUninitializedAtomicObjectQuery() or + TTimedlockOnInappropriateMutexTypeQuery() + +predicate isConcurrency7QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `uninitializedAtomicObject` query + Concurrency7Package::uninitializedAtomicObjectQuery() and + queryId = + // `@id` for the `uninitializedAtomicObject` query + "c/misra/uninitialized-atomic-object" and + ruleId = "RULE-9-7" and + category = "mandatory" + or + query = + // `Query` instance for the `timedlockOnInappropriateMutexType` query + Concurrency7Package::timedlockOnInappropriateMutexTypeQuery() and + queryId = + // `@id` for the `timedlockOnInappropriateMutexType` query + "c/misra/timedlock-on-inappropriate-mutex-type" and + ruleId = "RULE-21-26" and + category = "required" +} + +module Concurrency7Package { + Query uninitializedAtomicObjectQuery() { + //autogenerate `Query` type + result = + // `Query` type for `uninitializedAtomicObject` query + TQueryC(TConcurrency7PackageQuery(TUninitializedAtomicObjectQuery())) + } + + Query timedlockOnInappropriateMutexTypeQuery() { + //autogenerate `Query` type + result = + // `Query` type for `timedlockOnInappropriateMutexType` query + TQueryC(TConcurrency7PackageQuery(TTimedlockOnInappropriateMutexTypeQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index 3833533d50..b980584877 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -11,6 +11,7 @@ import Concurrency2 import Concurrency3 import Concurrency4 import Concurrency5 +import Concurrency7 import Contracts1 import Contracts2 import Contracts3 @@ -87,6 +88,7 @@ newtype TCQuery = TConcurrency3PackageQuery(Concurrency3Query q) or TConcurrency4PackageQuery(Concurrency4Query q) or TConcurrency5PackageQuery(Concurrency5Query q) or + TConcurrency7PackageQuery(Concurrency7Query q) or TContracts1PackageQuery(Contracts1Query q) or TContracts2PackageQuery(Contracts2Query q) or TContracts3PackageQuery(Contracts3Query q) or @@ -163,6 +165,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isConcurrency3QueryMetadata(query, queryId, ruleId, category) or isConcurrency4QueryMetadata(query, queryId, ruleId, category) or isConcurrency5QueryMetadata(query, queryId, ruleId, category) or + isConcurrency7QueryMetadata(query, queryId, ruleId, category) or isContracts1QueryMetadata(query, queryId, ruleId, category) or isContracts2QueryMetadata(query, queryId, ruleId, category) or isContracts3QueryMetadata(query, queryId, ruleId, category) or diff --git a/rule_packages/c/Concurrency7.json b/rule_packages/c/Concurrency7.json new file mode 100644 index 0000000000..c544cb88c7 --- /dev/null +++ b/rule_packages/c/Concurrency7.json @@ -0,0 +1,45 @@ +{ + "MISRA-C-2012": { + "RULE-9-7": { + "properties": { + "obligation": "mandatory" + }, + "queries": [ + { + "description": "Atomic objects that do not have static storage duration shall be initialized with a value or by using 'atomic_init()'.", + "kind": "problem", + "name": "Atomic objects shall be appropriately initialized before being accessed", + "precision": "high", + "severity": "warning", + "short_name": "UninitializedAtomicObject", + "tags": [ + "concurrency", + "external/misra/c/2012/amendment4" + ] + } + ], + "title": "Atomic objects shall be appropriately initialized before being accessed" + }, + "RULE-21-26": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "The Standard Library function mtx_timedlock() shall only be invoked on mutex objects of appropriate mutex type", + "kind": "problem", + "name": "The Standard Library function mtx_timedlock() shall only be invoked on mutexes of type mtx_timed", + "precision": "high", + "severity": "error", + "short_name": "TimedlockOnInappropriateMutexType", + "tags": [ + "correctness", + "concurrency", + "external/misra/c/2012/amendment4" + ] + } + ], + "title": "The Standard Library function mtx_timedlock() shall only be invoked on mutex objects of appropriate mutex type" + } + } +} \ No newline at end of file diff --git a/rules.csv b/rules.csv index 475ea1d66c..c07aeb58ed 100644 --- a/rules.csv +++ b/rules.csv @@ -678,7 +678,7 @@ c,MISRA-C-2012,RULE-9-3,Yes,Required,,,Arrays shall not be partially initialized 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,No,Required,,,Where designated initializers are used to initialize an array object the size of the array shall be specified explicitly,,,Medium, c,MISRA-C-2012,RULE-9-6,Yes,Required,,,An initializer using chained designators shall not contain initializers without designators,,Declarations9,Hard, -c,MISRA-C-2012,RULE-9-7,Yes,Mandatory,,,Atomic objects shall be appropriately initialized before being accessed,,Concurrency6,Hard, +c,MISRA-C-2012,RULE-9-7,Yes,Mandatory,,,Atomic objects shall be appropriately initialized before being accessed,,Concurrency7,Hard, c,MISRA-C-2012,RULE-10-1,Yes,Required,,,Operands shall not be of an inappropriate essential type,,EssentialTypes,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,,EssentialTypes,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,,EssentialTypes,Hard, @@ -791,7 +791,7 @@ c,MISRA-C-2012,RULE-21-22,Yes,Mandatory,,,All operand arguments to any type-gene c,MISRA-C-2012,RULE-21-23,Yes,Required,,,All operand arguments to any multi-argument type-generic macros in shall have the same standard type,Rule-21-22,EssentialTypes2,Easy, c,MISRA-C-2012,RULE-21-24,Yes,Required,,,The random number generator functions of shall not be used,MSC30-C,Banned2,Easy, c,MISRA-C-2012,RULE-21-25,Yes,Required,,,All memory synchronization operations shall be executed in sequentially consistent order,,Concurrency6,Medium, -c,MISRA-C-2012,RULE-21-26,Yes,Required,,,The Standard Library function mtx_timedlock() shall only be invoked on mutex objects of appropriate mutex type,,Concurrency6,Hard, +c,MISRA-C-2012,RULE-21-26,Yes,Required,,,The Standard Library function mtx_timedlock() shall only be invoked on mutex objects of appropriate mutex type,,Concurrency8,Hard, c,MISRA-C-2012,RULE-22-1,Yes,Required,,,All resources obtained dynamically by means of Standard Library functions shall be explicitly released,,Memory2,Hard, c,MISRA-C-2012,RULE-22-2,Yes,Mandatory,,,A block of memory shall only be freed if it was allocated by means of a Standard Library function,,Memory2,Hard, c,MISRA-C-2012,RULE-22-3,Yes,Required,,,The same file shall not be open for read and write access at the same time on different streams,,IO3,Hard, From 8a2076e5934d46a0ef70478ffd82b6bc146f884b Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 18 Nov 2024 00:03:04 -0800 Subject: [PATCH 053/370] Fix query metadata --- rule_packages/c/Concurrency7.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rule_packages/c/Concurrency7.json b/rule_packages/c/Concurrency7.json index c544cb88c7..f764468ae3 100644 --- a/rule_packages/c/Concurrency7.json +++ b/rule_packages/c/Concurrency7.json @@ -27,7 +27,7 @@ "queries": [ { "description": "The Standard Library function mtx_timedlock() shall only be invoked on mutex objects of appropriate mutex type", - "kind": "problem", + "kind": "path-problem", "name": "The Standard Library function mtx_timedlock() shall only be invoked on mutexes of type mtx_timed", "precision": "high", "severity": "error", From 6f36b1c322d9c48599de3bc6829aeaa158c76704 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 18 Nov 2024 12:48:30 -0800 Subject: [PATCH 054/370] Fix query metadata, format --- .../TimedlockOnInappropriateMutexType.ql | 2 +- .../RULE-9-7/UninitializedAtomicObject.ql | 28 ++++++++++--------- rule_packages/c/Concurrency7.json | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql b/c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql index d8d465045e..e6dda61d79 100644 --- a/c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql +++ b/c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql @@ -2,7 +2,7 @@ * @id c/misra/timedlock-on-inappropriate-mutex-type * @name RULE-21-26: The Standard Library function mtx_timedlock() shall only be invoked on mutexes of type mtx_timed * @description The Standard Library function mtx_timedlock() shall only be invoked on mutex objects - * of appropriate mutex type + * of appropriate mutex type. * @kind path-problem * @precision high * @problem.severity error diff --git a/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql b/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql index 40f833a740..006e8e8178 100644 --- a/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql +++ b/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql @@ -18,11 +18,14 @@ import semmle.code.cpp.controlflow.Dominance class ThreadSpawningFunction extends Function { ThreadSpawningFunction() { - this.hasName("pthread_create") or - this.hasName("thrd_create") or + this.hasName("pthread_create") + or + this.hasName("thrd_create") + or exists(FunctionCall fc | fc.getTarget() instanceof ThreadSpawningFunction and - fc.getEnclosingFunction() = this) + fc.getEnclosingFunction() = this + ) } } @@ -37,9 +40,7 @@ class AtomicInitAddressOfExpr extends FunctionCall { ) } - Expr getAddressedExpr() { - result = addressedExpr - } + Expr getAddressedExpr() { result = addressedExpr } } ControlFlowNode getARequiredInitializationPoint(LocalScopeVariable v) { @@ -47,11 +48,12 @@ ControlFlowNode getARequiredInitializationPoint(LocalScopeVariable v) { or exists(DeclStmt decl | decl.getADeclaration() = v and - result = any(FunctionCall fc - | fc.getTarget() instanceof ThreadSpawningFunction and - fc.getEnclosingBlock().getEnclosingBlock*() = v.getParentScope() and - fc.getAPredecessor*() = decl - ) + result = + any(FunctionCall fc | + fc.getTarget() instanceof ThreadSpawningFunction and + fc.getEnclosingBlock().getEnclosingBlock*() = v.getParentScope() and + fc.getAPredecessor*() = decl + ) ) } @@ -63,8 +65,8 @@ where not v.isTopLevel() and not exists(v.getInitializer()) and exists(ControlFlowNode missingInitPoint | - missingInitPoint = getARequiredInitializationPoint(v) - and not exists(AtomicInitAddressOfExpr initialization | + missingInitPoint = getARequiredInitializationPoint(v) and + not exists(AtomicInitAddressOfExpr initialization | initialization.getAddressedExpr().(VariableAccess).getTarget() = v and dominates(initialization, missingInitPoint) ) diff --git a/rule_packages/c/Concurrency7.json b/rule_packages/c/Concurrency7.json index f764468ae3..6fdc49984b 100644 --- a/rule_packages/c/Concurrency7.json +++ b/rule_packages/c/Concurrency7.json @@ -26,7 +26,7 @@ }, "queries": [ { - "description": "The Standard Library function mtx_timedlock() shall only be invoked on mutex objects of appropriate mutex type", + "description": "The Standard Library function mtx_timedlock() shall only be invoked on mutex objects of appropriate mutex type.", "kind": "path-problem", "name": "The Standard Library function mtx_timedlock() shall only be invoked on mutexes of type mtx_timed", "precision": "high", From 9ac5159694585358fe6bf267d26b4062350b726f Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 18 Nov 2024 12:56:07 -0800 Subject: [PATCH 055/370] Fix rule 21-26 packages in rules.csv: Concurrency7 not 8. --- rules.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules.csv b/rules.csv index c07aeb58ed..b914f7cad5 100644 --- a/rules.csv +++ b/rules.csv @@ -791,7 +791,7 @@ c,MISRA-C-2012,RULE-21-22,Yes,Mandatory,,,All operand arguments to any type-gene c,MISRA-C-2012,RULE-21-23,Yes,Required,,,All operand arguments to any multi-argument type-generic macros in shall have the same standard type,Rule-21-22,EssentialTypes2,Easy, c,MISRA-C-2012,RULE-21-24,Yes,Required,,,The random number generator functions of shall not be used,MSC30-C,Banned2,Easy, c,MISRA-C-2012,RULE-21-25,Yes,Required,,,All memory synchronization operations shall be executed in sequentially consistent order,,Concurrency6,Medium, -c,MISRA-C-2012,RULE-21-26,Yes,Required,,,The Standard Library function mtx_timedlock() shall only be invoked on mutex objects of appropriate mutex type,,Concurrency8,Hard, +c,MISRA-C-2012,RULE-21-26,Yes,Required,,,The Standard Library function mtx_timedlock() shall only be invoked on mutex objects of appropriate mutex type,,Concurrency7,Hard, c,MISRA-C-2012,RULE-22-1,Yes,Required,,,All resources obtained dynamically by means of Standard Library functions shall be explicitly released,,Memory2,Hard, c,MISRA-C-2012,RULE-22-2,Yes,Mandatory,,,A block of memory shall only be freed if it was allocated by means of a Standard Library function,,Memory2,Hard, c,MISRA-C-2012,RULE-22-3,Yes,Required,,,The same file shall not be open for read and write access at the same time on different streams,,IO3,Hard, From 503830ae350fd6979d120ceb992ca855e28680ce Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 22 Nov 2024 20:36:39 -0800 Subject: [PATCH 056/370] Implement Concurrency8 package --- ...AppropriateThreadObjectStorageDurations.ql | 43 +- ...propriateStorageDurationsFunctionReturn.ql | 11 +- ...DoNotModifyObjectsWithTemporaryLifetime.ql | 12 +- ...uctsWithAFlexibleArrayMemberDynamically.ql | 20 +- ...odifyObjectsWithTemporaryLifetime.expected | 8 +- .../codingstandards/c/IdentifierLinkage.qll | 47 +++ c/common/src/codingstandards/c/Objects.qll | 393 ++++++++++++++++++ .../src/codingstandards/c/StorageDuration.qll | 31 ++ .../codingstandards/c/UninitializedMutex.qll | 0 .../IdentifierLinkage.expected | 10 + .../identifierlinkage/IdentifierLinkage.ql | 5 + .../identifierlinkage/identifierlinkage.c | 30 ++ .../library/objects/ObjectIdentity.expected | 21 + .../test/library/objects/ObjectIdentity.ql | 5 + .../test/library/objects/objectidentity.c | 41 ++ ...rayToPointerConversionOfTemporaryObject.ql | 6 +- ...eLValueSubscriptedWithTemporaryLifetime.ql | 40 +- .../NonstandardUseOfThreadingObject.ql | 54 +++ ...readingObjectWithInvalidStorageDuration.ql | 31 ++ .../MutexInitWithInvalidMutexType.ql | 36 ++ .../MutexInitializedInsideThread.ql | 27 ++ .../MutexNotInitializedBeforeUse.ql | 130 ++++++ .../MutexObjectsNotAlwaysUnlocked.ql | 52 +++ ...ointerConversionOfTemporaryObject.expected | 8 +- ...eSubscriptedWithTemporaryLifetime.expected | 6 +- .../NonstandardUseOfThreadingObject.expected | 27 ++ .../NonstandardUseOfThreadingObject.qlref | 1 + c/misra/test/rules/RULE-22-12/test.c | 65 +++ ...gObjectWithInvalidStorageDuration.expected | 13 + ...dingObjectWithInvalidStorageDuration.qlref | 1 + c/misra/test/rules/RULE-22-13/test.c | 53 +++ .../MutexInitWithInvalidMutexType.expected | 5 + .../MutexInitWithInvalidMutexType.qlref | 1 + .../MutexInitializedInsideThread.expected | 1 + .../MutexInitializedInsideThread.qlref | 1 + .../MutexNotInitializedBeforeUse.expected | 14 + .../MutexNotInitializedBeforeUse.qlref | 1 + c/misra/test/rules/RULE-22-14/test.c | 146 +++++++ .../MutexObjectsNotAlwaysUnlocked.expected | 7 + .../MutexObjectsNotAlwaysUnlocked.qlref | 1 + c/misra/test/rules/RULE-22-16/test.c | 107 +++++ change_notes/2024-11-27-c-object-refactor.md | 21 + ...24-11-27-raii-concurrency-analysis-perf.md | 2 + ...4-11-27-resource-leak-analysis-refactor.md | 10 + .../src/codingstandards/cpp/Clvalues.qll | 3 + .../src/codingstandards/cpp/Concurrency.qll | 67 ++- cpp/common/src/codingstandards/cpp/Type.qll | 26 +- .../cpp/exclusions/c/Concurrency8.qll | 112 +++++ .../cpp/exclusions/c/RuleMetadata.qll | 3 + .../cpp/lifetimes/CLifetimes.qll | 48 --- .../cpp/resources/ResourceLeakAnalysis.qll | 101 +++++ .../cpp/resources/ResourceManagement.qll | 75 ++-- .../ExceptionSafetyValidState.qll | 63 +-- .../ExceptionSafetyValidState.expected | 8 +- rule_packages/c/Concurrency8.json | 115 +++++ rules.csv | 8 +- 56 files changed, 1964 insertions(+), 209 deletions(-) create mode 100644 c/common/src/codingstandards/c/IdentifierLinkage.qll create mode 100644 c/common/src/codingstandards/c/Objects.qll create mode 100644 c/common/src/codingstandards/c/StorageDuration.qll create mode 100644 c/common/src/codingstandards/c/UninitializedMutex.qll create mode 100644 c/common/test/library/identifierlinkage/IdentifierLinkage.expected create mode 100644 c/common/test/library/identifierlinkage/IdentifierLinkage.ql create mode 100644 c/common/test/library/identifierlinkage/identifierlinkage.c create mode 100644 c/common/test/library/objects/ObjectIdentity.expected create mode 100644 c/common/test/library/objects/ObjectIdentity.ql create mode 100644 c/common/test/library/objects/objectidentity.c create mode 100644 c/misra/src/rules/RULE-22-12/NonstandardUseOfThreadingObject.ql create mode 100644 c/misra/src/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.ql create mode 100644 c/misra/src/rules/RULE-22-14/MutexInitWithInvalidMutexType.ql create mode 100644 c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql create mode 100644 c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql create mode 100644 c/misra/src/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.ql create mode 100644 c/misra/test/rules/RULE-22-12/NonstandardUseOfThreadingObject.expected create mode 100644 c/misra/test/rules/RULE-22-12/NonstandardUseOfThreadingObject.qlref create mode 100644 c/misra/test/rules/RULE-22-12/test.c create mode 100644 c/misra/test/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.expected create mode 100644 c/misra/test/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.qlref create mode 100644 c/misra/test/rules/RULE-22-13/test.c create mode 100644 c/misra/test/rules/RULE-22-14/MutexInitWithInvalidMutexType.expected create mode 100644 c/misra/test/rules/RULE-22-14/MutexInitWithInvalidMutexType.qlref create mode 100644 c/misra/test/rules/RULE-22-14/MutexInitializedInsideThread.expected create mode 100644 c/misra/test/rules/RULE-22-14/MutexInitializedInsideThread.qlref create mode 100644 c/misra/test/rules/RULE-22-14/MutexNotInitializedBeforeUse.expected create mode 100644 c/misra/test/rules/RULE-22-14/MutexNotInitializedBeforeUse.qlref create mode 100644 c/misra/test/rules/RULE-22-14/test.c create mode 100644 c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.expected create mode 100644 c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.qlref create mode 100644 c/misra/test/rules/RULE-22-16/test.c create mode 100644 change_notes/2024-11-27-c-object-refactor.md create mode 100644 change_notes/2024-11-27-raii-concurrency-analysis-perf.md create mode 100644 change_notes/2024-11-27-resource-leak-analysis-refactor.md create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency8.qll delete mode 100644 cpp/common/src/codingstandards/cpp/lifetimes/CLifetimes.qll create mode 100644 cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll create mode 100644 rule_packages/c/Concurrency8.json diff --git a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql index e0617c266d..6d9caacc5c 100644 --- a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql +++ b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql @@ -14,30 +14,39 @@ import cpp import codingstandards.c.cert +import codingstandards.c.Objects import codingstandards.cpp.Concurrency import codingstandards.cpp.dataflow.TaintTracking import codingstandards.cpp.dataflow.DataFlow import semmle.code.cpp.commons.Alloc -from C11ThreadCreateCall tcc, StackVariable sv, Expr arg, Expr acc +from C11ThreadCreateCall tcc, Expr arg where not isExcluded(tcc, Concurrency4Package::appropriateThreadObjectStorageDurationsQuery()) and tcc.getArgument(2) = arg and - sv.getAnAccess() = acc and - // a stack variable that is given as an argument to a thread - TaintTracking::localTaint(DataFlow::exprNode(acc), DataFlow::exprNode(arg)) and - // or isn't one of the allowed usage patterns - not exists(Expr mfc | - isAllocationExpr(mfc) and - sv.getAnAssignedValue() = mfc and - acc.getAPredecessor*() = mfc - ) and - not exists(TSSGetFunctionCall tsg, TSSSetFunctionCall tss, DataFlow::Node src | - sv.getAnAssignedValue() = tsg and - acc.getAPredecessor*() = tsg and - // there should be dataflow from somewhere (the same somewhere) - // into each of the first arguments - DataFlow::localFlow(src, DataFlow::exprNode(tsg.getArgument(0))) and - DataFlow::localFlow(src, DataFlow::exprNode(tss.getArgument(0))) + ( + exists(ObjectIdentity obj, Expr acc | + obj.getASubobjectAccess() = acc and + obj.getStorageDuration().isAutomatic() and + exists(DataFlow::Node addrNode | + ( + addrNode = DataFlow::exprNode(any(AddressOfExpr e | e.getOperand() = acc)) + or + addrNode = DataFlow::exprNode(acc) and exists(ArrayToPointerConversion c | c.getExpr() = acc) + ) and + TaintTracking::localTaint(addrNode, DataFlow::exprNode(arg)) + ) + ) + or + // TODO: Remove/replace with tss_t type check, see #801. + exists(TSSGetFunctionCall tsg | + TaintTracking::localTaint(DataFlow::exprNode(tsg), DataFlow::exprNode(arg)) and + not exists(TSSSetFunctionCall tss, DataFlow::Node src | + // there should be dataflow from somewhere (the same somewhere) + // into each of the first arguments + DataFlow::localFlow(src, DataFlow::exprNode(tsg.getArgument(0))) and + DataFlow::localFlow(src, DataFlow::exprNode(tss.getArgument(0))) + ) + ) ) select tcc, "$@ not declared with appropriate storage duration", arg, "Shared object" diff --git a/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql b/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql index 9097f14297..1e1e19c7c6 100644 --- a/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql +++ b/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql @@ -13,10 +13,15 @@ import cpp import codingstandards.c.cert +import codingstandards.c.Objects import codingstandards.cpp.dataflow.DataFlow -class Source extends StackVariable { - Source() { not this instanceof Parameter } +class Source extends Expr { + ObjectIdentity rootObject; + Source() { + rootObject.getStorageDuration().isAutomatic() + and this = rootObject.getASubobjectAddressExpr() + } } class Sink extends DataFlow::Node { @@ -40,7 +45,7 @@ from DataFlow::Node src, DataFlow::Node sink where not isExcluded(sink.asExpr(), Declarations8Package::appropriateStorageDurationsFunctionReturnQuery()) and - exists(Source s | src.asExpr() = s.getAnAccess()) and + exists(Source s | src.asExpr() = s) and sink instanceof Sink and DataFlow::localFlow(src, sink) select sink, "$@ with automatic storage may be accessible outside of its lifetime.", src, diff --git a/c/cert/src/rules/EXP35-C/DoNotModifyObjectsWithTemporaryLifetime.ql b/c/cert/src/rules/EXP35-C/DoNotModifyObjectsWithTemporaryLifetime.ql index 6a018ed8c4..3689aa4397 100644 --- a/c/cert/src/rules/EXP35-C/DoNotModifyObjectsWithTemporaryLifetime.ql +++ b/c/cert/src/rules/EXP35-C/DoNotModifyObjectsWithTemporaryLifetime.ql @@ -13,15 +13,13 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.lifetimes.CLifetimes +import codingstandards.c.Objects // Note: Undefined behavior is possible regardless of whether the accessed field from the returned // struct is an array or a scalar (i.e. arithmetic and pointer types) member, according to the standard. -from FieldAccess fa, FunctionCall fc +from FieldAccess fa, TemporaryObjectIdentity tempObject where not isExcluded(fa, InvalidMemory2Package::doNotModifyObjectsWithTemporaryLifetimeQuery()) and - not fa.getQualifier().isLValue() and - fa.getQualifier().getUnconverted() = fc and - fa.getQualifier().getUnconverted().getUnspecifiedType() instanceof StructOrUnionTypeWithArrayField -select fa, "Field access on $@ qualifier occurs after its temporary object lifetime.", fc, - "function call" + fa.getQualifier().getUnconverted() = tempObject +select fa, "Field access on $@ qualifier occurs after its temporary object lifetime.", tempObject, + "temporary object" diff --git a/c/cert/src/rules/MEM33-C/AllocStructsWithAFlexibleArrayMemberDynamically.ql b/c/cert/src/rules/MEM33-C/AllocStructsWithAFlexibleArrayMemberDynamically.ql index 620c4486a9..4e4ccc2171 100644 --- a/c/cert/src/rules/MEM33-C/AllocStructsWithAFlexibleArrayMemberDynamically.ql +++ b/c/cert/src/rules/MEM33-C/AllocStructsWithAFlexibleArrayMemberDynamically.ql @@ -14,6 +14,7 @@ import cpp import codingstandards.c.cert import codingstandards.c.Variable +import codingstandards.c.Objects import semmle.code.cpp.models.interfaces.Allocation import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis @@ -21,7 +22,7 @@ abstract class FlexibleArrayAlloc extends Element { /** * Returns the `Variable` being allocated. */ - abstract Variable getVariable(); + abstract Element getReportElement(); } /** @@ -53,18 +54,25 @@ class FlexibleArrayStructDynamicAlloc extends FlexibleArrayAlloc, FunctionCall { ) } - override Variable getVariable() { result = v } + override Element getReportElement() { result = v } } /** * A `Variable` of type `FlexibleArrayStructType` that is not allocated dynamically. */ -class FlexibleArrayNonDynamicAlloc extends FlexibleArrayAlloc, Variable { +class FlexibleArrayNonDynamicAlloc extends FlexibleArrayAlloc { + ObjectIdentity object; FlexibleArrayNonDynamicAlloc() { - this.getUnspecifiedType().getUnspecifiedType() instanceof FlexibleArrayStructType + this = object and + not object.getStorageDuration().isAllocated() and + // Exclude temporaries. Though they should violate this rule, in practice these results are + // often spurious and redundant, such as (*x = *x) which creates an unused temporary object. + not object.hasTemporaryLifetime() and + object.getType().getUnspecifiedType() instanceof FlexibleArrayStructType + and not exists(Variable v | v.getInitializer().getExpr() = this) } - override Variable getVariable() { result = this } + override Element getReportElement() { result = object } } from FlexibleArrayAlloc alloc, string message @@ -77,4 +85,4 @@ where alloc instanceof FlexibleArrayNonDynamicAlloc and message = "$@ contains a flexible array member but is not dynamically allocated." ) -select alloc, message, alloc.getVariable(), alloc.getVariable().getName() +select alloc, message, alloc.getReportElement(), alloc.getReportElement().toString() diff --git a/c/cert/test/rules/EXP35-C/DoNotModifyObjectsWithTemporaryLifetime.expected b/c/cert/test/rules/EXP35-C/DoNotModifyObjectsWithTemporaryLifetime.expected index f14ab4de4a..3fb10f3267 100644 --- a/c/cert/test/rules/EXP35-C/DoNotModifyObjectsWithTemporaryLifetime.expected +++ b/c/cert/test/rules/EXP35-C/DoNotModifyObjectsWithTemporaryLifetime.expected @@ -1,4 +1,4 @@ -| test.c:65:18:65:18 | a | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:65:9:65:14 | call to get_s1 | function call | -| test.c:67:18:67:19 | s1 | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:67:9:67:14 | call to get_s3 | function call | -| test.c:68:18:68:19 | i1 | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:68:9:68:14 | call to get_s3 | function call | -| test.c:69:18:69:21 | af12 | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:69:9:69:14 | call to get_s4 | function call | +| test.c:65:18:65:18 | a | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:65:9:65:14 | call to get_s1 | temporary object | +| test.c:67:18:67:19 | s1 | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:67:9:67:14 | call to get_s3 | temporary object | +| test.c:68:18:68:19 | i1 | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:68:9:68:14 | call to get_s3 | temporary object | +| test.c:69:18:69:21 | af12 | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:69:9:69:14 | call to get_s4 | temporary object | diff --git a/c/common/src/codingstandards/c/IdentifierLinkage.qll b/c/common/src/codingstandards/c/IdentifierLinkage.qll new file mode 100644 index 0000000000..085ebf5a7b --- /dev/null +++ b/c/common/src/codingstandards/c/IdentifierLinkage.qll @@ -0,0 +1,47 @@ +import cpp + +newtype TIdentifierLinkage = + TIdentifierLinkageExternal() or + TIdentifierLinkageInternal() or + TIdentifierLinkageNone() + +/** + * In C, identifiers have internal linkage, or external linkage, or no linkage (6.2.2.1). + * + * The linkage of an identifier is used to, among other things, determine the storage duration + * and/or lifetime of that identifier. Storage durations and lifetimes are often used to define + * rules in the various coding standards. + */ +class IdentifierLinkage extends TIdentifierLinkage { + predicate isExternal() { this = TIdentifierLinkageExternal() } + + predicate isInternal() { this = TIdentifierLinkageInternal() } + + predicate isNone() { this = TIdentifierLinkageNone() } + + string toString() { + this.isExternal() and result = "external linkage" + or + this.isInternal() and result = "internal linkage" + or + this.isNone() and result = "no linkage" + } +} + +/** + * Determine the linkage of a variable: external, or static, or none. + * + * The linkage of a variable is determined by its scope and storage class. Note that other types of + * identifiers (e.g. functions) may also have linkage, but that behavior is not covered in this + * predicate. + */ +IdentifierLinkage linkageOfVariable(Variable v) { + // 6.2.2.3, file scope identifiers marked static have internal linkage. + v.isTopLevel() and v.isStatic() and result.isInternal() + or + // 6.2.2.4 describes generally non-static file scope identifiers, which have external linkage. + v.isTopLevel() and not v.isStatic() and result.isExternal() + or + // Note: Not all identifiers have linkage, see 6.2.2.6 + not v.isTopLevel() and result.isNone() +} diff --git a/c/common/src/codingstandards/c/Objects.qll b/c/common/src/codingstandards/c/Objects.qll new file mode 100644 index 0000000000..105291c688 --- /dev/null +++ b/c/common/src/codingstandards/c/Objects.qll @@ -0,0 +1,393 @@ +import cpp +import codingstandards.c.StorageDuration +import codingstandards.c.IdentifierLinkage +import semmle.code.cpp.valuenumbering.HashCons +import codingstandards.cpp.Clvalues + +/** + * A libary for handling "Objects" in C. + * + * Objects may be stored in registers or memory, they have an address, a type, a storage duration, + * and a lifetime (which is different than storage duration). Objects which are structs or arrays + * have subobjects, which share the storage duration and lifetime of the parent object. + * + * Note: lifetime analysis is not performed in this library, but is available in + * the module `codingstandards.cpp.lifetimes.LifetimeProfile`. In the future, these libraries could + * be merged for more complete analysis. + * + * To get objects in a project, use the `ObjectIdentity` class which finds the following types of + * objects: + * - global variables + * - local variables + * - literals + * - malloc calls + * - certain temporary object expressions + * + * And direct references to these objects can be found via the member predicate `getAnAccess()`. + * However, much of a project's code will not refer to these objects directly, but rather, refer to + * their subobjects. The class `ObjectIdentity` exposes several member predicates for finding when + * these subobjects are used: + * - `getASubobjectType()` + * - `getASubobjectAccess()` + * - `getASubobjectAddressExpr()` + * + * These methods do not use flow analysis, and will not return a conclusive list of accesses. To + * get better results here, this library should be integrated with flow analysis or the library + * `LifetimeProfile.qll`. + * + * Additionally, subobjects are currently not tracked individually. In the future subobjects could + * be tracked as a root object and an access chain to refer to them. For now, however, finding *any* + * subobject access is sufficient for many analyses. + * + * To get the storage duration, `ObjectIdentity` exposes the member predicate + * `getStorageDuration()` with the following options: + * - `obj.getStorageDuration().isAutomatic()`: Stack objects + * - `obj.getStorageDuration().isStatic()`: Global objects + * - `obj.getStorageDuration().isThread()`: Threadlocal objects + * - `obj.getStorageDuration().isAllocated()`: Dynamic objects + * + * Note that lifetimes are not storage durations. The only lifetime tracking currently implemented + * is `hasTemporaryLifetime()`, which is a subset of automatic storage duration objects, and may + * be filtered out, or selected directly with `TemporaryObjectIdentity`. + */ +final class ObjectIdentity = ObjectIdentityBase; + +/** + * A base class for objects in C, along with the source location where the object can be identified + * in the project code (thus, this class extends `Element`), which may be variable, or may be an + * expression such as a literal or a malloc call. + * + * Extend this class to define a new type of object identity. To create a class which filters the + * set of object identities, users of this library should extend the final subclass + * `ObjectIdentity` instead. + */ +abstract class ObjectIdentityBase extends Element { + /** + * The type of this object. + * + * Note that for allocated objects, this is inferred from the sizeof() statement or the variable + * it is assigned to. + */ + abstract Type getType(); + + /* The storage duration of this object: static, thread, automatic, or allocated. */ + abstract StorageDuration getStorageDuration(); + + /** + * Get the nested objects within this object (members, array element types). + * + * Note that if a struct has a pointer member, the pointer itself is a subobject, but the value + * it points to is not. Therefore `struct { int* x; }` has a subobject of type `int*`, but not + * `int`. + */ + Type getASubObjectType() { result = getADirectSubobjectType*(getType()) } + + /** + * Get expressions which trivially access this object. Does not perform flow analysis. + * + * For dynamically allocated objects, this is a dereference of the malloc call. + */ + abstract Expr getAnAccess(); + + /** + * Get expressions which trivially access this object or a subobject of this object. Does not + * perform flow analysis. + * + * For dynamically allocated objects, this is a dereference of the malloc call or direct access + * of the result of dereferencing the malloc call. + */ + Expr getASubobjectAccess() { result = getASubobjectAccessOf(getAnAccess()) } + + /** + * Get expressions which trivially take the address of this object or a subobject of this object. + * Does not perform flow analysis. + */ + Expr getASubobjectAddressExpr() { + exists(Expr subobject | + subobject = getASubobjectAccess() and + ( + result = any(AddressOfExpr e | e.getOperand() = subobject) + or + exists(ArrayToPointerConversion c | c.getExpr() = subobject) and + not exists(ArrayExpr a | a.getArrayBase() = subobject) and + result = subobject + ) + ) + } + + /** + * Holds if the object has temporary lifetime. This is not a storage duration, but only objects + * with automatic storage duration have temporary lifetime. + */ + abstract predicate hasTemporaryLifetime(); +} + +/** + * Finds expressions `e.x` or `e[x]` for expression `e`, recursively. Does not resolve pointers. + * + * Note that this does not hold for `e->x` or `e[x]` where `e` is a pointer. + */ +private Expr getASubobjectAccessOf(Expr e) { + result = e + or + result.(DotFieldAccess).getQualifier() = getASubobjectAccessOf(e) + or + result.(ArrayExpr).getArrayBase() = getASubobjectAccessOf(e) and + not result.(ArrayExpr).getArrayBase().getUnspecifiedType() instanceof PointerType +} + +/** + * Find the object types that are embedded within the current type. + * + * For example, a block of memory with type `T[]` has subobjects of type `T`, and a struct with a + * member of `T member;` has a subobject of type `T`. + * + * Note that subobjects may be pointers, but the value they point to is not a subobject. For + * instance, `struct { int* x; }` has a subobject of type `int*`, but not `int`. + */ +Type getADirectSubobjectType(Type type) { + result = type.stripTopLevelSpecifiers().(Struct).getAMember().getADeclarationEntry().getType() + or + result = type.stripTopLevelSpecifiers().(ArrayType).getBaseType() +} + +/** + * An object in memory which may be identified by the variable that holds it. + * + * This may be a local variable, a global variable, or a parameter, etc. However, it cannot be a + * member of a struct or union, as these do not have storage duration. + */ +class VariableObjectIdentity extends Variable, ObjectIdentityBase { + VariableObjectIdentity() { + // Exclude members; member definitions does not allocate storage and thus do not have a storage + // duration. They are therefore not objects. To get the storage duration of members, use one of + // the predicates related to sub objects, e.g. `getASubObjectType()`. + not isMember() + } + + override StorageDuration getStorageDuration() { + // 6.2.4.4, objects declared _Thread_local have thread storage duration. + isThreadLocal() and result.isThread() + or + // 6.2.4.3, Non _ThreadLocal objects with internal or external linkage or declared static have + // static storage duration. + not isThreadLocal() and + (hasLinkage() or isStatic()) and + result.isStatic() + or + // 6.2.4.3, Non _ThreadLocal objects no linkage that are not static have automatic storage + // duration. + not isThreadLocal() and + not hasLinkage() and + not isStatic() and + result.isAutomatic() + } + + override Type getType() { + // Caution here: If we use `Variable.super.getType()` then override resolution is skipped, and + // it uses the base predicate defined as `none()`. By casting this to `Variable` and calling + // `getType()`, all overrides (harmlessly, *including this one*...) are considered, which means + // we defer to the subclasses such as `GlobalVariable` overrides of `getType()`, which is what + // we want. + result = this.(Variable).getType() + } + + /* The storage duration of a variable depends on its linkage. */ + IdentifierLinkage getLinkage() { result = linkageOfVariable(this) } + + predicate hasLinkage() { not getLinkage().isNone() } + + override VariableAccess getAnAccess() { result = Variable.super.getAnAccess() } + + override predicate hasTemporaryLifetime() { + none() // Objects identified by a variable do not have temporary lifetime. + } +} + +/** + * A string literal is an object with static storage duration. + * + * 6.4.5.6, multibyte character sequences initialize an array of static storage duration. + */ +class LiteralObjectIdentity extends Literal, ObjectIdentityBase { + override StorageDuration getStorageDuration() { result.isStatic() } + + override Type getType() { result = Literal.super.getType() } + + override Expr getAnAccess() { result = this } + + override predicate hasTemporaryLifetime() { + none() // String literal objects do not have temporary lifetime. + } +} + +/** + * An object identifiable as a struct or array literal, which is an lvalue that may have static or + * automatic storage duration depending on context. + * + * 6.5.2.5.5, compound literals outside of a function have static storage duration, while literals + * inside a function have automatic storage duration. + */ +class AggregateLiteralObjectIdentity extends AggregateLiteral, ObjectIdentityBase { + override StorageDuration getStorageDuration() { + if exists(getEnclosingFunction()) then result.isAutomatic() else result.isStatic() + } + + override Type getType() { result = AggregateLiteral.super.getType() } + + override Expr getAnAccess() { result = this } + + override predicate hasTemporaryLifetime() { + // Confusing; a struct literal is an lvalue, and therefore does not have temporary lifetime. + none() + } +} + +/** + * An object identified by a call to `malloc`. + * + * Note: the malloc expression returns an address to this object, not the object itself. Therefore, + * `getAnAccess()` returns cases where this malloc result is dereferenced, and not the malloc call + * itself. + * + * Note that the predicates for tracking accesses, subobject accesses, and address expresisons may + * be less reliable as dynamic memory is fundamentally more difficult to track. However, this class + * attempts to give reasonable results. In the future, this could be improved by integrating with + * LifetimeProfile.qll or by integrating flow analysis. + * + * Additionally, the type of this object is inferred based on its size and use. + */ +class AllocatedObjectIdentity extends AllocationExpr, ObjectIdentityBase { + AllocatedObjectIdentity() { + this.(FunctionCall).getTarget().(AllocationFunction).requiresDealloc() + } + + override StorageDuration getStorageDuration() { result.isAllocated() } + + /** Attempt to infer the type of the allocated memory */ + override Type getType() { result = this.getAllocatedElementType() } + + /** Find dereferences of direct aliases of this pointer result. */ + override Expr getAnAccess() { result.(PointerDereferenceExpr).getOperand() = getAnAlias() } + + /** + * Find the following subobject accesses, given a pointer alias `x`: + * - `(*x)` + * - `(*x).y` + * - `(*x)[i]` + * - `x->y` + * - `x[i]` + * - `x->y.z` + * - `x[i].y` + * - all direct accesses (`foo.x`, `foo[i]`) of the above + */ + override Expr getASubobjectAccess() { + result = getASubobjectAccessOf(getAnAccess()) + or + exists(PointerFieldAccess pfa | + pfa.getQualifier() = getASubobjectAddressExpr() and + result = getASubobjectAccessOf(pfa) + ) + or + exists(ArrayExpr arrayExpr | + arrayExpr.getArrayBase() = getASubobjectAddressExpr() and + result = getASubobjectAccessOf(arrayExpr) + ) + } + + /** + * Given a pointer alias `x`, finds `x` itself. Additionally, defers to the default class + * behavior, which finds address-of (`&`) and array-to-pointer conversions of all subobject + * accesses. (See `AllocatedObjectIdentity.getASubobjectAccess()`.) + */ + override Expr getASubobjectAddressExpr() { + result = getAnAlias() + or + result = super.getASubobjectAddressExpr() + } + + /** + * Find an obvious direct reference to the result of a `malloc()` function call. This includes + * the function call itself, but additionally: + * - For `T* x = malloc(...)`, accesses to variable `x` are likely aliases of the malloc result + * - For `(expr) = malloc(...)` future lexically identical uses of `expr` are likely aliases of + * the malloc result. + * + * This is used so that member predicates such as `getAnAccess()`, `getASubobjectAccess()` can + * find cases such as: + * + * ```c + * int *x = malloc(sizeof(int)); + * return *x; // accesses the malloc result + * ``` + */ + Expr getAnAlias() { + result = this + or + exists(AssignExpr assignExpr | + assignExpr.getRValue() = this and + hashCons(result) = hashCons(assignExpr.getLValue()) + ) + or + exists(Variable v | + v.getInitializer().getExpr() = this and + result = v.getAnAccess() + ) + } + + override predicate hasTemporaryLifetime() { + none() // Allocated objects do not have "temporary lifetime." + } +} + +/** + * A struct or union type that contains an array type, used to find objects with temporary + * lifetime. + */ +private class StructOrUnionTypeWithArrayField extends Struct { + StructOrUnionTypeWithArrayField() { + this.getAField().getUnspecifiedType() instanceof ArrayType + or + // nested struct or union containing an array type + this.getAField().getUnspecifiedType().(Struct) instanceof StructOrUnionTypeWithArrayField + } +} + +/** + * 6.2.4.7, A non-lvalue expression with struct or or union type that has a field member of array + * type, refers to an object with automatic storage duration (and has temporary lifetime). + * + * The spec uses the lanugage "refers to." This is likely intended to mean that the expression + * `foo().x` does not create a new temporary object, but rather "refers to" the temporary object + * storing the value of the expression `foo()`. + * + * Separate this predicate to avoid non-monotonic recursion (`C() { not exists(C c | ... ) }`). + */ +private class TemporaryObjectIdentityExpr extends Expr { + TemporaryObjectIdentityExpr() { + getType() instanceof StructOrUnionTypeWithArrayField and + not isCLValue(this) + } +} + +/** + * 6.2.4.7, A non-lvalue expression with struct or or union type that has a field member of array + * type, is an object with automatic storage duration (and has temporary lifetime). + */ +class TemporaryObjectIdentity extends ObjectIdentityBase instanceof TemporaryObjectIdentityExpr { + TemporaryObjectIdentity() { + // See comment in `TemporaryObjectIdentityExpr` for why we check `getASubobjectAccess()` here. + not exists(TemporaryObjectIdentityExpr parent | + this = getASubobjectAccessOf(parent) and + not this = parent + ) + } + + override StorageDuration getStorageDuration() { result.isAutomatic() } + + override Type getType() { result = this.(Expr).getType() } + + override Expr getAnAccess() { result = this } + + override predicate hasTemporaryLifetime() { any() } +} diff --git a/c/common/src/codingstandards/c/StorageDuration.qll b/c/common/src/codingstandards/c/StorageDuration.qll new file mode 100644 index 0000000000..4669d467bb --- /dev/null +++ b/c/common/src/codingstandards/c/StorageDuration.qll @@ -0,0 +1,31 @@ +import cpp + +class DeclarationWithStorageDuration extends Declaration { } + +newtype TStorageDuration = + StorageDurationStatic() or + StorageDurationAutomatic() or + StorageDurationThread() or + StorageDurationAllocated() + +class StorageDuration extends TStorageDuration { + predicate isStatic() { this = StorageDurationStatic() } + + predicate isAutomatic() { this = StorageDurationAutomatic() } + + predicate isThread() { this = StorageDurationThread() } + + predicate isAllocated() { this = StorageDurationAllocated() } + + string toString() { result = getStorageTypeName() + " storage duration" } + + string getStorageTypeName() { + isStatic() and result = "static" + or + isAutomatic() and result = "automatic" + or + isThread() and result = "thread" + or + isAllocated() and result = "allocated" + } +} diff --git a/c/common/src/codingstandards/c/UninitializedMutex.qll b/c/common/src/codingstandards/c/UninitializedMutex.qll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/c/common/test/library/identifierlinkage/IdentifierLinkage.expected b/c/common/test/library/identifierlinkage/IdentifierLinkage.expected new file mode 100644 index 0000000000..c3f1bc39ef --- /dev/null +++ b/c/common/test/library/identifierlinkage/IdentifierLinkage.expected @@ -0,0 +1,10 @@ +| identifierlinkage.c:2:5:2:10 | g_ext1 | external linkage | +| identifierlinkage.c:3:12:3:17 | g_ext2 | external linkage | +| identifierlinkage.c:6:12:6:17 | g_int1 | internal linkage | +| identifierlinkage.c:9:5:9:10 | g_ext3 | external linkage | +| identifierlinkage.c:12:12:12:17 | g_int2 | internal linkage | +| identifierlinkage.c:15:12:15:12 | p | no linkage | +| identifierlinkage.c:16:7:16:13 | l_none1 | no linkage | +| identifierlinkage.c:17:14:17:20 | l_none2 | no linkage | +| identifierlinkage.c:18:14:18:19 | l_ext1 | external linkage | +| identifierlinkage.c:24:7:24:7 | m | no linkage | diff --git a/c/common/test/library/identifierlinkage/IdentifierLinkage.ql b/c/common/test/library/identifierlinkage/IdentifierLinkage.ql new file mode 100644 index 0000000000..37e5b4cd58 --- /dev/null +++ b/c/common/test/library/identifierlinkage/IdentifierLinkage.ql @@ -0,0 +1,5 @@ +import codingstandards.c.IdentifierLinkage + +from Variable v +where not v.getLocation().toString() = "file://:0:0:0:0" +select v, linkageOfVariable(v) diff --git a/c/common/test/library/identifierlinkage/identifierlinkage.c b/c/common/test/library/identifierlinkage/identifierlinkage.c new file mode 100644 index 0000000000..cf6b439797 --- /dev/null +++ b/c/common/test/library/identifierlinkage/identifierlinkage.c @@ -0,0 +1,30 @@ +// Simple external linkage +int g_ext1; +extern int g_ext2; + +// Simple internal linkage +static int g_int1; + +// Redefined maintaining linkage +int g_ext3; +extern int g_ext3; + +static int g_int2; +extern int g_int2; + +void f(int p) { + int l_none1; + static int l_none2; + extern int l_ext1; +} + +// Structs are not variables +struct s { + // Struct members are variables with no linkage. + int m; +}; + +// Enums and enum constants are not variables and have no linkage. +enum e { + E1 +}; \ No newline at end of file diff --git a/c/common/test/library/objects/ObjectIdentity.expected b/c/common/test/library/objects/ObjectIdentity.expected new file mode 100644 index 0000000000..34be1974f5 --- /dev/null +++ b/c/common/test/library/objects/ObjectIdentity.expected @@ -0,0 +1,21 @@ +| objectidentity.c:3:5:3:14 | g_statstg1 | static storage duration | file://:0:0:0:0 | int | +| objectidentity.c:4:12:4:21 | g_statstg2 | static storage duration | file://:0:0:0:0 | int | +| objectidentity.c:5:12:5:21 | g_statstg3 | static storage duration | file://:0:0:0:0 | int | +| objectidentity.c:8:13:8:22 | p_autostg1 | automatic storage duration | file://:0:0:0:0 | int | +| objectidentity.c:8:31:8:40 | l_autostg2 | automatic storage duration | file://:0:0:0:0 | int | +| objectidentity.c:12:14:12:23 | l_statstg1 | static storage duration | file://:0:0:0:0 | int | +| objectidentity.c:13:14:13:23 | l_statstg2 | static storage duration | file://:0:0:0:0 | int | +| objectidentity.c:17:15:17:24 | g_thrdstg1 | thread storage duration | file://:0:0:0:0 | int | +| objectidentity.c:18:22:18:31 | g_thrdstg2 | thread storage duration | file://:0:0:0:0 | int | +| objectidentity.c:19:22:19:31 | g_thrdstg3 | thread storage duration | file://:0:0:0:0 | int | +| objectidentity.c:21:24:21:33 | l_statstg3 | thread storage duration | file://:0:0:0:0 | int | +| objectidentity.c:22:24:22:33 | l_statstg4 | thread storage duration | file://:0:0:0:0 | int | +| objectidentity.c:35:11:35:20 | g_statstg4 | static storage duration | file://:0:0:0:0 | s * | +| objectidentity.c:35:35:35:37 | {...} | static storage duration | objectidentity.c:27:8:27:8 | s | +| objectidentity.c:35:36:35:36 | 0 | static storage duration | file://:0:0:0:0 | int | +| objectidentity.c:36:7:36:16 | g_statstg5 | static storage duration | file://:0:0:0:0 | char * | +| objectidentity.c:36:20:36:26 | hello | static storage duration | file://:0:0:0:0 | char[6] | +| objectidentity.c:38:3:38:3 | 1 | static storage duration | file://:0:0:0:0 | int | +| objectidentity.c:39:3:39:9 | hello | static storage duration | file://:0:0:0:0 | char[6] | +| objectidentity.c:40:3:40:15 | {...} | automatic storage duration | objectidentity.c:27:8:27:8 | s | +| objectidentity.c:40:14:40:14 | 1 | static storage duration | file://:0:0:0:0 | int | diff --git a/c/common/test/library/objects/ObjectIdentity.ql b/c/common/test/library/objects/ObjectIdentity.ql new file mode 100644 index 0000000000..28e6832bb2 --- /dev/null +++ b/c/common/test/library/objects/ObjectIdentity.ql @@ -0,0 +1,5 @@ +import codingstandards.c.Objects + +from ObjectIdentity obj +where obj.getFile().getBaseName() = "objectidentity.c" +select obj, obj.getStorageDuration(), obj.getType() \ No newline at end of file diff --git a/c/common/test/library/objects/objectidentity.c b/c/common/test/library/objects/objectidentity.c new file mode 100644 index 0000000000..066f68b1fd --- /dev/null +++ b/c/common/test/library/objects/objectidentity.c @@ -0,0 +1,41 @@ +#include "threads.h" +// Basic static storage duration +int g_statstg1; +extern int g_statstg2; +static int g_statstg3; + +// Basic automatic storage duration +void f1(int p_autostg1) { int l_autostg2; } + +// Block identifiers with static storage duration +void f2(void) { + extern int l_statstg1; + static int l_statstg2; +} + +// Thread storage duration +_Thread_local g_thrdstg1; +extern _Thread_local g_thrdstg2; +static _Thread_local g_thrdstg3; +void f3() { + extern _Thread_local l_statstg3; + static _Thread_local l_statstg4; +} + +// Struct declarations do not allocate storage, and do not have a storage +// duration. +struct s { + int m; +}; + +// Enums and enum constants are not variables and have no linkage. +enum e { E1 }; + +// Various literals: +struct s *g_statstg4 = &(struct s){0}; +char *g_statstg5 = "hello"; +void f4(void) { + 1; + "hello"; + (struct s){1}; +} \ No newline at end of file diff --git a/c/misra/src/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.ql b/c/misra/src/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.ql index 5317966f3b..c65890f6bc 100644 --- a/c/misra/src/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.ql +++ b/c/misra/src/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.lifetimes.CLifetimes +import codingstandards.c.Objects /** * Holds if the value of an expression is used or stored. @@ -59,11 +59,11 @@ Expr temporaryObjectFlowStep(Expr e) { } from - TemporaryLifetimeArrayAccess fa, TemporaryLifetimeExpr temporary, + FieldAccess fa, TemporaryObjectIdentity temporary, ArrayToPointerConversion conversion where not isExcluded(conversion, InvalidMemory3Package::arrayToPointerConversionOfTemporaryObjectQuery()) and - fa.getTemporary() = temporary and + fa = temporary.getASubobjectAccess() and conversion.getExpr() = fa and isUsedOrStored(temporaryObjectFlowStep*(conversion.getExpr())) select conversion, "Array to pointer conversion of array $@ from temporary object $@.", diff --git a/c/misra/src/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.ql b/c/misra/src/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.ql index f8a341b9bd..e10b478ee7 100644 --- a/c/misra/src/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.ql +++ b/c/misra/src/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.ql @@ -15,45 +15,31 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.lifetimes.CLifetimes +import codingstandards.c.Objects +import codeql.util.Boolean -class TemporaryLifetimeArrayExpr extends ArrayExpr { - TemporaryLifetimeArrayAccess member; - Type elementType; - - TemporaryLifetimeArrayExpr() { - member = getArrayBase() and - elementType = member.getType().(ArrayType).getBaseType() - or - exists(TemporaryLifetimeArrayExpr inner | - inner = getArrayBase() and - member = inner.getMember() and - elementType = inner.getElementType().(ArrayType).getBaseType() - ) - } - - TemporaryLifetimeArrayAccess getMember() { result = member } - - Type getElementType() { result = elementType } -} - -predicate usedAsModifiableLvalue(Expr expr) { +predicate usedAsModifiableLvalue(Expr expr, Boolean allowArrayAccess) { exists(Assignment parent | parent.getLValue() = expr) or exists(CrementOperation parent | parent.getOperand() = expr) or exists(AddressOfExpr parent | parent.getOperand() = expr) or - exists(FieldAccess parent | parent.getQualifier() = expr and usedAsModifiableLvalue(parent)) + // Don't report `x.y[0].m[0]++` twice. Recurse with `allowArrayAccess` set to false. + exists(FieldAccess parent | parent.getQualifier() = expr and usedAsModifiableLvalue(parent, false)) + or + allowArrayAccess = true and + exists(ArrayExpr parent | parent.getArrayBase() = expr and usedAsModifiableLvalue(parent, true)) } -from TemporaryLifetimeArrayExpr expr, TemporaryLifetimeArrayAccess member +from ArrayExpr expr, FieldAccess fieldAccess, TemporaryObjectIdentity tempObject where not isExcluded(expr, InvalidMemory3Package::modifiableLValueSubscriptedWithTemporaryLifetimeQuery()) and - member = expr.getMember() and + expr = tempObject.getASubobjectAccess() and + fieldAccess = expr.getArrayBase() and not expr.isUnevaluated() and - usedAsModifiableLvalue(expr) + usedAsModifiableLvalue(expr, true) select expr, "Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ ", - member, member.getTarget().getName(), member.getTemporary(), member.getTemporary().toString() + fieldAccess, fieldAccess.getTarget().getName(), tempObject, tempObject.toString() diff --git a/c/misra/src/rules/RULE-22-12/NonstandardUseOfThreadingObject.ql b/c/misra/src/rules/RULE-22-12/NonstandardUseOfThreadingObject.ql new file mode 100644 index 0000000000..d92b4ccea6 --- /dev/null +++ b/c/misra/src/rules/RULE-22-12/NonstandardUseOfThreadingObject.ql @@ -0,0 +1,54 @@ +/** + * @id c/misra/nonstandard-use-of-threading-object + * @name RULE-22-12: Standard library threading objects (mutexes, threads, etc.) shall only be accessed by the appropriate Standard Library functions + * @description Thread objects, thread synchronization objects, and thread-specific storage pointers + * shall only be accessed by the appropriate Standard Library functions. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-22-12 + * correctness + * concurrency + * external/misra/c/2012/amendment4 + * external/misra/obligation/mandatory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.Concurrency +import codingstandards.cpp.Type + +predicate isThreadingObject(Type t) { t instanceof PossiblySpecified::Type } + +predicate validUseOfStdThreadObject(Expr e) { + e.getParent() instanceof AddressOfExpr + or + exists(Call c | + c.getTarget().hasName(["tss_get", "tss_set", "tss_delete"]) and + e = c.getArgument(0) + ) +} + +predicate isStdThreadObjectPtr(Type t) { isThreadingObject(t.(PointerType).getBaseType()) } + +predicate invalidStdThreadObjectUse(Expr e) { + // Invalid use of mtx_t, etc. + isThreadingObject(e.getType()) and + not validUseOfStdThreadObject(e) + or + // Invalid cast from mtx_t* to void*, etc. + isStdThreadObjectPtr(e.getType()) and + exists(Cast cast | + cast.getExpr() = e and + not isStdThreadObjectPtr(cast.getType()) + ) +} + +from Expr e +where + not isExcluded(e, Concurrency8Package::nonstandardUseOfThreadingObjectQuery()) and + invalidStdThreadObjectUse(e) and + // Deduplicate results: (mtx = mtx) is an expression of mtx type, but don't flag the equality + // check, only flag the two `mtx` references. + not invalidStdThreadObjectUse(e.getAChild+()) +select e, "Invalid usage of standard thread object type '" + e.getType().toString() + "'." diff --git a/c/misra/src/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.ql b/c/misra/src/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.ql new file mode 100644 index 0000000000..066cf3c295 --- /dev/null +++ b/c/misra/src/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.ql @@ -0,0 +1,31 @@ +/** + * @id c/misra/threading-object-with-invalid-storage-duration + * @name RULE-22-13: Threading objects (mutexes, threads, etc). shall have not have automatic or thread storage duration + * @description Thread objects, thread synchronization objects, and thread specific storage pointers + * shall have appropriate storage duration. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-22-13 + * correctness + * concurrency + * external/misra/c/2012/amendment4 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.Objects +import codingstandards.cpp.Concurrency +import codingstandards.cpp.Type + +from ObjectIdentity obj, StorageDuration storageDuration, Type type +where + not isExcluded(obj, Concurrency8Package::threadingObjectWithInvalidStorageDurationQuery()) and + storageDuration = obj.getStorageDuration() and + not storageDuration.isStatic() and + type = obj.getASubObjectType() and + type instanceof PossiblySpecified::Type +select obj, + "Object of type '" + obj.getType().getName() + "' has invalid storage duration type '" + + storageDuration.getStorageTypeName() + "'." diff --git a/c/misra/src/rules/RULE-22-14/MutexInitWithInvalidMutexType.ql b/c/misra/src/rules/RULE-22-14/MutexInitWithInvalidMutexType.ql new file mode 100644 index 0000000000..a122a0bec4 --- /dev/null +++ b/c/misra/src/rules/RULE-22-14/MutexInitWithInvalidMutexType.ql @@ -0,0 +1,36 @@ +/** + * @id c/misra/mutex-init-with-invalid-mutex-type + * @name RULE-22-14: Mutexes shall be initialized with a valid mutex type + * @description Mutexes shall be initialized with a valid mutex type. + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-22-14 + * correctness + * concurrency + * external/misra/c/2012/amendment4 + * external/misra/obligation/mandatory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.Concurrency + +predicate isBaseMutexType(EnumConstantAccess access) { + access.getTarget().hasName(["mtx_plain", "mtx_timed"]) +} + +predicate isValidMutexType(Expr expr) { + isBaseMutexType(expr) + or + exists(BinaryBitwiseOperation binOr | binOr = expr | + isBaseMutexType(binOr.getLeftOperand()) and + binOr.getRightOperand().(EnumConstantAccess).getTarget().hasName("mtx_recursive") + ) +} + +from C11MutexSource init +where + not isExcluded(init, Concurrency8Package::mutexInitWithInvalidMutexTypeQuery()) and + not isValidMutexType(init.getMutexTypeExpr()) +select init, "Mutex initialized with incorrect type expression." diff --git a/c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql b/c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql new file mode 100644 index 0000000000..649c941e66 --- /dev/null +++ b/c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql @@ -0,0 +1,27 @@ +/** + * @id c/misra/mutex-initialized-inside-thread + * @name RULE-22-14: Thread synchronization objects shall be initialized deterministically + * @description Mutex and condition objects initialized inside of threads may result in + * indeterministic state + * @kind problem + * @precision high + * @problem.severity recommendation + * @tags external/misra/id/rule-22-14 + * readability + * maintainability + * concurrency + * external/misra/c/2012/amendment4 + * external/misra/obligation/mandatory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.Concurrency + +from C11MutexSource mutexCreate, ThreadedFunction thread +where + not isExcluded(mutexCreate, Concurrency8Package::mutexInitializedInsideThreadQuery()) and + thread.calls*(mutexCreate.getEnclosingFunction()) +select +mutexCreate, "Mutex initialization reachable from threaded function '$@'.", +thread, thread.getName() diff --git a/c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql b/c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql new file mode 100644 index 0000000000..ed4226c207 --- /dev/null +++ b/c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql @@ -0,0 +1,130 @@ +/** + * @id c/misra/mutex-not-initialized-before-use + * @name RULE-22-14: Thread synchronization objects shall be initialized before being accessed + * @description Mutex and condition objects shall be initialized with the standard library functions + * before using them. + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-22-14 + * correctness + * concurrency + * external/misra/c/2012/amendment4 + * external/misra/obligation/mandatory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.Objects +import codingstandards.cpp.Concurrency +import codingstandards.cpp.Type + +/** A function which is not called or started as a thread */ +class RootFunction extends Function { + RootFunction() { + not exists(Function f | f.calls(this)) and + not this instanceof ThreadedFunction + } +} + +/** A function call which initializes a mutex or a condition */ +class ThreadObjectInitialization extends FunctionCall { + ObjectIdentity owningObject; + + ThreadObjectInitialization() { + this.(C11MutexSource).getMutexExpr() = owningObject.getASubobjectAddressExpr() + or + exists(CConditionOperation condOp | + this = condOp and + condOp.isInit() and + condOp.getConditionExpr() = owningObject.getASubobjectAddressExpr() + ) + } + + ObjectIdentity getOwningObject() { result = owningObject } +} + +/** + * A function argument where that argument is used as a mutex or condition object. + */ +class ThreadObjectUse extends Expr { + ObjectIdentity owningObject; + string typeString; + ThreadObjectUse() { + owningObject.getASubobjectAddressExpr() = this and + ( + exists(CMutexFunctionCall mutexUse | this = mutexUse.getLockExpr()) and + typeString = "Mutex" + or + exists(CConditionOperation condOp | this = condOp.getMutexExpr()) and + typeString = "Mutex" + or + exists(CConditionOperation condOp | + condOp.isUse() and + this = condOp.getConditionExpr() and + typeString = "Condition" + ) + ) + } + + ObjectIdentity getOwningObject() { result = owningObject } + + string getDescription() { + if + getOwningObject().getType() instanceof PossiblySpecified::Type or + getOwningObject().getType() instanceof PossiblySpecified::Type + then result = typeString + else result = typeString + " in object" + } +} + + +predicate requiresInitializedMutexObject( + Function func, ThreadObjectUse mutexUse, ObjectIdentity owningObject +) { + mutexUse.getEnclosingFunction() = func and + owningObject = mutexUse.getOwningObject() and + not exists(ThreadObjectInitialization init | + init.getEnclosingFunction() = func and + init.getOwningObject() = owningObject and + mutexUse.getAPredecessor+() = init + ) + or + exists(FunctionCall call | + func = call.getEnclosingFunction() and + requiresInitializedMutexObject(call.getTarget(), mutexUse, owningObject) and + not exists(ThreadObjectInitialization init | + call.getAPredecessor*() = init and + init.getOwningObject() = owningObject + ) + ) + or + exists(C11ThreadCreateCall call | + func = call.getEnclosingFunction() and + not owningObject.getStorageDuration().isThread() and + requiresInitializedMutexObject(call.getFunction(), mutexUse, owningObject) and + not exists(ThreadObjectInitialization init | + call.getAPredecessor*() = init and + init.getOwningObject() = owningObject + ) + ) +} + +from ThreadObjectUse objUse, ObjectIdentity obj, Function callRoot +where + not isExcluded(objUse, Concurrency8Package::mutexNotInitializedBeforeUseQuery()) and + obj = objUse.getOwningObject() and + requiresInitializedMutexObject(callRoot, objUse, obj) and + ( + if obj.getStorageDuration().isAutomatic() + then obj.getEnclosingElement+() = callRoot + else ( + obj.getStorageDuration().isThread() and callRoot instanceof ThreadedFunction + or + callRoot instanceof RootFunction + ) + ) +select objUse, + objUse.getDescription() + + " '$@' possibly used before initialization, from entry point function '$@'.", obj, + obj.toString(), callRoot, callRoot.getName() diff --git a/c/misra/src/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.ql b/c/misra/src/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.ql new file mode 100644 index 0000000000..c86c9b9d9d --- /dev/null +++ b/c/misra/src/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.ql @@ -0,0 +1,52 @@ +/** + * @id c/misra/mutex-objects-not-always-unlocked + * @name RULE-22-16: All mutex objects locked by a thread shall be explicitly unlocked by the same thread + * @description Mutex not unlocked by thread on all execution paths in current thread after being + * locked. + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-22-16 + * correctness + * concurrency + * external/misra/c/2012/amendment4 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.Concurrency +import codingstandards.cpp.resources.ResourceLeakAnalysis + +module MutexLeakConfig implements ResourceLeakConfigSig { + predicate isAllocate(ControlFlowNode allocPoint, DataFlow::Node node) { + exists(MutexFunctionCall lock | + allocPoint = lock and + lock.isLock() and + node.asDefiningArgument() = lock.getLockExpr() + ) + } + + predicate isFree(ControlFlowNode node, DataFlow::Node resource) { + exists(MutexFunctionCall mfc | + node = mfc and + mfc.isUnlock() and + mfc.getLockExpr() = resource.asExpr() + ) + } +} + +string describeMutex(Expr mutexExpr) { + if mutexExpr instanceof AddressOfExpr + then result = mutexExpr.(AddressOfExpr).getOperand().toString() + else result = mutexExpr.toString() +} + +from MutexFunctionCall lockCall, string mutexDescription +where + not isExcluded(lockCall, Concurrency8Package::mutexObjectsNotAlwaysUnlockedQuery()) and + //lockCall.getLockExpr() = mutexNode.asDefiningArgument() and + exists(ResourceLeak::getALeak(lockCall)) and + mutexDescription = describeMutex(lockCall.getLockExpr()) +select lockCall, + "Mutex '" + mutexDescription + "' is locked here and may not always be subsequently unlocked." diff --git a/c/misra/test/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.expected b/c/misra/test/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.expected index 688dde4650..34bec03490 100644 --- a/c/misra/test/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.expected +++ b/c/misra/test/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.expected @@ -21,10 +21,10 @@ | test.c:65:15:65:32 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:65:15:65:20 | call to get_s1 | call to get_s1 | | test.c:66:16:66:33 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:66:16:66:21 | call to get_s1 | call to get_s1 | | test.c:67:23:67:40 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:67:23:67:28 | call to get_s1 | call to get_s1 | -| test.c:89:3:89:30 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:89:12:89:20 | member_s1 | member_s1 | -| test.c:90:3:90:36 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:90:3:90:26 | access to array | access to array | -| test.c:91:15:91:42 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:91:24:91:32 | member_s1 | member_s1 | -| test.c:92:15:92:48 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:92:15:92:38 | access to array | access to array | +| test.c:89:3:89:30 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:89:3:89:8 | call to get_s2 | call to get_s2 | +| test.c:90:3:90:36 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:90:3:90:8 | call to get_s2 | call to get_s2 | +| test.c:91:15:91:42 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:91:15:91:20 | call to get_s2 | call to get_s2 | +| test.c:92:15:92:48 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:92:15:92:20 | call to get_s2 | call to get_s2 | | test.c:111:15:111:33 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:111:16:111:22 | ... = ... | ... = ... | | test.c:113:15:113:37 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:113:16:113:26 | ... ? ... : ... | ... ? ... : ... | | test.c:114:15:114:31 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:114:16:114:20 | ... , ... | ... , ... | diff --git a/c/misra/test/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.expected b/c/misra/test/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.expected index ae140dcd59..19604e2092 100644 --- a/c/misra/test/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.expected +++ b/c/misra/test/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.expected @@ -3,13 +3,13 @@ | test.c:82:3:82:17 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:82:12:82:14 | arr | arr | test.c:82:3:82:8 | call to get_s1 | call to get_s1 | | test.c:83:3:83:17 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:83:12:83:14 | arr | arr | test.c:83:3:83:8 | call to get_s1 | call to get_s1 | | test.c:84:5:84:19 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:84:14:84:16 | arr | arr | test.c:84:5:84:10 | call to get_s1 | call to get_s1 | -| test.c:93:3:93:27 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:93:22:93:24 | arr | arr | test.c:93:12:93:20 | member_s1 | member_s1 | -| test.c:94:3:94:27 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:94:22:94:24 | arr | arr | test.c:94:3:94:20 | access to array | access to array | +| test.c:93:3:93:27 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:93:22:93:24 | arr | arr | test.c:93:3:93:8 | call to get_s2 | call to get_s2 | +| test.c:94:3:94:27 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:94:22:94:24 | arr | arr | test.c:94:3:94:8 | call to get_s2 | call to get_s2 | | test.c:137:3:137:23 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:137:12:137:20 | arr_union | arr_union | test.c:137:3:137:8 | call to get_s3 | call to get_s3 | | test.c:138:3:138:24 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:138:12:138:21 | arr_struct | arr_struct | test.c:138:3:138:8 | call to get_s3 | call to get_s3 | | test.c:139:3:139:24 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:139:12:139:21 | arr_struct | arr_struct | test.c:139:3:139:8 | call to get_s3 | call to get_s3 | | test.c:140:3:140:24 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:140:12:140:21 | arr_struct | arr_struct | test.c:140:3:140:8 | call to get_s3 | call to get_s3 | | test.c:141:3:141:24 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:141:12:141:21 | arr_struct | arr_struct | test.c:141:3:141:8 | call to get_s3 | call to get_s3 | | test.c:142:4:142:25 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:142:13:142:22 | arr_struct | arr_struct | test.c:142:4:142:9 | call to get_s3 | call to get_s3 | -| test.c:146:3:146:22 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:146:12:146:16 | arr2d | arr2d | test.c:146:3:146:8 | call to get_s3 | call to get_s3 | +| test.c:146:3:146:19 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:146:12:146:16 | arr2d | arr2d | test.c:146:3:146:8 | call to get_s3 | call to get_s3 | | test.c:147:4:147:20 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:147:13:147:17 | arr2d | arr2d | test.c:147:4:147:9 | call to get_s3 | call to get_s3 | diff --git a/c/misra/test/rules/RULE-22-12/NonstandardUseOfThreadingObject.expected b/c/misra/test/rules/RULE-22-12/NonstandardUseOfThreadingObject.expected new file mode 100644 index 0000000000..62a740f960 --- /dev/null +++ b/c/misra/test/rules/RULE-22-12/NonstandardUseOfThreadingObject.expected @@ -0,0 +1,27 @@ +| test.c:37:3:37:7 | mutex | Invalid usage of standard thread object type 'mtx_t'. | +| test.c:37:11:37:21 | * ... | Invalid usage of standard thread object type 'mtx_t'. | +| test.c:38:3:38:8 | thread | Invalid usage of standard thread object type 'thrd_t'. | +| test.c:38:12:38:23 | * ... | Invalid usage of standard thread object type 'thrd_t'. | +| test.c:39:3:39:13 | threadlocal | Invalid usage of standard thread object type 'tss_t'. | +| test.c:39:17:39:27 | * ... | Invalid usage of standard thread object type 'tss_t'. | +| test.c:40:3:40:11 | condition | Invalid usage of standard thread object type 'cnd_t'. | +| test.c:40:15:40:25 | * ... | Invalid usage of standard thread object type 'cnd_t'. | +| test.c:43:10:43:15 | & ... | Invalid usage of standard thread object type 'mtx_t *'. | +| test.c:44:10:44:16 | & ... | Invalid usage of standard thread object type 'thrd_t *'. | +| test.c:45:10:45:21 | & ... | Invalid usage of standard thread object type 'tss_t *'. | +| test.c:46:10:46:19 | & ... | Invalid usage of standard thread object type 'cnd_t *'. | +| test.c:48:3:48:13 | threadlocal | Invalid usage of standard thread object type 'tss_t'. | +| test.c:49:3:49:13 | threadlocal | Invalid usage of standard thread object type 'tss_t'. | +| test.c:50:3:50:13 | threadlocal | Invalid usage of standard thread object type 'tss_t'. | +| test.c:54:3:54:8 | thread | Invalid usage of standard thread object type 'thrd_t'. | +| test.c:54:13:54:18 | thread | Invalid usage of standard thread object type 'thrd_t'. | +| test.c:55:3:55:8 | thread | Invalid usage of standard thread object type 'thrd_t'. | +| test.c:55:13:55:18 | thread | Invalid usage of standard thread object type 'thrd_t'. | +| test.c:56:3:56:13 | threadlocal | Invalid usage of standard thread object type 'tss_t'. | +| test.c:56:18:56:28 | threadlocal | Invalid usage of standard thread object type 'tss_t'. | +| test.c:57:3:57:13 | threadlocal | Invalid usage of standard thread object type 'tss_t'. | +| test.c:57:18:57:28 | threadlocal | Invalid usage of standard thread object type 'tss_t'. | +| test.c:61:14:61:18 | mutex | Invalid usage of standard thread object type 'mtx_t'. | +| test.c:62:15:62:20 | thread | Invalid usage of standard thread object type 'thrd_t'. | +| test.c:63:20:63:30 | threadlocal | Invalid usage of standard thread object type 'tss_t'. | +| test.c:64:18:64:26 | condition | Invalid usage of standard thread object type 'cnd_t'. | diff --git a/c/misra/test/rules/RULE-22-12/NonstandardUseOfThreadingObject.qlref b/c/misra/test/rules/RULE-22-12/NonstandardUseOfThreadingObject.qlref new file mode 100644 index 0000000000..d1d345420d --- /dev/null +++ b/c/misra/test/rules/RULE-22-12/NonstandardUseOfThreadingObject.qlref @@ -0,0 +1 @@ +rules/RULE-22-12/NonstandardUseOfThreadingObject.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-12/test.c b/c/misra/test/rules/RULE-22-12/test.c new file mode 100644 index 0000000000..1c59c43d8c --- /dev/null +++ b/c/misra/test/rules/RULE-22-12/test.c @@ -0,0 +1,65 @@ +#include "string.h" +#include "threads.h" + +mtx_t mutex; +thrd_t thread; +tss_t threadlocal; +cnd_t condition; + +extern void use_mutex(mtx_t *m); +extern void use_thread(thrd_t *t); +extern void use_threadlocal(tss_t *t); +extern void use_condition(cnd_t *c); + +void valid_usages(void) { + mtx_init(&mutex, mtx_plain); // COMPLIANT + mtx_lock(&mutex); // COMPLIANT + mtx_unlock(&mutex); // COMPLIANT + thrd_create(&thread, NULL, NULL); // COMPLIANT + tss_create(&threadlocal, NULL); // COMPLIANT + tss_set(threadlocal, NULL); // COMPLIANT + cnd_init(&condition); // COMPLIANT + cnd_signal(&condition); // COMPLIANT + cnd_wait(&condition, &mutex); // COMPLIANT + + use_mutex(&mutex); // COMPLIANT + use_thread(&thread); // COMPLIANT + use_threadlocal(&threadlocal); // COMPLIANT + use_condition(&condition); // COMPLIANT +} + +extern void copy_mutex(mtx_t m); +extern void copy_thread(thrd_t t); +extern void copy_threadlocal(tss_t t); +extern void copy_condition(cnd_t t); + +void invalid_usages(void) { + mutex = *(mtx_t *)0; // NON-COMPLIANT + thread = *(thrd_t *)0; // NON-COMPLIANT + threadlocal = *(tss_t *)0; // NON-COMPLIANT + condition = *(cnd_t *)0; // NON-COMPLIANT + + int *buf; + memcpy(&mutex, buf, sizeof(mtx_t)); // NON-COMPLIANT + memcpy(&thread, buf, sizeof(thrd_t)); // NON-COMPLIANT + memcpy(&threadlocal, buf, sizeof(tss_t)); // NON-COMPLIANT + memcpy(&condition, buf, sizeof(cnd_t)); // NON-COMPLIANT + + threadlocal++; // NON-COMPLIANT + threadlocal += 1; // NON-COMPLIANT + threadlocal + 1; // NON-COMPLIANT + + // mutex == mutex; // NON-COMPLIANT + // mutex != mutex; // NON-COMPLIANT + thread == thread; // NON-COMPLIANT + thread != thread; // NON-COMPLIANT + threadlocal == threadlocal; // NON-COMPLIANT + threadlocal != threadlocal; // NON-COMPLIANT + // condition == condition; // NON-COMPLIANT + // condition != condition; // NON-COMPLIANT + + copy_mutex(mutex); // COMPLIANT + copy_thread(thread); // COMPLIANT + copy_threadlocal(threadlocal); // COMPLIANT + copy_condition(condition); // COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.expected b/c/misra/test/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.expected new file mode 100644 index 0000000000..0fe033366d --- /dev/null +++ b/c/misra/test/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.expected @@ -0,0 +1,13 @@ +| test.c:14:21:14:22 | g9 | Object of type 'mtx_t' has invalid storage duration type 'thread'. | +| test.c:15:22:15:24 | g10 | Object of type 'thrd_t' has invalid storage duration type 'thread'. | +| test.c:16:21:16:23 | g11 | Object of type 'tss_t' has invalid storage duration type 'thread'. | +| test.c:17:21:17:23 | g12 | Object of type 'cnd_t' has invalid storage duration type 'thread'. | +| test.c:34:9:34:10 | l1 | Object of type 'mtx_t' has invalid storage duration type 'automatic'. | +| test.c:35:10:35:11 | l2 | Object of type 'thrd_t' has invalid storage duration type 'automatic'. | +| test.c:36:9:36:10 | l3 | Object of type 'tss_t' has invalid storage duration type 'automatic'. | +| test.c:37:9:37:10 | l4 | Object of type 'cnd_t' has invalid storage duration type 'automatic'. | +| test.c:44:9:44:10 | l9 | Object of type 'mtx_t[10]' has invalid storage duration type 'automatic'. | +| test.c:46:13:46:15 | l11 | Object of type 'has_mtx_t' has invalid storage duration type 'automatic'. | +| test.c:48:13:48:15 | l13 | Object of type 'has_mtx_t[10]' has invalid storage duration type 'automatic'. | +| test.c:51:9:51:14 | call to malloc | Object of type 'mtx_t' has invalid storage duration type 'allocated'. | +| test.c:52:9:52:14 | call to malloc | Object of type 'mtx_t' has invalid storage duration type 'allocated'. | diff --git a/c/misra/test/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.qlref b/c/misra/test/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.qlref new file mode 100644 index 0000000000..9c054fc623 --- /dev/null +++ b/c/misra/test/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.qlref @@ -0,0 +1 @@ +rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-13/test.c b/c/misra/test/rules/RULE-22-13/test.c new file mode 100644 index 0000000000..0a5a84167d --- /dev/null +++ b/c/misra/test/rules/RULE-22-13/test.c @@ -0,0 +1,53 @@ +#include "stdlib.h" +#include "threads.h" + +mtx_t g1; // COMPLIANT +thrd_t g2; // COMPLIANT +tss_t g3; // COMPLIANT +cnd_t g4; // COMPLIANT + +static mtx_t g5; // COMPLIANT +static thrd_t g6; // COMPLIANT +static tss_t g7; // COMPLIANT +static cnd_t g8; // COMPLIANT + +_Thread_local mtx_t g9; // NON-COMPLIANT +_Thread_local thrd_t g10; // NON-COMPLIANT +_Thread_local tss_t g11; // NON-COMPLIANT +_Thread_local cnd_t g12; // NON-COMPLIANT + +typedef struct { + mtx_t m; +} has_mtx_t; + +typedef struct { + mtx_t *m; +} has_ptr_mtx_t; + +mtx_t g13[10]; // COMPLIANT +mtx_t *g14; // COMPLIANT +has_mtx_t g15; // COMPLIANT +has_ptr_mtx_t g16; // COMPLIANT +has_mtx_t g17[10]; // COMPLIANT + +void f1(void) { + mtx_t l1; // NON-COMPLIANT + thrd_t l2; // NON-COMPLIANT + tss_t l3; // NON-COMPLIANT + cnd_t l4; // NON-COMPLIANT + + static mtx_t l5; // COMPLIANT + static thrd_t l6; // COMPLIANT + static tss_t l7; // COMPLIANT + static cnd_t l8; // COMPLIANT + + mtx_t l9[10]; // NON-COMPLIANT + mtx_t *l10; // COMPLIANT + has_mtx_t l11; // NON-COMPLIANT + has_ptr_mtx_t l12; // COMPLIANT + has_mtx_t l13[10]; // NON-COMPLIANT + + l10 = &g1; // COMPLIANT + l10 = malloc(sizeof(mtx_t)); // NON-COMPLIANT + l10 = malloc(sizeof(mtx_t) * 4); // NON-COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-14/MutexInitWithInvalidMutexType.expected b/c/misra/test/rules/RULE-22-14/MutexInitWithInvalidMutexType.expected new file mode 100644 index 0000000000..1ea39b6b1d --- /dev/null +++ b/c/misra/test/rules/RULE-22-14/MutexInitWithInvalidMutexType.expected @@ -0,0 +1,5 @@ +| test.c:140:3:140:10 | call to mtx_init | Mutex initialized with incorrect type expression. | +| test.c:141:3:141:10 | call to mtx_init | Mutex initialized with incorrect type expression. | +| test.c:142:3:142:10 | call to mtx_init | Mutex initialized with incorrect type expression. | +| test.c:144:3:144:10 | call to mtx_init | Mutex initialized with incorrect type expression. | +| test.c:145:3:145:10 | call to mtx_init | Mutex initialized with incorrect type expression. | diff --git a/c/misra/test/rules/RULE-22-14/MutexInitWithInvalidMutexType.qlref b/c/misra/test/rules/RULE-22-14/MutexInitWithInvalidMutexType.qlref new file mode 100644 index 0000000000..32b57cfd07 --- /dev/null +++ b/c/misra/test/rules/RULE-22-14/MutexInitWithInvalidMutexType.qlref @@ -0,0 +1 @@ +rules/RULE-22-14/MutexInitWithInvalidMutexType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-14/MutexInitializedInsideThread.expected b/c/misra/test/rules/RULE-22-14/MutexInitializedInsideThread.expected new file mode 100644 index 0000000000..360c02f622 --- /dev/null +++ b/c/misra/test/rules/RULE-22-14/MutexInitializedInsideThread.expected @@ -0,0 +1 @@ +| test.c:110:3:110:10 | call to mtx_init | Mutex initialization reachable from threaded function '$@'. | test.c:105:6:105:32 | from_root7_use_thread_local | from_root7_use_thread_local | diff --git a/c/misra/test/rules/RULE-22-14/MutexInitializedInsideThread.qlref b/c/misra/test/rules/RULE-22-14/MutexInitializedInsideThread.qlref new file mode 100644 index 0000000000..83ada06139 --- /dev/null +++ b/c/misra/test/rules/RULE-22-14/MutexInitializedInsideThread.qlref @@ -0,0 +1 @@ +rules/RULE-22-14/MutexInitializedInsideThread.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-14/MutexNotInitializedBeforeUse.expected b/c/misra/test/rules/RULE-22-14/MutexNotInitializedBeforeUse.expected new file mode 100644 index 0000000000..b9560165ce --- /dev/null +++ b/c/misra/test/rules/RULE-22-14/MutexNotInitializedBeforeUse.expected @@ -0,0 +1,14 @@ +| test.c:6:12:6:14 | & ... | Mutex '$@' possibly used before initialization, from entry point function '$@'. | test.c:5:9:5:10 | l1 | l1 | test.c:4:6:4:19 | use_local_mtxs | use_local_mtxs | +| test.c:13:12:13:16 | & ... | Mutex in object '$@' possibly used before initialization, from entry point function '$@'. | test.c:12:5:12:6 | l2 | l2 | test.c:4:6:4:19 | use_local_mtxs | use_local_mtxs | +| test.c:18:12:18:17 | & ... | Mutex in object '$@' possibly used before initialization, from entry point function '$@'. | test.c:17:9:17:10 | l3 | l3 | test.c:4:6:4:19 | use_local_mtxs | use_local_mtxs | +| test.c:23:12:23:13 | l4 | Mutex '$@' possibly used before initialization, from entry point function '$@'. | test.c:22:15:22:20 | call to malloc | call to malloc | test.c:28:6:28:31 | root1_calls_use_local_mtxs | root1_calls_use_local_mtxs | +| test.c:41:12:41:14 | & ... | Mutex '$@' possibly used before initialization, from entry point function '$@'. | test.c:34:7:34:8 | g1 | g1 | test.c:40:6:40:30 | root2_uses_global_mutexes | root2_uses_global_mutexes | +| test.c:42:12:42:17 | & ... | Mutex in object '$@' possibly used before initialization, from entry point function '$@'. | test.c:37:3:37:4 | g2 | g2 | test.c:40:6:40:30 | root2_uses_global_mutexes | root2_uses_global_mutexes | +| test.c:43:12:43:13 | g3 | Mutex '$@' possibly used before initialization, from entry point function '$@'. | test.c:56:8:56:13 | call to malloc | call to malloc | test.c:40:6:40:30 | root2_uses_global_mutexes | root2_uses_global_mutexes | +| test.c:64:12:64:14 | & ... | Mutex '$@' possibly used before initialization, from entry point function '$@'. | test.c:34:7:34:8 | g1 | g1 | test.c:67:6:67:45 | root4_call_thread_without_initialization | root4_call_thread_without_initialization | +| test.c:88:12:88:14 | & ... | Mutex '$@' possibly used before initialization, from entry point function '$@'. | test.c:87:9:87:10 | l1 | l1 | test.c:86:6:86:36 | island1_use_uninitialized_mutex | island1_use_uninitialized_mutex | +| test.c:100:12:100:14 | & ... | Mutex '$@' possibly used before initialization, from entry point function '$@'. | test.c:98:21:98:22 | g5 | g5 | test.c:99:6:99:27 | root6_use_thread_local | root6_use_thread_local | +| test.c:107:12:107:14 | & ... | Mutex '$@' possibly used before initialization, from entry point function '$@'. | test.c:98:21:98:22 | g5 | g5 | test.c:105:6:105:32 | from_root7_use_thread_local | from_root7_use_thread_local | +| test.c:124:12:124:13 | & ... | Condition '$@' possibly used before initialization, from entry point function '$@'. | test.c:122:9:122:9 | c | c | test.c:121:6:121:28 | root8_uninitialized_cnd | root8_uninitialized_cnd | +| test.c:124:16:124:17 | & ... | Mutex '$@' possibly used before initialization, from entry point function '$@'. | test.c:123:9:123:9 | m | m | test.c:121:6:121:28 | root8_uninitialized_cnd | root8_uninitialized_cnd | +| test.c:127:12:127:13 | & ... | Condition '$@' possibly used before initialization, from entry point function '$@'. | test.c:122:9:122:9 | c | c | test.c:121:6:121:28 | root8_uninitialized_cnd | root8_uninitialized_cnd | diff --git a/c/misra/test/rules/RULE-22-14/MutexNotInitializedBeforeUse.qlref b/c/misra/test/rules/RULE-22-14/MutexNotInitializedBeforeUse.qlref new file mode 100644 index 0000000000..2827a9c571 --- /dev/null +++ b/c/misra/test/rules/RULE-22-14/MutexNotInitializedBeforeUse.qlref @@ -0,0 +1 @@ +rules/RULE-22-14/MutexNotInitializedBeforeUse.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-14/test.c b/c/misra/test/rules/RULE-22-14/test.c new file mode 100644 index 0000000000..d8f1770ad8 --- /dev/null +++ b/c/misra/test/rules/RULE-22-14/test.c @@ -0,0 +1,146 @@ +#include "stdlib.h" +#include "threads.h" + +void use_local_mtxs(int x, int y) { + mtx_t l1; + mtx_lock(&l1); // NON-COMPLIANT + mtx_init(&l1, mtx_plain); + mtx_lock(&l1); // COMPLIANT + + struct { + mtx_t m; + } l2; + mtx_lock(&l2.m); // NON-COMPLIANT + mtx_init(&l2.m, mtx_plain); + mtx_lock(&l2.m); // COMPLIANT + + mtx_t l3[10]; + mtx_lock(&l3[y]); // NON-COMPLIANT + mtx_init(&l3[x], mtx_plain); + mtx_lock(&l3[y]); // COMPLIANT + + mtx_t *l4 = malloc(sizeof(mtx_t)); + mtx_lock(l4); // NON-COMPLIANT + mtx_init(l4, mtx_plain); + mtx_lock(l4); // COMPLIANT +} + +void root1_calls_use_local_mtxs() { + // Since a function exists which calls use_local_mtxs(), that function is not + // a root function. The query should still report unused locals in this case. + use_local_mtxs(1, 2); +} + +mtx_t g1; +struct { + mtx_t m1; +} g2; +mtx_t *g3; + +void root2_uses_global_mutexes() { + mtx_lock(&g1); // NON-COMPLIANT + mtx_lock(&g2.m1); // NON-COMPLIANT + mtx_lock(g3); // NON-COMPLIANT +} + +void from_root3_use_global_mutexes() { + mtx_lock(&g1); // COMPLIANT + mtx_lock(&g2.m1); // COMPLIANT + mtx_lock(g3); // COMPLIANT +} + +void root3_initializes_and_uses_global_mutexes() { + // Init global mutex with an allocated storage duration object. The existence + // of this malloc() is not checked by the query, but if its exists, the object + // and its uses should be trackable as a nice bonus. + g3 = malloc(sizeof(mtx_t)); + mtx_init(&g1, mtx_plain); + mtx_init(&g2.m1, mtx_plain); + mtx_init(g3, mtx_plain); + from_root3_use_global_mutexes(); +} + +void from_root4_use_global_mutex(void *arg) { + mtx_lock(&g1); // NON-COMPLIANT +} + +void root4_call_thread_without_initialization() { + thrd_t t; + thrd_create(&t, &from_root4_use_global_mutex, NULL); +} + +void from_root5_use_global_mutex(void *arg) { + mtx_lock(&g1); // COMPLIANT +} + +void root5_thread_with_initialization() { + mtx_init(&g1, mtx_plain); + thrd_t t; + thrd_create(&t, &from_root5_use_global_mutex, NULL); +} + +// Set up two functions such that a calls b and b calls a. This means there is +// no root function, but we should still report unused locals. +void island2_call_island1(); + +void island1_use_uninitialized_mutex() { + mtx_t l1; + mtx_lock(&l1); // NON-COMPLIANT + + // Globals are hard to detect + mtx_lock(&g1); // NON-COMPLIANT[False negative] + + island2_call_island1(); +} + +void island2_call_island1() { island1_use_uninitialized_mutex(); } + +_Thread_local mtx_t g5; +void root6_use_thread_local() { + mtx_lock(&g5); // NON-COMPLIANT + mtx_init(&g5, mtx_plain); + mtx_lock(&g5); // COMPLIANT +} + +void from_root7_use_thread_local() { + // Invalid, thread local g5 hasn't been initialized in this thread. + mtx_lock(&g5); // NON-COMPLIANT + + // Violates recommendation, mutexes initialized within a thread. + mtx_init(&g5, mtx_plain); // NON-COMPLIANT + + // Valid if we except the above initialization. + mtx_lock(&g5); // COMPLIANT +} + +void root7_spawn_thread_uninitialized_thread_local() { + thrd_t t; + thrd_create(&t, &from_root7_use_thread_local, NULL); +} + +void root8_uninitialized_cnd() { + cnd_t c; + mtx_t m; + cnd_wait(&c, &m); // NON-COMPLIANT + + mtx_init(&m, mtx_plain); + cnd_wait(&c, &m); // NON-COMPLIANT + + cnd_init(&c); + cnd_wait(&c, &m); // COMPLIANT +} + +void invalid_mtx_init_types() { + mtx_t m; + mtx_init(&m, mtx_plain); // COMPLIANT + mtx_init(&m, mtx_plain | mtx_recursive); // COMPLIANT + mtx_init(&m, mtx_timed); // COMPLIANT + mtx_init(&m, mtx_timed | mtx_recursive); // COMPLIANT + + mtx_init(&m, mtx_recursive); // NON-COMPLIANT + mtx_init(&m, mtx_plain | mtx_timed); // NON-COMPLIANT + mtx_init(&m, mtx_plain | mtx_plain); // NON-COMPLIANT + mtx_init(&m, mtx_plain & mtx_recursive); // NON-COMPLIANT + mtx_init(&m, mtx_plain * mtx_recursive); // NON-COMPLIANT + mtx_init(&m, -1); // NON-COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.expected b/c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.expected new file mode 100644 index 0000000000..126e75bca7 --- /dev/null +++ b/c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.expected @@ -0,0 +1,7 @@ +| test.c:16:3:16:10 | call to mtx_lock | Mutex 'm' is locked here and may not always be subsequently unlocked. | +| test.c:21:3:21:10 | call to mtx_lock | Mutex 'm' is locked here and may not always be subsequently unlocked. | +| test.c:39:3:39:10 | call to mtx_lock | Mutex 'm' is locked here and may not always be subsequently unlocked. | +| test.c:55:3:55:10 | call to mtx_lock | Mutex 'm' is locked here and may not always be subsequently unlocked. | +| test.c:72:3:72:10 | call to mtx_lock | Mutex 'g1' is locked here and may not always be subsequently unlocked. | +| test.c:79:3:79:10 | call to mtx_lock | Mutex 'm' is locked here and may not always be subsequently unlocked. | +| test.c:101:5:101:12 | call to mtx_lock | Mutex 'm' is locked here and may not always be subsequently unlocked. | diff --git a/c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.qlref b/c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.qlref new file mode 100644 index 0000000000..a1877f944d --- /dev/null +++ b/c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.qlref @@ -0,0 +1 @@ +rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-16/test.c b/c/misra/test/rules/RULE-22-16/test.c new file mode 100644 index 0000000000..b9a19165e8 --- /dev/null +++ b/c/misra/test/rules/RULE-22-16/test.c @@ -0,0 +1,107 @@ +#include "threads.h" + +void f1() { + mtx_t m; + mtx_lock(&m); // COMPLIANT + mtx_unlock(&m); +} + +void f2() { + mtx_t m; + mtx_unlock(&m); // COMPLIANT +} + +void f3() { + mtx_t m; + mtx_lock(&m); // NON-COMPLIANT +} + +void f4(int p) { + mtx_t m; + mtx_lock(&m); // NON-COMPLIANT + if (p) { + mtx_unlock(&m); + } +} + +void f5(int p) { + mtx_t m; + mtx_lock(&m); // COMPLIANT + if (p) { + mtx_unlock(&m); + } else { + mtx_unlock(&m); + } +} + +void f6(int p) { + mtx_t m; + mtx_lock(&m); // NON-COMPLIANT + if (p) { + goto skipped; + } + mtx_unlock(&m); + skipped: +} + +void f7(int p) { + mtx_t *m; + mtx_lock(m); // COMPLIANT + mtx_unlock(m); +} + +void f8(int p) { + mtx_t *m; + mtx_lock(m); // NON-COMPLIANT +} + +void f9(int p) { + mtx_t m; + mtx_lock(&m); // COMPLIANT + mtx_t *ptr_m = &m; + mtx_unlock(ptr_m); +} + +mtx_t g1; +void f10() { + mtx_lock(&g1); // COMPLIANT + mtx_unlock(&g1); +} + +void f11() { + mtx_lock(&g1); // NON-COMPLIANT +} + +void f12() { + struct { + mtx_t m; + } s; + mtx_lock(&s.m); // NON-COMPLIANT +} + +void f13() { + struct { + mtx_t m; + } s; + mtx_lock(&s.m); // COMPLIANT + mtx_unlock(&s.m); +} + +void f14() { + for(;;) { + mtx_t m; + mtx_lock(&m); // COMPLIANT + mtx_unlock(&m); + } +} + +void f15(int p) { + for(;;) { + mtx_t m; + mtx_lock(&m); // NON-COMPLIANT + if (p) { + break; + } + mtx_unlock(&m); + } +} \ No newline at end of file diff --git a/change_notes/2024-11-27-c-object-refactor.md b/change_notes/2024-11-27-c-object-refactor.md new file mode 100644 index 0000000000..511ce1b7ce --- /dev/null +++ b/change_notes/2024-11-27-c-object-refactor.md @@ -0,0 +1,21 @@ +- `CON34-C` - `AppropriateThreadObjectStorageDurations.ql`: + - Improved analysis for detecting objects with automatic storage duration + - New reports will include `a.x`, `a[x]` for object `a` with automatic storage duration +- `DCL30-C` - `AppropriateStorageDurationsFunctionReturn.ql`: + - Improved analysis for detecting objects with automatic storage duration + - New reports will include `a.x`, `a[x]` for object `a` with automatic storage duration + - False positives related to returning copying pointer values +- `EXP35-C` - `DoNotModifyObjectsWithTemporaryLifetime.ql`: + - Improved analysis for detecting objects with temporary lifetime + - More non-lvalue expressions that produce temporary objects detected, for instance `(x = y).x`, previously only `f().x` discovered +- `MEM33-C` - `AllocStructsWithAFlexibleArrayMemberDynamically.ql`: + - Improved analysis for detecting objects with automatic storage duration + - New reports will include struct literals with a flexible array member +- `RULE-18-9` - `ModifiableLValueSubscriptedWithTemporaryLifetime.ql`: + - Problems will be reported at more obviously non-lvalue locations + - Implementation refactored to be shared with other libraries + - No other changes expected +- `RULE-18-9` - `ArrayToPointerConversionOfTemporaryLifetime.ql`: + - Problems will be reported at more obviously non-lvalue locations + - Implementation refactored to be shared with other libraries + - No other changes expected \ No newline at end of file diff --git a/change_notes/2024-11-27-raii-concurrency-analysis-perf.md b/change_notes/2024-11-27-raii-concurrency-analysis-perf.md new file mode 100644 index 0000000000..3a08427808 --- /dev/null +++ b/change_notes/2024-11-27-raii-concurrency-analysis-perf.md @@ -0,0 +1,2 @@ + - `Concurrency` - for all queries related to RAII-style mutexes + - These types of locks have been refactored to improve performance in some queries. No change in query results expected. \ No newline at end of file diff --git a/change_notes/2024-11-27-resource-leak-analysis-refactor.md b/change_notes/2024-11-27-resource-leak-analysis-refactor.md new file mode 100644 index 0000000000..8f2799b543 --- /dev/null +++ b/change_notes/2024-11-27-resource-leak-analysis-refactor.md @@ -0,0 +1,10 @@ +- `ERR57-CPP` - `DoNotLeakResourcesWhenHandlingExceptions.ql`: + - Resource leak detection code refactored for sharing across queries + - Control flow no longer uses "cut nodes." This could impact performance positively or negatively, however measurements have been taken that indicate no significant change + - Some false positives have been suppressed due to slightly different control flow approach + - Leaked mutex locks and open files are reported at slightly different location, reported at call site (e.g. `f.open(...)`, `m.lock()`) rather than on the variable itself (`f` and `m`). +- `A15-1-4` - `ValidResourcesStateBeforeThrow.ql`: + - Resource leak detection code refactored for sharing across queries + - Control flow no longer uses "cut nodes." This could impact performance positively or negatively, however measurements have been taken that indicate no significant change + - Some false positives have been suppressed due to slightly different control flow approach + - Leaked mutex locks and open files are reported at slightly different location, reported at call site (e.g. `f.open(...)`, `m.lock()`) rather than on the variable itself (`f` and `m`). \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/Clvalues.qll b/cpp/common/src/codingstandards/cpp/Clvalues.qll index 73fcd65eb1..157041f13b 100644 --- a/cpp/common/src/codingstandards/cpp/Clvalues.qll +++ b/cpp/common/src/codingstandards/cpp/Clvalues.qll @@ -14,4 +14,7 @@ predicate isCLValue(Expr expr) { not expr instanceof AssignExpr and not expr instanceof CommaExpr and not exists(Cast c | c = expr.getConversion*()) + or + // 6.5.2.5.4: Compound literals are always lvalues. + expr instanceof AggregateLiteral } diff --git a/cpp/common/src/codingstandards/cpp/Concurrency.qll b/cpp/common/src/codingstandards/cpp/Concurrency.qll index d856fa4515..f68553dfd9 100644 --- a/cpp/common/src/codingstandards/cpp/Concurrency.qll +++ b/cpp/common/src/codingstandards/cpp/Concurrency.qll @@ -69,6 +69,42 @@ class C11ThreadCreateCall extends ThreadCreationFunction { override ControlFlowNode getNext() { result = getFunction().getEntryPoint() } } +class C11MutexType extends TypedefType { + C11MutexType() { + this.hasName("mtx_t") + } +} + +class C11ThreadType extends TypedefType { + C11ThreadType() { + this.hasName("thrd_t") + } +} + +class C11ConditionType extends TypedefType { + C11ConditionType() { + this.hasName("cnd_t") + } +} + +class C11ThreadStorageType extends TypedefType { + C11ThreadStorageType() { + this.hasName("tss_t") + } +} + +class C11ThreadingObjectType extends TypedefType { + C11ThreadingObjectType() { + this instanceof C11MutexType + or + this instanceof C11ThreadType + or + this instanceof C11ConditionType + or + this instanceof C11ThreadStorageType + } +} + /** * Common base class providing an interface into function call * based mutex locks. @@ -317,14 +353,14 @@ abstract class LockingOperation extends FunctionCall { */ class RAIIStyleLock extends LockingOperation { VariableAccess lock; - Element e; RAIIStyleLock() { ( getTarget().getDeclaringType().hasQualifiedName("std", "lock_guard") or getTarget().getDeclaringType().hasQualifiedName("std", "unique_lock") or getTarget().getDeclaringType().hasQualifiedName("std", "scoped_lock") - ) + ) and + lock = getArgument(0).getAChild*() } /** @@ -333,7 +369,6 @@ class RAIIStyleLock extends LockingOperation { override predicate isLock() { not isLockingOperationWithinLockingOperation(this) and this instanceof ConstructorCall and - lock = getArgument(0).getAChild*() and // defer_locks don't cause a lock not exists(Expr exp | exp = getArgument(1) and @@ -463,6 +498,28 @@ class CConditionalWait extends ConditionalWait { CConditionalWait() { getTarget().getName() in ["cnd_wait"] } } +/** + * Models a function which uses a c condition variable. Not integrated into the thread aware CFG. + */ +class CConditionOperation extends FunctionCall { + CConditionOperation() { + getTarget().hasName(["cnd_broadcast", "cnd_signal", "cnd_timedwait", "cnd_wait", "cnd_init"]) + } + + predicate isInit() { + getTarget().hasName("cnd_init") + } + + predicate isUse() { + not isInit() + } + + Expr getConditionExpr() { result = getArgument(0) } + + /* Note: only holds for `cnd_wait()` and `cnd_timedwait()` */ + Expr getMutexExpr() { result = getArgument(1) } +} + /** * Models a call to a `std::thread` constructor that depends on a mutex. */ @@ -531,6 +588,10 @@ class CPPMutexSource extends MutexSource, ConstructorCall { */ class C11MutexSource extends MutexSource, FunctionCall { C11MutexSource() { getTarget().hasName("mtx_init") } + + Expr getMutexExpr() { result = getArgument(0) } + + Expr getMutexTypeExpr() { result = getArgument(1) } } /** diff --git a/cpp/common/src/codingstandards/cpp/Type.qll b/cpp/common/src/codingstandards/cpp/Type.qll index 4199b4a12d..4f72f5612e 100644 --- a/cpp/common/src/codingstandards/cpp/Type.qll +++ b/cpp/common/src/codingstandards/cpp/Type.qll @@ -60,6 +60,30 @@ Type stripSpecifiers(Type type) { else result = type } +signature class PossiblySpecifiedBaseType extends Type; + +/** + * This module defines a class `Type` which holds for types `T` and `const/volatile T` etc. + * + * Similar to `getUnspecifiedType()`, but does not resolve typedefs. Useful for matching + * potentially qualified versions of standard typedef types, such as `const mtx_t`. + * + * Example usage: `someType.(PossiblySpecified::Type).strip()` + */ +module PossiblySpecified { + import cpp as cpp + final class CppType = cpp::Type; + + class Type extends CppType { + BaseType baseType; + Type() { + baseType = stripSpecifiers(this) + } + + BaseType strip() { result = baseType } + } +} + /** * Get the precision of an integral type, where precision is defined as the number of bits * that can be used to represent the numeric value. @@ -69,4 +93,4 @@ int getPrecision(IntegralType type) { type.isExplicitlyUnsigned() and result = type.getSize() * 8 or type.isExplicitlySigned() and result = type.getSize() * 8 - 1 -} +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency8.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency8.qll new file mode 100644 index 0000000000..677b35d12b --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency8.qll @@ -0,0 +1,112 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype Concurrency8Query = + TNonstandardUseOfThreadingObjectQuery() or + TThreadingObjectWithInvalidStorageDurationQuery() or + TMutexNotInitializedBeforeUseQuery() or + TMutexInitializedInsideThreadQuery() or + TMutexInitWithInvalidMutexTypeQuery() or + TMutexObjectsNotAlwaysUnlockedQuery() + +predicate isConcurrency8QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `nonstandardUseOfThreadingObject` query + Concurrency8Package::nonstandardUseOfThreadingObjectQuery() and + queryId = + // `@id` for the `nonstandardUseOfThreadingObject` query + "c/misra/nonstandard-use-of-threading-object" and + ruleId = "RULE-22-12" and + category = "mandatory" + or + query = + // `Query` instance for the `threadingObjectWithInvalidStorageDuration` query + Concurrency8Package::threadingObjectWithInvalidStorageDurationQuery() and + queryId = + // `@id` for the `threadingObjectWithInvalidStorageDuration` query + "c/misra/threading-object-with-invalid-storage-duration" and + ruleId = "RULE-22-13" and + category = "required" + or + query = + // `Query` instance for the `mutexNotInitializedBeforeUse` query + Concurrency8Package::mutexNotInitializedBeforeUseQuery() and + queryId = + // `@id` for the `mutexNotInitializedBeforeUse` query + "c/misra/mutex-not-initialized-before-use" and + ruleId = "RULE-22-14" and + category = "mandatory" + or + query = + // `Query` instance for the `mutexInitializedInsideThread` query + Concurrency8Package::mutexInitializedInsideThreadQuery() and + queryId = + // `@id` for the `mutexInitializedInsideThread` query + "c/misra/mutex-initialized-inside-thread" and + ruleId = "RULE-22-14" and + category = "mandatory" + or + query = + // `Query` instance for the `mutexInitWithInvalidMutexType` query + Concurrency8Package::mutexInitWithInvalidMutexTypeQuery() and + queryId = + // `@id` for the `mutexInitWithInvalidMutexType` query + "c/misra/mutex-init-with-invalid-mutex-type" and + ruleId = "RULE-22-14" and + category = "mandatory" + or + query = + // `Query` instance for the `mutexObjectsNotAlwaysUnlocked` query + Concurrency8Package::mutexObjectsNotAlwaysUnlockedQuery() and + queryId = + // `@id` for the `mutexObjectsNotAlwaysUnlocked` query + "c/misra/mutex-objects-not-always-unlocked" and + ruleId = "RULE-22-16" and + category = "required" +} + +module Concurrency8Package { + Query nonstandardUseOfThreadingObjectQuery() { + //autogenerate `Query` type + result = + // `Query` type for `nonstandardUseOfThreadingObject` query + TQueryC(TConcurrency8PackageQuery(TNonstandardUseOfThreadingObjectQuery())) + } + + Query threadingObjectWithInvalidStorageDurationQuery() { + //autogenerate `Query` type + result = + // `Query` type for `threadingObjectWithInvalidStorageDuration` query + TQueryC(TConcurrency8PackageQuery(TThreadingObjectWithInvalidStorageDurationQuery())) + } + + Query mutexNotInitializedBeforeUseQuery() { + //autogenerate `Query` type + result = + // `Query` type for `mutexNotInitializedBeforeUse` query + TQueryC(TConcurrency8PackageQuery(TMutexNotInitializedBeforeUseQuery())) + } + + Query mutexInitializedInsideThreadQuery() { + //autogenerate `Query` type + result = + // `Query` type for `mutexInitializedInsideThread` query + TQueryC(TConcurrency8PackageQuery(TMutexInitializedInsideThreadQuery())) + } + + Query mutexInitWithInvalidMutexTypeQuery() { + //autogenerate `Query` type + result = + // `Query` type for `mutexInitWithInvalidMutexType` query + TQueryC(TConcurrency8PackageQuery(TMutexInitWithInvalidMutexTypeQuery())) + } + + Query mutexObjectsNotAlwaysUnlockedQuery() { + //autogenerate `Query` type + result = + // `Query` type for `mutexObjectsNotAlwaysUnlocked` query + TQueryC(TConcurrency8PackageQuery(TMutexObjectsNotAlwaysUnlockedQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index 1562ba7894..f91f80f17a 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -12,6 +12,7 @@ import Concurrency2 import Concurrency3 import Concurrency4 import Concurrency5 +import Concurrency8 import Contracts1 import Contracts2 import Contracts3 @@ -91,6 +92,7 @@ newtype TCQuery = TConcurrency3PackageQuery(Concurrency3Query q) or TConcurrency4PackageQuery(Concurrency4Query q) or TConcurrency5PackageQuery(Concurrency5Query q) or + TConcurrency8PackageQuery(Concurrency8Query q) or TContracts1PackageQuery(Contracts1Query q) or TContracts2PackageQuery(Contracts2Query q) or TContracts3PackageQuery(Contracts3Query q) or @@ -170,6 +172,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isConcurrency3QueryMetadata(query, queryId, ruleId, category) or isConcurrency4QueryMetadata(query, queryId, ruleId, category) or isConcurrency5QueryMetadata(query, queryId, ruleId, category) or + isConcurrency8QueryMetadata(query, queryId, ruleId, category) or isContracts1QueryMetadata(query, queryId, ruleId, category) or isContracts2QueryMetadata(query, queryId, ruleId, category) or isContracts3QueryMetadata(query, queryId, ruleId, category) or diff --git a/cpp/common/src/codingstandards/cpp/lifetimes/CLifetimes.qll b/cpp/common/src/codingstandards/cpp/lifetimes/CLifetimes.qll deleted file mode 100644 index 9282260fb9..0000000000 --- a/cpp/common/src/codingstandards/cpp/lifetimes/CLifetimes.qll +++ /dev/null @@ -1,48 +0,0 @@ -import cpp -import codingstandards.cpp.Clvalues - -/** - * A struct or union type that contains an array type. - */ -class StructOrUnionTypeWithArrayField extends Struct { - StructOrUnionTypeWithArrayField() { - this.getAField().getUnspecifiedType() instanceof ArrayType - or - // nested struct or union containing an array type - this.getAField().getUnspecifiedType().(Struct) instanceof StructOrUnionTypeWithArrayField - } -} - -/** - * A non-lvalue expression with struct or or union type that has a field member - * of array type, has a temporary lifetime. - * - * The array members are also part of that object, and thus also have temporary - * lifetime. - */ -class TemporaryLifetimeExpr extends Expr { - TemporaryLifetimeExpr() { - getUnconverted().getUnspecifiedType() instanceof StructOrUnionTypeWithArrayField and - not isCLValue(this) - or - this.getUnconverted().(ArrayExpr).getArrayBase() instanceof TemporaryLifetimeArrayAccess - } -} - -/** - * A field access on a temporary object that returns an array member. - */ -class TemporaryLifetimeArrayAccess extends FieldAccess { - // The temporary lifetime object which owns the array that is returned. - TemporaryLifetimeExpr temporary; - - TemporaryLifetimeArrayAccess() { - getQualifier().getUnconverted() = temporary and - getUnspecifiedType() instanceof ArrayType - } - - /** - * Get the temporary lifetime object which own the array that is returned. - */ - Expr getTemporary() { result = temporary } -} diff --git a/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll b/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll new file mode 100644 index 0000000000..4623b3e95e --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll @@ -0,0 +1,101 @@ +import cpp +import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.valuenumbering.GlobalValueNumbering +import semmle.code.cpp.controlflow.Dominance +import codeql.util.Boolean + +/** + * A library for detecting leaked resources. + * + * To use this library, implement `ResourceLeakConfigSig`: + * + * ``` + * class UnjoinedThreadConfig implements ResourceLeakConfigSig { + * predicate isResource(DataFlow::Node node) { + * node.asExpr().isThreadCreate() + * } + * + * predicate isFree(ControlFlowNode node, DataFlow::Node resource) { + * node.asExpr().isThreadJoin(resource.asExpr()) + * } + * } + * ``` + * + * You can now check if a resource is leaked through the module predicate + * `ResourceLeak::isLeaked(resource)`. + * + * The leak analysis finds the exit point of the function in which the resource is is declared, and + * then reverses execution from there using `getAPredecessor()`. When this backwards walk discovers + * a control flow node that frees the resource, that exploration stops. If any exploration reaches + * a resource, that resource may be leaked via that path. + * + * Uses `DataFlow::Node` in order to track aliases of the resource to better detect when the + * resource is freed. + * + * This library by default assumes that resources are expression nodes. To use it with other kinds + * of nodes requires overriding `resourceInitPoint`. + */ +signature module ResourceLeakConfigSig { + predicate isAllocate(ControlFlowNode node, DataFlow::Node resource); + + predicate isFree(ControlFlowNode node, DataFlow::Node resource); + + default DataFlow::Node getAnAlias(DataFlow::Node node) { + DataFlow::localFlow(node, result) or + exists(Expr current, Expr after | + current in [node.asExpr(), node.asDefiningArgument()] and + after in [result.asExpr(), result.asDefiningArgument()] and + globalValueNumber(current) = globalValueNumber(after) and + strictlyDominates(current, after) + ) + } + + /* A point at which a resource is considered to have leaked if it has not been freed. */ + default ControlFlowNode outOfScope(ControlFlowNode allocPoint) { + result = allocPoint.(Expr).getEnclosingFunction().getBlock().getLastStmt() + } +} + +module ResourceLeak { + private newtype TResource = TJustResource(DataFlow::Node resource, ControlFlowNode cfgNode) { + Config::isAllocate(cfgNode, resource) + } + + /** + * Get an alias of a resource, and aliases of nodes that are aliased by a resource. + */ + private DataFlow::Node getAnAliasRecursive(DataFlow::Node node) { + result = Config::getAnAlias(node) and + Config::isAllocate(_, node) + or + exists(DataFlow::Node parent | + node = getAnAliasRecursive(parent) and + result = Config::getAnAlias(parent) + ) + } + + private predicate isLeakedAtControlPoint(TResource resource, ControlFlowNode cfgNode) { + // Holds if this control point is where the resource was allocated (and therefore not freed). + resource = TJustResource(_, cfgNode) + or + // Holds if this control point does not free the resource, and is reachable from a point that + // does not free the resource. + isLeakedAtControlPoint(resource, cfgNode.getAPredecessor()) and + not exists(DataFlow::Node freed, DataFlow::Node resourceNode | + Config::isFree(cfgNode, freed) and + freed = getAnAliasRecursive(resourceNode) and + resource = TJustResource(resourceNode, _) + ) + } + + /** + * Holds if `resource` is leaked. Use this module predicate to find leaked resources. + */ + ControlFlowNode getALeak(ControlFlowNode allocPoint) { + exists(TResource resourceWrapper, DataFlow::Node resource | + resourceWrapper = TJustResource(resource, allocPoint) and + result = Config::outOfScope(allocPoint) and + isLeakedAtControlPoint(resourceWrapper, result) + ) + } +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/resources/ResourceManagement.qll b/cpp/common/src/codingstandards/cpp/resources/ResourceManagement.qll index 0798575495..93c26e0a46 100644 --- a/cpp/common/src/codingstandards/cpp/resources/ResourceManagement.qll +++ b/cpp/common/src/codingstandards/cpp/resources/ResourceManagement.qll @@ -1,58 +1,45 @@ import cpp import codingstandards.cpp.dataflow.DataFlow +import codingstandards.cpp.resources.ResourceLeakAnalysis -/** - * The `ResourceAcquisitionExpr` abstract class models resource - * acquisition and release expressions - */ -abstract class ResourceAcquisitionExpr extends Expr { - abstract Expr getReleaseExpr(); -} - -// allocation - deallocation -class AllocExpr extends ResourceAcquisitionExpr { - AllocExpr() { this.(AllocationExpr).requiresDealloc() } - - override Expr getReleaseExpr() { - exists(DeallocationExpr d | result = d.getFreedExpr()) and - DataFlow::localFlow(DataFlow::exprNode(this), DataFlow::exprNode(result)) - } -} - -// file open-close -class FstreamAcquisitionExpr extends ResourceAcquisitionExpr { - FstreamAcquisitionExpr() { +module ResourceLeakConfig implements ResourceLeakConfigSig { + predicate isAllocate(ControlFlowNode allocPoint, DataFlow::Node node) { + exists(AllocationExpr alloc | + allocPoint = alloc and + alloc.requiresDealloc() and + node.asExpr() = alloc + ) + or exists(FunctionCall f | - f.getTarget().hasQualifiedName("std", "basic_fstream", "open") and this = f.getQualifier() + f.getTarget().hasQualifiedName("std", "basic_fstream", "open") + and allocPoint = f + and node.asDefiningArgument() = f.getQualifier() ) - } - - override Expr getReleaseExpr() { + or exists(FunctionCall f | - f.getTarget().hasQualifiedName("std", "basic_fstream", "close") and result = f.getQualifier() - ) and - exists(DataFlow::Node def | - def.asDefiningArgument() = this and - DataFlow::localFlow(def, DataFlow::exprNode(result)) + f.getTarget().hasQualifiedName("std", "mutex", "lock") and + allocPoint = f and + node.asDefiningArgument() = f.getQualifier() ) } -} -// mutex lock unlock -class MutexAcquisitionExpr extends ResourceAcquisitionExpr { - MutexAcquisitionExpr() { + predicate isFree(ControlFlowNode node, DataFlow::Node resource) { + exists(DeallocationExpr d, Expr freedExpr| + freedExpr = d.getFreedExpr() and + node = d and + resource.asExpr() = freedExpr + ) + or exists(FunctionCall f | - f.getTarget().hasQualifiedName("std", "mutex", "lock") and this = f.getQualifier() + f.getTarget().hasQualifiedName("std", "basic_fstream", "close") + and node = f and + resource.asExpr() = f.getQualifier() ) - } - - override Expr getReleaseExpr() { + or exists(FunctionCall f | - f.getTarget().hasQualifiedName("std", "mutex", "unlock") and result = f.getQualifier() - ) and - exists(DataFlow::Node def | - def.asDefiningArgument() = this and - DataFlow::localFlow(def, DataFlow::exprNode(result)) + f.getTarget().hasQualifiedName("std", "mutex", "unlock") + and node = f and + resource.asExpr() = f.getQualifier() ) } -} +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/rules/exceptionsafetyvalidstate/ExceptionSafetyValidState.qll b/cpp/common/src/codingstandards/cpp/rules/exceptionsafetyvalidstate/ExceptionSafetyValidState.qll index 16f86f78be..8ed5342def 100644 --- a/cpp/common/src/codingstandards/cpp/rules/exceptionsafetyvalidstate/ExceptionSafetyValidState.qll +++ b/cpp/common/src/codingstandards/cpp/rules/exceptionsafetyvalidstate/ExceptionSafetyValidState.qll @@ -4,42 +4,17 @@ */ import cpp -import semmle.code.cpp.controlflow.SubBasicBlocks import codingstandards.cpp.Exclusions import codingstandards.cpp.Customizations import codingstandards.cpp.exceptions.ExceptionFlow import codingstandards.cpp.ExceptionSafety import codingstandards.cpp.resources.ResourceManagement +import codingstandards.cpp.resources.ResourceLeakAnalysis abstract class ExceptionSafetyValidStateSharedQuery extends Query { } Query getQuery() { result instanceof ExceptionSafetyValidStateSharedQuery } -/** - * Ensures that `UncaughtThrowExpr` and `Expr` appear at the start of a `SubBasicBlock`. - */ -class SafetyValidStateSubBasicBlock extends SubBasicBlockCutNode { - SafetyValidStateSubBasicBlock() { - this instanceof ResourceAcquisitionExpr or - this = any(ResourceAcquisitionExpr rae).getReleaseExpr() or - this instanceof UncaughtThrowExpr - } -} - -/** - * Execution continues from an allocation expression - * without releasing the resource - */ -SubBasicBlock followsInitialized(ResourceAcquisitionExpr src) { - result = src - or - exists(SubBasicBlock mid | - mid = followsInitialized(src) and - result = mid.getASuccessor() and - //stop recursion on resource release - not result = src.getReleaseExpr() - ) -} /** * `UncaughtThrowExpr` models a `throw` expression that is not handled @@ -48,14 +23,40 @@ class UncaughtThrowExpr extends ThrowExpr { UncaughtThrowExpr() { getASuccessor() = getEnclosingFunction() } } +module ThrowLeakConfig implements ResourceLeakConfigSig { + + predicate isAllocate(ControlFlowNode node, DataFlow::Node resource) { + //exists(ResourceAcquisitionExpr rae | + // node = rae and resource.asExpr() = rae + //) + ResourceLeakConfig::isAllocate(node, resource) + } + + predicate isFree(ControlFlowNode node, DataFlow::Node resource) { + //exists(ResourceAcquisitionExpr rae | + // node = rae.getReleaseExpr() and resource.asExpr() = rae + //) + ResourceLeakConfig::isFree(node, resource) + } + + ControlFlowNode outOfScope(ControlFlowNode allocPoint) { + result.(UncaughtThrowExpr).getEnclosingFunction() = allocPoint.(Expr).getEnclosingFunction() + } + + DataFlow::Node getAnAlias(DataFlow::Node node) { + DataFlow::localFlow(node, result) + } +} + query predicate problems( - UncaughtThrowExpr te, string message, ResourceAcquisitionExpr e, string eDescription + UncaughtThrowExpr te, string message, Element e, string eDescription ) { not isExcluded(te, getQuery()) and - exists(SubBasicBlock sbb | - sbb.getANode() = e and - te = followsInitialized(sbb) - ) and + //exists(SubBasicBlock sbb | + // sbb.getANode() = e and + // te = followsInitialized(sbb) + //) and + te = ResourceLeak::getALeak(e) and message = "The $@ is not released explicitly before throwing an exception." and eDescription = "allocated resource" } diff --git a/cpp/common/test/rules/exceptionsafetyvalidstate/ExceptionSafetyValidState.expected b/cpp/common/test/rules/exceptionsafetyvalidstate/ExceptionSafetyValidState.expected index 18689c333b..b8a8c17435 100644 --- a/cpp/common/test/rules/exceptionsafetyvalidstate/ExceptionSafetyValidState.expected +++ b/cpp/common/test/rules/exceptionsafetyvalidstate/ExceptionSafetyValidState.expected @@ -6,7 +6,7 @@ | test.cpp:103:5:103:9 | re-throw exception | The $@ is not released explicitly before throwing an exception. | test.cpp:99:12:99:21 | new | allocated resource | | test.cpp:125:5:125:37 | throw ... | The $@ is not released explicitly before throwing an exception. | test.cpp:124:9:124:18 | new | allocated resource | | test.cpp:134:5:134:37 | throw ... | The $@ is not released explicitly before throwing an exception. | test.cpp:133:23:133:32 | new | allocated resource | -| test.cpp:142:3:142:35 | throw ... | The $@ is not released explicitly before throwing an exception. | test.cpp:141:3:141:4 | fs | allocated resource | -| test.cpp:154:3:154:35 | throw ... | The $@ is not released explicitly before throwing an exception. | test.cpp:152:3:152:4 | fs | allocated resource | -| test.cpp:160:3:160:35 | throw ... | The $@ is not released explicitly before throwing an exception. | test.cpp:159:3:159:5 | mtx | allocated resource | -| test.cpp:172:3:172:35 | throw ... | The $@ is not released explicitly before throwing an exception. | test.cpp:170:3:170:5 | mtx | allocated resource | +| test.cpp:142:3:142:35 | throw ... | The $@ is not released explicitly before throwing an exception. | test.cpp:141:6:141:9 | call to open | allocated resource | +| test.cpp:154:3:154:35 | throw ... | The $@ is not released explicitly before throwing an exception. | test.cpp:152:6:152:9 | call to open | allocated resource | +| test.cpp:160:3:160:35 | throw ... | The $@ is not released explicitly before throwing an exception. | test.cpp:159:7:159:10 | call to lock | allocated resource | +| test.cpp:172:3:172:35 | throw ... | The $@ is not released explicitly before throwing an exception. | test.cpp:170:7:170:10 | call to lock | allocated resource | diff --git a/rule_packages/c/Concurrency8.json b/rule_packages/c/Concurrency8.json new file mode 100644 index 0000000000..c27563f81e --- /dev/null +++ b/rule_packages/c/Concurrency8.json @@ -0,0 +1,115 @@ +{ + "MISRA-C-2012": { + "RULE-22-12": { + "properties": { + "obligation": "mandatory" + }, + "queries": [ + { + "description": "Thread objects, thread synchronization objects, and thread-specific storage pointers shall only be accessed by the appropriate Standard Library functions.", + "kind": "problem", + "name": "Standard library threading objects (mutexes, threads, etc.) shall only be accessed by the appropriate Standard Library functions", + "precision": "very-high", + "severity": "error", + "short_name": "NonstandardUseOfThreadingObject", + "tags": [ + "correctness", + "concurrency", + "external/misra/c/2012/amendment4" + ] + } + ], + "title": "Thread objects, thread synchronization objects, and thread-specific storage pointers shall only be accessed by the appropriate Standard Library functions" + }, + "RULE-22-13": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Thread objects, thread synchronization objects, and thread specific storage pointers shall have appropriate storage duration.", + "kind": "problem", + "name": "Threading objects (mutexes, threads, etc). shall have not have automatic or thread storage duration", + "precision": "very-high", + "severity": "error", + "short_name": "ThreadingObjectWithInvalidStorageDuration", + "tags": [ + "correctness", + "concurrency", + "external/misra/c/2012/amendment4" + ] + } + ], + "title": "Thread objects, thread synchronization objects, and thread specific storage pointers shall have appropriate storage duration" + }, + "RULE-22-14": { + "properties": { + "obligation": "mandatory" + }, + "queries": [ + { + "description": "Mutex and condition objects shall be initialized with the standard library functions before using them.", + "kind": "problem", + "name": "Thread synchronization objects shall be initialized before being accessed", + "precision": "high", + "severity": "error", + "short_name": "MutexNotInitializedBeforeUse", + "tags": [ + "correctness", + "concurrency", + "external/misra/c/2012/amendment4" + ] + }, + { + "description": "Mutex and condition objects initialized inside of threads may result in indeterministic state", + "kind": "problem", + "name": "Thread synchronization objects shall be initialized deterministically", + "precision": "high", + "severity": "recommendation", + "short_name": "MutexInitializedInsideThread", + "tags": [ + "readability", + "maintainability", + "concurrency", + "external/misra/c/2012/amendment4" + ] + }, + { + "description": "Mutexes shall be initialized with a valid mutex type.", + "kind": "problem", + "name": "Mutexes shall be initialized with a valid mutex type", + "precision": "high", + "severity": "error", + "short_name": "MutexInitWithInvalidMutexType", + "tags": [ + "correctness", + "concurrency", + "external/misra/c/2012/amendment4" + ] + } + ], + "title": "Thread synchronization objects shall be initialized before being accessed" + }, + "RULE-22-16": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Mutex not unlocked by thread on all execution paths in current thread after being locked.", + "kind": "problem", + "name": "All mutex objects locked by a thread shall be explicitly unlocked by the same thread", + "precision": "high", + "severity": "error", + "short_name": "MutexObjectsNotAlwaysUnlocked", + "tags": [ + "correctness", + "concurrency", + "external/misra/c/2012/amendment4" + ] + } + ], + "title": "All mutex objects locked by a thread shall be explicitly unlocked by the same thread" + } + } +} \ No newline at end of file diff --git a/rules.csv b/rules.csv index 475ea1d66c..624de41885 100644 --- a/rules.csv +++ b/rules.csv @@ -803,11 +803,11 @@ c,MISRA-C-2012,RULE-22-8,Yes,Required,,,The value of errno shall be set to zero c,MISRA-C-2012,RULE-22-9,Yes,Required,,,The value of errno shall be tested against zero after calling an errno-setting-function,,Contracts3,Medium, c,MISRA-C-2012,RULE-22-10,Yes,Required,,,The value of errno shall only be tested when the last function to be called was an errno-setting-function,,Contracts3,Medium, c,MISRA-C-2012,RULE-22-11,Yes,Required,,,A thread that was previously either joined or detached shall not be subsequently joined nor detached,CON39-C,Concurrency6,Import, -c,MISRA-C-2012,RULE-22-12,Yes,Mandatory,,,"Thread objects, thread synchronization objects, and thread-specific storage pointers shall only be accessed by the appropriate Standard Library functions",,Concurrency6,Medium, -c,MISRA-C-2012,RULE-22-13,Yes,Required,,,"Thread objects, thread synchronization objects, and thread specific storage pointers shall have appropriate storage duration",EXP54-CPP and CON34-C,Concurrency6,Medium, -c,MISRA-C-2012,RULE-22-14,Yes,Mandatory,,,Thread synchronization objects shall be initialized before being accessed,EXP53-CPP,Concurrency6,Hard, +c,MISRA-C-2012,RULE-22-12,Yes,Mandatory,,,"Thread objects, thread synchronization objects, and thread-specific storage pointers shall only be accessed by the appropriate Standard Library functions",,Concurrency8,Medium, +c,MISRA-C-2012,RULE-22-13,Yes,Required,,,"Thread objects, thread synchronization objects, and thread specific storage pointers shall have appropriate storage duration",EXP54-CPP and CON34-C,Concurrency8,Medium, +c,MISRA-C-2012,RULE-22-14,Yes,Mandatory,,,Thread synchronization objects shall be initialized before being accessed,EXP53-CPP,Concurrency9,Hard, c,MISRA-C-2012,RULE-22-15,Yes,Required,,,Thread synchronization objects and thread-specific storage pointers shall not be destroyed until after all threads accessing them have terminated,,Concurrency6,Hard, -c,MISRA-C-2012,RULE-22-16,Yes,Required,,,All mutex objects locked by a thread shall be explicitly unlocked by the same thread,MEM51-CPP,Concurrency6,Hard, +c,MISRA-C-2012,RULE-22-16,Yes,Required,,,All mutex objects locked by a thread shall be explicitly unlocked by the same thread,MEM51-CPP,Concurrency9,Hard, c,MISRA-C-2012,RULE-22-17,Yes,Required,,,No thread shall unlock a mutex or call cnd_wait() or cnd_timedwait() for a mutex it has not locked before,Rule 22.2,Concurrency6,Medium, c,MISRA-C-2012,RULE-22-18,Yes,Required,,,Non-recursive mutexes shall not be recursively locked,CON56-CPP,Concurrency6,Medium, c,MISRA-C-2012,RULE-22-19,Yes,Required,,,A condition variable shall be associated with at most one mutex object,,Concurrency6,Medium, From 6a1fa993e30b666121ef65d6ed6ea42c51d22ce0 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 28 Nov 2024 05:12:32 -0800 Subject: [PATCH 057/370] Code format & package description fixes --- .../identifierlinkage/identifierlinkage.c | 4 +-- .../MutexInitializedInsideThread.ql | 2 +- c/misra/test/rules/RULE-22-13/test.c | 4 +-- c/misra/test/rules/RULE-22-16/test.c | 12 ++++----- .../src/codingstandards/cpp/Concurrency.qll | 26 +++++-------------- cpp/common/src/codingstandards/cpp/Type.qll | 12 ++++----- .../cpp/resources/ResourceLeakAnalysis.qll | 26 ++++++++++--------- .../cpp/resources/ResourceManagement.qll | 18 ++++++------- .../ExceptionSafetyValidState.qll | 20 ++------------ rule_packages/c/Concurrency8.json | 2 +- 10 files changed, 49 insertions(+), 77 deletions(-) diff --git a/c/common/test/library/identifierlinkage/identifierlinkage.c b/c/common/test/library/identifierlinkage/identifierlinkage.c index cf6b439797..25265aa144 100644 --- a/c/common/test/library/identifierlinkage/identifierlinkage.c +++ b/c/common/test/library/identifierlinkage/identifierlinkage.c @@ -25,6 +25,4 @@ struct s { }; // Enums and enum constants are not variables and have no linkage. -enum e { - E1 -}; \ No newline at end of file +enum e { E1 }; \ No newline at end of file diff --git a/c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql b/c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql index 649c941e66..a3a8f0b382 100644 --- a/c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql +++ b/c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql @@ -2,7 +2,7 @@ * @id c/misra/mutex-initialized-inside-thread * @name RULE-22-14: Thread synchronization objects shall be initialized deterministically * @description Mutex and condition objects initialized inside of threads may result in - * indeterministic state + * indeterministic state. * @kind problem * @precision high * @problem.severity recommendation diff --git a/c/misra/test/rules/RULE-22-13/test.c b/c/misra/test/rules/RULE-22-13/test.c index 0a5a84167d..193f4be471 100644 --- a/c/misra/test/rules/RULE-22-13/test.c +++ b/c/misra/test/rules/RULE-22-13/test.c @@ -47,7 +47,7 @@ void f1(void) { has_ptr_mtx_t l12; // COMPLIANT has_mtx_t l13[10]; // NON-COMPLIANT - l10 = &g1; // COMPLIANT - l10 = malloc(sizeof(mtx_t)); // NON-COMPLIANT + l10 = &g1; // COMPLIANT + l10 = malloc(sizeof(mtx_t)); // NON-COMPLIANT l10 = malloc(sizeof(mtx_t) * 4); // NON-COMPLIANT } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-16/test.c b/c/misra/test/rules/RULE-22-16/test.c index b9a19165e8..00764645a4 100644 --- a/c/misra/test/rules/RULE-22-16/test.c +++ b/c/misra/test/rules/RULE-22-16/test.c @@ -41,7 +41,7 @@ void f6(int p) { goto skipped; } mtx_unlock(&m); - skipped: +skipped: } void f7(int p) { @@ -84,24 +84,24 @@ void f13() { mtx_t m; } s; mtx_lock(&s.m); // COMPLIANT - mtx_unlock(&s.m); + mtx_unlock(&s.m); } void f14() { - for(;;) { + for (;;) { mtx_t m; mtx_lock(&m); // COMPLIANT - mtx_unlock(&m); + mtx_unlock(&m); } } void f15(int p) { - for(;;) { + for (;;) { mtx_t m; mtx_lock(&m); // NON-COMPLIANT if (p) { break; } - mtx_unlock(&m); + mtx_unlock(&m); } } \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/Concurrency.qll b/cpp/common/src/codingstandards/cpp/Concurrency.qll index f68553dfd9..ba4517a284 100644 --- a/cpp/common/src/codingstandards/cpp/Concurrency.qll +++ b/cpp/common/src/codingstandards/cpp/Concurrency.qll @@ -70,27 +70,19 @@ class C11ThreadCreateCall extends ThreadCreationFunction { } class C11MutexType extends TypedefType { - C11MutexType() { - this.hasName("mtx_t") - } + C11MutexType() { this.hasName("mtx_t") } } class C11ThreadType extends TypedefType { - C11ThreadType() { - this.hasName("thrd_t") - } + C11ThreadType() { this.hasName("thrd_t") } } class C11ConditionType extends TypedefType { - C11ConditionType() { - this.hasName("cnd_t") - } + C11ConditionType() { this.hasName("cnd_t") } } class C11ThreadStorageType extends TypedefType { - C11ThreadStorageType() { - this.hasName("tss_t") - } + C11ThreadStorageType() { this.hasName("tss_t") } } class C11ThreadingObjectType extends TypedefType { @@ -100,7 +92,7 @@ class C11ThreadingObjectType extends TypedefType { this instanceof C11ThreadType or this instanceof C11ConditionType - or + or this instanceof C11ThreadStorageType } } @@ -506,13 +498,9 @@ class CConditionOperation extends FunctionCall { getTarget().hasName(["cnd_broadcast", "cnd_signal", "cnd_timedwait", "cnd_wait", "cnd_init"]) } - predicate isInit() { - getTarget().hasName("cnd_init") - } + predicate isInit() { getTarget().hasName("cnd_init") } - predicate isUse() { - not isInit() - } + predicate isUse() { not isInit() } Expr getConditionExpr() { result = getArgument(0) } diff --git a/cpp/common/src/codingstandards/cpp/Type.qll b/cpp/common/src/codingstandards/cpp/Type.qll index 4f72f5612e..42d77b8055 100644 --- a/cpp/common/src/codingstandards/cpp/Type.qll +++ b/cpp/common/src/codingstandards/cpp/Type.qll @@ -64,21 +64,21 @@ signature class PossiblySpecifiedBaseType extends Type; /** * This module defines a class `Type` which holds for types `T` and `const/volatile T` etc. - * + * * Similar to `getUnspecifiedType()`, but does not resolve typedefs. Useful for matching * potentially qualified versions of standard typedef types, such as `const mtx_t`. - * + * * Example usage: `someType.(PossiblySpecified::Type).strip()` */ module PossiblySpecified { import cpp as cpp + final class CppType = cpp::Type; class Type extends CppType { BaseType baseType; - Type() { - baseType = stripSpecifiers(this) - } + + Type() { baseType = stripSpecifiers(this) } BaseType strip() { result = baseType } } @@ -93,4 +93,4 @@ int getPrecision(IntegralType type) { type.isExplicitlyUnsigned() and result = type.getSize() * 8 or type.isExplicitlySigned() and result = type.getSize() * 8 - 1 -} \ No newline at end of file +} diff --git a/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll b/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll index 4623b3e95e..2f932870b3 100644 --- a/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll +++ b/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll @@ -6,32 +6,32 @@ import codeql.util.Boolean /** * A library for detecting leaked resources. - * + * * To use this library, implement `ResourceLeakConfigSig`: - * + * * ``` * class UnjoinedThreadConfig implements ResourceLeakConfigSig { * predicate isResource(DataFlow::Node node) { * node.asExpr().isThreadCreate() * } - * + * * predicate isFree(ControlFlowNode node, DataFlow::Node resource) { * node.asExpr().isThreadJoin(resource.asExpr()) * } * } * ``` - * + * * You can now check if a resource is leaked through the module predicate * `ResourceLeak::isLeaked(resource)`. - * + * * The leak analysis finds the exit point of the function in which the resource is is declared, and * then reverses execution from there using `getAPredecessor()`. When this backwards walk discovers * a control flow node that frees the resource, that exploration stops. If any exploration reaches * a resource, that resource may be leaked via that path. - * + * * Uses `DataFlow::Node` in order to track aliases of the resource to better detect when the * resource is freed. - * + * * This library by default assumes that resources are expression nodes. To use it with other kinds * of nodes requires overriding `resourceInitPoint`. */ @@ -41,7 +41,8 @@ signature module ResourceLeakConfigSig { predicate isFree(ControlFlowNode node, DataFlow::Node resource); default DataFlow::Node getAnAlias(DataFlow::Node node) { - DataFlow::localFlow(node, result) or + DataFlow::localFlow(node, result) + or exists(Expr current, Expr after | current in [node.asExpr(), node.asDefiningArgument()] and after in [result.asExpr(), result.asDefiningArgument()] and @@ -57,9 +58,10 @@ signature module ResourceLeakConfigSig { } module ResourceLeak { - private newtype TResource = TJustResource(DataFlow::Node resource, ControlFlowNode cfgNode) { - Config::isAllocate(cfgNode, resource) - } + private newtype TResource = + TJustResource(DataFlow::Node resource, ControlFlowNode cfgNode) { + Config::isAllocate(cfgNode, resource) + } /** * Get an alias of a resource, and aliases of nodes that are aliased by a resource. @@ -98,4 +100,4 @@ module ResourceLeak { isLeakedAtControlPoint(resourceWrapper, result) ) } -} \ No newline at end of file +} diff --git a/cpp/common/src/codingstandards/cpp/resources/ResourceManagement.qll b/cpp/common/src/codingstandards/cpp/resources/ResourceManagement.qll index 93c26e0a46..58cf6fc8d2 100644 --- a/cpp/common/src/codingstandards/cpp/resources/ResourceManagement.qll +++ b/cpp/common/src/codingstandards/cpp/resources/ResourceManagement.qll @@ -11,9 +11,9 @@ module ResourceLeakConfig implements ResourceLeakConfigSig { ) or exists(FunctionCall f | - f.getTarget().hasQualifiedName("std", "basic_fstream", "open") - and allocPoint = f - and node.asDefiningArgument() = f.getQualifier() + f.getTarget().hasQualifiedName("std", "basic_fstream", "open") and + allocPoint = f and + node.asDefiningArgument() = f.getQualifier() ) or exists(FunctionCall f | @@ -24,22 +24,22 @@ module ResourceLeakConfig implements ResourceLeakConfigSig { } predicate isFree(ControlFlowNode node, DataFlow::Node resource) { - exists(DeallocationExpr d, Expr freedExpr| + exists(DeallocationExpr d, Expr freedExpr | freedExpr = d.getFreedExpr() and node = d and resource.asExpr() = freedExpr ) or exists(FunctionCall f | - f.getTarget().hasQualifiedName("std", "basic_fstream", "close") - and node = f and + f.getTarget().hasQualifiedName("std", "basic_fstream", "close") and + node = f and resource.asExpr() = f.getQualifier() ) or exists(FunctionCall f | - f.getTarget().hasQualifiedName("std", "mutex", "unlock") - and node = f and + f.getTarget().hasQualifiedName("std", "mutex", "unlock") and + node = f and resource.asExpr() = f.getQualifier() ) } -} \ No newline at end of file +} diff --git a/cpp/common/src/codingstandards/cpp/rules/exceptionsafetyvalidstate/ExceptionSafetyValidState.qll b/cpp/common/src/codingstandards/cpp/rules/exceptionsafetyvalidstate/ExceptionSafetyValidState.qll index 8ed5342def..5a712dd522 100644 --- a/cpp/common/src/codingstandards/cpp/rules/exceptionsafetyvalidstate/ExceptionSafetyValidState.qll +++ b/cpp/common/src/codingstandards/cpp/rules/exceptionsafetyvalidstate/ExceptionSafetyValidState.qll @@ -15,7 +15,6 @@ abstract class ExceptionSafetyValidStateSharedQuery extends Query { } Query getQuery() { result instanceof ExceptionSafetyValidStateSharedQuery } - /** * `UncaughtThrowExpr` models a `throw` expression that is not handled */ @@ -24,18 +23,11 @@ class UncaughtThrowExpr extends ThrowExpr { } module ThrowLeakConfig implements ResourceLeakConfigSig { - predicate isAllocate(ControlFlowNode node, DataFlow::Node resource) { - //exists(ResourceAcquisitionExpr rae | - // node = rae and resource.asExpr() = rae - //) ResourceLeakConfig::isAllocate(node, resource) } predicate isFree(ControlFlowNode node, DataFlow::Node resource) { - //exists(ResourceAcquisitionExpr rae | - // node = rae.getReleaseExpr() and resource.asExpr() = rae - //) ResourceLeakConfig::isFree(node, resource) } @@ -43,19 +35,11 @@ module ThrowLeakConfig implements ResourceLeakConfigSig { result.(UncaughtThrowExpr).getEnclosingFunction() = allocPoint.(Expr).getEnclosingFunction() } - DataFlow::Node getAnAlias(DataFlow::Node node) { - DataFlow::localFlow(node, result) - } + DataFlow::Node getAnAlias(DataFlow::Node node) { DataFlow::localFlow(node, result) } } -query predicate problems( - UncaughtThrowExpr te, string message, Element e, string eDescription -) { +query predicate problems(UncaughtThrowExpr te, string message, Element e, string eDescription) { not isExcluded(te, getQuery()) and - //exists(SubBasicBlock sbb | - // sbb.getANode() = e and - // te = followsInitialized(sbb) - //) and te = ResourceLeak::getALeak(e) and message = "The $@ is not released explicitly before throwing an exception." and eDescription = "allocated resource" diff --git a/rule_packages/c/Concurrency8.json b/rule_packages/c/Concurrency8.json index c27563f81e..2dc5d48042 100644 --- a/rule_packages/c/Concurrency8.json +++ b/rule_packages/c/Concurrency8.json @@ -61,7 +61,7 @@ ] }, { - "description": "Mutex and condition objects initialized inside of threads may result in indeterministic state", + "description": "Mutex and condition objects initialized inside of threads may result in indeterministic state.", "kind": "problem", "name": "Thread synchronization objects shall be initialized deterministically", "precision": "high", From f73df15dab20ade19313fc45e0db062ae1026255 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 28 Nov 2024 05:14:49 -0800 Subject: [PATCH 058/370] fix rules.csv package changes --- rules.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules.csv b/rules.csv index 624de41885..e58d5658af 100644 --- a/rules.csv +++ b/rules.csv @@ -805,9 +805,9 @@ c,MISRA-C-2012,RULE-22-10,Yes,Required,,,The value of errno shall only be tested c,MISRA-C-2012,RULE-22-11,Yes,Required,,,A thread that was previously either joined or detached shall not be subsequently joined nor detached,CON39-C,Concurrency6,Import, c,MISRA-C-2012,RULE-22-12,Yes,Mandatory,,,"Thread objects, thread synchronization objects, and thread-specific storage pointers shall only be accessed by the appropriate Standard Library functions",,Concurrency8,Medium, c,MISRA-C-2012,RULE-22-13,Yes,Required,,,"Thread objects, thread synchronization objects, and thread specific storage pointers shall have appropriate storage duration",EXP54-CPP and CON34-C,Concurrency8,Medium, -c,MISRA-C-2012,RULE-22-14,Yes,Mandatory,,,Thread synchronization objects shall be initialized before being accessed,EXP53-CPP,Concurrency9,Hard, +c,MISRA-C-2012,RULE-22-14,Yes,Mandatory,,,Thread synchronization objects shall be initialized before being accessed,EXP53-CPP,Concurrency8,Hard, c,MISRA-C-2012,RULE-22-15,Yes,Required,,,Thread synchronization objects and thread-specific storage pointers shall not be destroyed until after all threads accessing them have terminated,,Concurrency6,Hard, -c,MISRA-C-2012,RULE-22-16,Yes,Required,,,All mutex objects locked by a thread shall be explicitly unlocked by the same thread,MEM51-CPP,Concurrency9,Hard, +c,MISRA-C-2012,RULE-22-16,Yes,Required,,,All mutex objects locked by a thread shall be explicitly unlocked by the same thread,MEM51-CPP,Concurrency8,Hard, c,MISRA-C-2012,RULE-22-17,Yes,Required,,,No thread shall unlock a mutex or call cnd_wait() or cnd_timedwait() for a mutex it has not locked before,Rule 22.2,Concurrency6,Medium, c,MISRA-C-2012,RULE-22-18,Yes,Required,,,Non-recursive mutexes shall not be recursively locked,CON56-CPP,Concurrency6,Medium, c,MISRA-C-2012,RULE-22-19,Yes,Required,,,A condition variable shall be associated with at most one mutex object,,Concurrency6,Medium, From 616935254fd44bb1b3b96158e0169873fafeafc1 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 28 Nov 2024 05:21:53 -0800 Subject: [PATCH 059/370] Query formatting --- .../rules/CON34-C/AppropriateThreadObjectStorageDurations.ql | 3 ++- .../DCL30-C/AppropriateStorageDurationsFunctionReturn.ql | 5 +++-- .../AllocStructsWithAFlexibleArrayMemberDynamically.ql | 5 +++-- c/common/src/codingstandards/c/UninitializedMutex.qll | 0 c/common/test/library/objects/ObjectIdentity.ql | 2 +- .../RULE-18-9/ArrayToPointerConversionOfTemporaryObject.ql | 4 +--- .../ModifiableLValueSubscriptedWithTemporaryLifetime.ql | 4 +++- c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql | 5 ++--- c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql | 2 +- 9 files changed, 16 insertions(+), 14 deletions(-) delete mode 100644 c/common/src/codingstandards/c/UninitializedMutex.qll diff --git a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql index 6d9caacc5c..5a1dd3c461 100644 --- a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql +++ b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql @@ -32,7 +32,8 @@ where ( addrNode = DataFlow::exprNode(any(AddressOfExpr e | e.getOperand() = acc)) or - addrNode = DataFlow::exprNode(acc) and exists(ArrayToPointerConversion c | c.getExpr() = acc) + addrNode = DataFlow::exprNode(acc) and + exists(ArrayToPointerConversion c | c.getExpr() = acc) ) and TaintTracking::localTaint(addrNode, DataFlow::exprNode(arg)) ) diff --git a/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql b/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql index 1e1e19c7c6..02f195e768 100644 --- a/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql +++ b/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql @@ -18,9 +18,10 @@ import codingstandards.cpp.dataflow.DataFlow class Source extends Expr { ObjectIdentity rootObject; + Source() { - rootObject.getStorageDuration().isAutomatic() - and this = rootObject.getASubobjectAddressExpr() + rootObject.getStorageDuration().isAutomatic() and + this = rootObject.getASubobjectAddressExpr() } } diff --git a/c/cert/src/rules/MEM33-C/AllocStructsWithAFlexibleArrayMemberDynamically.ql b/c/cert/src/rules/MEM33-C/AllocStructsWithAFlexibleArrayMemberDynamically.ql index 4e4ccc2171..f4483bd9fe 100644 --- a/c/cert/src/rules/MEM33-C/AllocStructsWithAFlexibleArrayMemberDynamically.ql +++ b/c/cert/src/rules/MEM33-C/AllocStructsWithAFlexibleArrayMemberDynamically.ql @@ -62,14 +62,15 @@ class FlexibleArrayStructDynamicAlloc extends FlexibleArrayAlloc, FunctionCall { */ class FlexibleArrayNonDynamicAlloc extends FlexibleArrayAlloc { ObjectIdentity object; + FlexibleArrayNonDynamicAlloc() { this = object and not object.getStorageDuration().isAllocated() and // Exclude temporaries. Though they should violate this rule, in practice these results are // often spurious and redundant, such as (*x = *x) which creates an unused temporary object. not object.hasTemporaryLifetime() and - object.getType().getUnspecifiedType() instanceof FlexibleArrayStructType - and not exists(Variable v | v.getInitializer().getExpr() = this) + object.getType().getUnspecifiedType() instanceof FlexibleArrayStructType and + not exists(Variable v | v.getInitializer().getExpr() = this) } override Element getReportElement() { result = object } diff --git a/c/common/src/codingstandards/c/UninitializedMutex.qll b/c/common/src/codingstandards/c/UninitializedMutex.qll deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/c/common/test/library/objects/ObjectIdentity.ql b/c/common/test/library/objects/ObjectIdentity.ql index 28e6832bb2..0e92e588ba 100644 --- a/c/common/test/library/objects/ObjectIdentity.ql +++ b/c/common/test/library/objects/ObjectIdentity.ql @@ -2,4 +2,4 @@ import codingstandards.c.Objects from ObjectIdentity obj where obj.getFile().getBaseName() = "objectidentity.c" -select obj, obj.getStorageDuration(), obj.getType() \ No newline at end of file +select obj, obj.getStorageDuration(), obj.getType() diff --git a/c/misra/src/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.ql b/c/misra/src/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.ql index c65890f6bc..da73214859 100644 --- a/c/misra/src/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.ql +++ b/c/misra/src/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.ql @@ -58,9 +58,7 @@ Expr temporaryObjectFlowStep(Expr e) { e = result.(ConditionalExpr).getElse() } -from - FieldAccess fa, TemporaryObjectIdentity temporary, - ArrayToPointerConversion conversion +from FieldAccess fa, TemporaryObjectIdentity temporary, ArrayToPointerConversion conversion where not isExcluded(conversion, InvalidMemory3Package::arrayToPointerConversionOfTemporaryObjectQuery()) and fa = temporary.getASubobjectAccess() and diff --git a/c/misra/src/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.ql b/c/misra/src/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.ql index e10b478ee7..5ccc8316ec 100644 --- a/c/misra/src/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.ql +++ b/c/misra/src/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.ql @@ -26,7 +26,9 @@ predicate usedAsModifiableLvalue(Expr expr, Boolean allowArrayAccess) { exists(AddressOfExpr parent | parent.getOperand() = expr) or // Don't report `x.y[0].m[0]++` twice. Recurse with `allowArrayAccess` set to false. - exists(FieldAccess parent | parent.getQualifier() = expr and usedAsModifiableLvalue(parent, false)) + exists(FieldAccess parent | + parent.getQualifier() = expr and usedAsModifiableLvalue(parent, false) + ) or allowArrayAccess = true and exists(ArrayExpr parent | parent.getArrayBase() = expr and usedAsModifiableLvalue(parent, true)) diff --git a/c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql b/c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql index a3a8f0b382..497fdaf14d 100644 --- a/c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql +++ b/c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql @@ -22,6 +22,5 @@ from C11MutexSource mutexCreate, ThreadedFunction thread where not isExcluded(mutexCreate, Concurrency8Package::mutexInitializedInsideThreadQuery()) and thread.calls*(mutexCreate.getEnclosingFunction()) -select -mutexCreate, "Mutex initialization reachable from threaded function '$@'.", -thread, thread.getName() +select mutexCreate, "Mutex initialization reachable from threaded function '$@'.", thread, + thread.getName() diff --git a/c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql b/c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql index ed4226c207..f02891d5d0 100644 --- a/c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql +++ b/c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql @@ -50,6 +50,7 @@ class ThreadObjectInitialization extends FunctionCall { class ThreadObjectUse extends Expr { ObjectIdentity owningObject; string typeString; + ThreadObjectUse() { owningObject.getASubobjectAddressExpr() = this and ( @@ -78,7 +79,6 @@ class ThreadObjectUse extends Expr { } } - predicate requiresInitializedMutexObject( Function func, ThreadObjectUse mutexUse, ObjectIdentity owningObject ) { From 6ad3660b0245b7c93509ed2389bc8a62ba139de7 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 28 Nov 2024 08:14:31 -0800 Subject: [PATCH 060/370] Fix RAII mutex test --- cpp/common/src/codingstandards/cpp/Concurrency.qll | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/Concurrency.qll b/cpp/common/src/codingstandards/cpp/Concurrency.qll index ba4517a284..8043352c5a 100644 --- a/cpp/common/src/codingstandards/cpp/Concurrency.qll +++ b/cpp/common/src/codingstandards/cpp/Concurrency.qll @@ -352,7 +352,15 @@ class RAIIStyleLock extends LockingOperation { getTarget().getDeclaringType().hasQualifiedName("std", "unique_lock") or getTarget().getDeclaringType().hasQualifiedName("std", "scoped_lock") ) and - lock = getArgument(0).getAChild*() + ( + lock = getArgument(0).getAChild*() + or + this instanceof DestructorCall and + exists(RAIIStyleLock constructor | + constructor = getQualifier().(VariableAccess).getTarget().getInitializer().getExpr() and + lock = constructor.getArgument(0).getAChild*() + ) + ) } /** @@ -361,6 +369,7 @@ class RAIIStyleLock extends LockingOperation { override predicate isLock() { not isLockingOperationWithinLockingOperation(this) and this instanceof ConstructorCall and + lock = getArgument(0).getAChild*() and // defer_locks don't cause a lock not exists(Expr exp | exp = getArgument(1) and From f3a6c3f4e53fbc80870d848da14c7f9b50d2a6c7 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 2 Dec 2024 14:33:04 +0000 Subject: [PATCH 061/370] Deviations: remove no longer required query lgtm-style suppressions are no longer supported by CodeQL and Code Scanning. --- .../deviations/DeviationsSuppression.qhelp | 12 -- .../cpp/deviations/DeviationsSuppression.ql | 120 ------------------ 2 files changed, 132 deletions(-) delete mode 100644 cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.qhelp delete mode 100644 cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql diff --git a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.qhelp b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.qhelp deleted file mode 100644 index 0bf3a3a71b..0000000000 --- a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.qhelp +++ /dev/null @@ -1,12 +0,0 @@ - - - -

This query generates suppression information for rules that have an associated deviation record.

-
- -
  • - MISRA Compliance 2020 document: - Chapter 4.2 (page 12) - Deviations. -
  • -
    -
    \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql deleted file mode 100644 index 9035b7d288..0000000000 --- a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql +++ /dev/null @@ -1,120 +0,0 @@ -/** - * @name Deviation suppression - * @description Generates information about files and locations where certain alerts should be considered suppressed by deviations. - * @kind alert-suppression - * @id cpp/coding-standards/deviation-suppression - */ - -import cpp -import Deviations - -/** Holds if `lineNumber` is an indexed line number in file `f`. */ -private predicate isLineNumber(File f, int lineNumber) { - exists(Location l | l.getFile() = f | - l.getStartLine() = lineNumber - or - l.getEndLine() = lineNumber - ) -} - -/** Gets the last line number in `f`. */ -private int getLastLineNumber(File f) { result = max(int lineNumber | isLineNumber(f, lineNumber)) } - -/** Gets the last column number on the last line of `f`. */ -int getLastColumnNumber(File f) { - result = - max(Location l | - l.getFile() = f and - l.getEndLine() = getLastLineNumber(f) - | - l.getEndColumn() - ) -} - -newtype TDeviationScope = - TDeviationRecordFileScope(DeviationRecord dr, File file) { - exists(string deviationPath | - dr.isDeviated(_, deviationPath) and - file.getRelativePath().prefix(deviationPath.length()) = deviationPath - ) - } or - TDeviationRecordCommentScope(DeviationRecord dr, Comment c) { c = dr.getACodeIdentifierComment() } - -/** A deviation scope. */ -class DeviationScope extends TDeviationScope { - /** Gets the location at which this deviation was defined. */ - abstract Locatable getDeviationDefinitionLocation(); - - /** Gets the Query being deviated. */ - abstract Query getQuery(); - - abstract string toString(); - - abstract predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ); -} - -/** A deviation scope derived from a "path" entry in a `DeviationRecord`. */ -class DeviationRecordFileScope extends DeviationScope, TDeviationRecordFileScope { - private DeviationRecord getDeviationRecord() { this = TDeviationRecordFileScope(result, _) } - - override Locatable getDeviationDefinitionLocation() { result = getDeviationRecord() } - - private File getFile() { this = TDeviationRecordFileScope(_, result) } - - override Query getQuery() { result = getDeviationRecord().getQuery() } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - // In an ideal world, we would produce a URL here that informed the AlertSuppression code that - // the whole file was suppressed. However, experimentation suggestions the alert suppression - // code only works with locations with lines and columns, so we generate a location that covers - // the whole "indexed" file, by finding the location indexed in the database with the latest - // line and column number. - exists(File f | f = getFile() | - f.getLocation().hasLocationInfo(filepath, _, _, _, _) and - startline = 1 and - startcolumn = 1 and - endline = getLastLineNumber(f) and - endcolumn = getLastColumnNumber(f) - ) - } - - override string toString() { - result = "Deviation of " + getDeviationRecord().getQuery() + " for " + getFile() + "." - } -} - -/** - * A deviation scope derived from a comment corresponding to a "code-identifier" entry for a - * `DeviationRecord`. - */ -class DeviationRecordCommentScope extends DeviationScope, TDeviationRecordCommentScope { - private DeviationRecord getDeviationRecord() { this = TDeviationRecordCommentScope(result, _) } - - private Comment getComment() { this = TDeviationRecordCommentScope(_, result) } - - override Locatable getDeviationDefinitionLocation() { result = getDeviationRecord() } - - override Query getQuery() { result = getDeviationRecord().getQuery() } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - getComment().getLocation().hasLocationInfo(filepath, startline, _, endline, endcolumn) and - startcolumn = 1 - } - - override string toString() { - result = - "Deviation of " + getDeviationRecord().getQuery() + " for comment " + getComment() + "." - } -} - -from DeviationScope deviationScope -select deviationScope.getDeviationDefinitionLocation(), // suppression comment - "// lgtm[" + deviationScope.getQuery().getQueryId() + "]", // text of suppression comment (excluding delimiters) - "lgtm[" + deviationScope.getQuery().getQueryId() + "]", // text of suppression annotation - deviationScope // scope of suppression From 7b2a2e0e183931cc12c2138f792ecfb045f74513 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 3 Dec 2024 12:02:37 +0000 Subject: [PATCH 062/370] Add library for more complex code identifier deviations This new library supports deviating on the next line, or on ranges, in addition to deviating on the current line. --- .../deviations/CodeIdentifierDeviation.qll | 242 ++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll new file mode 100644 index 0000000000..e6220711a9 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll @@ -0,0 +1,242 @@ +/** + * A module for identifying comment markers in code that trigger deviations. + * + * Each comment marker consists of a `code-identifier` with some optional annotations. A deviation will be applied to + * some range of lines in the file containing the comment based on the annotation. The supported marker annotation + * formats are: + * - `` - the deviation applies to results on the current line. + * - `DEVIATION()` - same as above. + * - `DEVIATION_NEXT_LINE()` - this deviation applies to results on the next line. + * - `DEVIATION_BEGIN()` - marks the beginning of a range of lines where the deviation applies. + * - `DEVIATION_END()` - marks the end of a range of lines where the deviation applies. + * + * The valid `code-identifier`s are specified in deviation records, which also specify the query whose results are + * suppressed by the deviation. + * + * For begin/end, we maintain a stack of begin markers. When we encounter an end marker, we pop the stack to determine + * the range of that begin/end marker. If the stack is empty, the end marker is considered unmatched and invalid. If + * the stack is non-empty at the end of the file, all the begin markers are considered unmatched and invalid. + * + * Begin/end markers are not valid across include boundaries, as the stack is not maintained across files. + */ + +import cpp +import Deviations + +/** + * Holds if the given comment contains the code identifier. + */ +bindingset[codeIdentifier] +private predicate commentMatches(Comment comment, string codeIdentifier) { + exists(string text | + comment instanceof CppStyleComment and + // strip the beginning slashes + text = comment.getContents().suffix(2).trim() + or + comment instanceof CStyleComment and + // strip both the beginning /* and the end */ the comment + exists(string text0 | + text0 = comment.getContents().suffix(2) and + text = text0.prefix(text0.length() - 2).trim() + ) and + // The /* */ comment must be a single-line comment + not text.matches("%\n%") + | + // Code identifier appears at the start of the comment (modulo whitespace) + text.prefix(codeIdentifier.length()) = codeIdentifier + or + // Code identifier appears at the end of the comment (modulo whitespace) + text.suffix(text.length() - codeIdentifier.length()) = codeIdentifier + ) +} + +/** + * A deviation marker in the code. + */ +abstract class DeviationMarker extends Comment { + DeviationRecord record; + + /** + * Gets the deviation record associated with this deviation marker. + */ + DeviationRecord getRecord() { result = record } +} + +/** + * A deviation marker for a deviation that applies to the current line. + */ +class DeviationEndOfLineMarker extends DeviationMarker { + DeviationEndOfLineMarker() { + commentMatches(this, "DEVIATION(" + record.getCodeIdentifier() + ")") + } +} + +/** + * A deviation marker for a deviation that applies to the next line. + */ +class DeviationNextLineMarker extends DeviationMarker { + DeviationNextLineMarker() { + commentMatches(this, "DEVIATION_NEXT_LINE(" + record.getCodeIdentifier() + ")") + } +} + +/** + * A deviation marker for a deviation that applies to a range of lines + */ +abstract class DeviationRangeMarker extends DeviationMarker { } + +/** + * A deviation marker for a deviation that begins on this line. + */ +class DeviationBegin extends DeviationRangeMarker { + DeviationBegin() { commentMatches(this, "DEVIATION_BEGIN(" + record.getCodeIdentifier() + ")") } +} + +/** + * A deviation marker for a deviation that ends on this line. + */ +class DeviationEnd extends DeviationRangeMarker { + DeviationEnd() { commentMatches(this, "DEVIATION_END(" + record.getCodeIdentifier() + ")") } +} + +private predicate hasDeviationCommentFileOrdering( + DeviationRecord record, DeviationRangeMarker comment, File file, int index +) { + comment = + rank[index](DeviationRangeMarker c | + c.getRecord() = record and + file = c.getFile() + | + c order by c.getLocation().getStartLine(), c.getLocation().getStartColumn() + ) +} + +private predicate mkBeginStack(DeviationRecord record, File file, BeginStack stack, int index) { + // Stack is empty at the start + index = 0 and + stack = TEmptyBeginStack() and + exists(DeviationRangeMarker marker | + marker.getRecord() = record and marker.getLocation().getFile() = file + ) + or + // Next token is begin, so push it to the stack + exists(DeviationBegin begin, BeginStack prev | + record = begin.getRecord() and + hasDeviationCommentFileOrdering(record, begin, file, index) and + mkBeginStack(record, file, prev, index - 1) and + stack = TConsBeginStack(begin, prev) + ) + or + // Next token is end + exists(DeviationEnd end, BeginStack prevStack | + record = end.getRecord() and + hasDeviationCommentFileOrdering(record, end, file, index) and + mkBeginStack(record, file, prevStack, index - 1) + | + // There is, so pop the most recent begin off the stack + prevStack = TConsBeginStack(_, stack) + or + // Error, no begin on the stack, ignore and continue + prevStack = TEmptyBeginStack() and + stack = TEmptyBeginStack() + ) +} + +newtype TBeginStack = + TConsBeginStack(DeviationBegin begin, TBeginStack prev) { + exists(File file, int index | + hasDeviationCommentFileOrdering(begin.getRecord(), begin, file, index) and + mkBeginStack(begin.getRecord(), file, prev, index - 1) + ) + } or + TEmptyBeginStack() + +private class BeginStack extends TBeginStack { + string toString() { + exists(DeviationBegin begin, BeginStack prev | this = TConsBeginStack(begin, prev) | + result = "(" + begin + ", " + prev.toString() + ")" + ) + or + this = TEmptyBeginStack() and + result = "()" + } +} + +private predicate isDeviationRangePaired( + DeviationRecord record, DeviationBegin begin, DeviationEnd end +) { + exists(File file, int index | + record = end.getRecord() and + hasDeviationCommentFileOrdering(record, end, file, index) and + mkBeginStack(record, file, TConsBeginStack(begin, _), index - 1) + ) +} + +newtype TCodeIndentifierDeviation = + TSingleLineDeviation(DeviationRecord record, Comment comment, string filepath, int suppressedLine) { + ( + commentMatches(comment, record.getCodeIdentifier()) or + comment.(DeviationEndOfLineMarker).getRecord() = record + ) and + comment.getLocation().hasLocationInfo(filepath, suppressedLine, _, _, _) + or + comment.(DeviationNextLineMarker).getRecord() = record and + comment.getLocation().hasLocationInfo(filepath, suppressedLine - 1, _, _, _) + } or + TMultiLineDeviation( + DeviationRecord record, DeviationBegin beginComment, DeviationEnd endComment, string filepath, + int suppressedStartLine, int suppressedEndLine + ) { + isDeviationRangePaired(record, beginComment, endComment) and + beginComment.getLocation().hasLocationInfo(filepath, suppressedStartLine, _, _, _) and + endComment.getLocation().hasLocationInfo(filepath, suppressedEndLine, _, _, _) + } + +class CodeIdentifierDeviation extends TCodeIndentifierDeviation { + /** The deviation record associated with the deviation comment. */ + DeviationRecord getDeviationRecord() { + this = TSingleLineDeviation(result, _, _, _) + or + this = TMultiLineDeviation(result, _, _, _, _, _) + } + + /** + * Holds if the given element is matched by this code identifier deviation. + */ + bindingset[e] + pragma[inline_late] + predicate isElementMatching(Element e) { + exists(string filepath, int elementLocationStart | + e.getLocation().hasLocationInfo(filepath, elementLocationStart, _, _, _) + | + exists(int suppressedLine | + this = TSingleLineDeviation(_, _, filepath, suppressedLine) and + suppressedLine = elementLocationStart + ) + or + exists(int suppressedStartLine, int suppressedEndLine | + this = TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine) and + suppressedStartLine < elementLocationStart and + suppressedEndLine > elementLocationStart + ) + ) + } + + string toString() { + exists(string filepath | + exists(int suppressedLine | + this = TSingleLineDeviation(_, _, filepath, suppressedLine) and + result = + "Deviation record " + getDeviationRecord() + " applied to " + filepath + " Line " + + suppressedLine + ) + or + exists(int suppressedStartLine, int suppressedEndLine | + this = TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine) and + result = + "Deviation record " + getDeviationRecord() + " applied to " + filepath + " Line" + + suppressedStartLine + ":" + suppressedEndLine + ) + ) + } +} From f1730722ed98a0c7df7b27b755a43d27beb97302 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 3 Dec 2024 12:04:31 +0000 Subject: [PATCH 063/370] Deviations: Integrate extended code-identifier deviations This ties in the code-identifier deviation support to the deviations and exclusions libraries. --- .../src/codingstandards/cpp/Exclusions.qll | 21 +++++--------- .../cpp/deviations/Deviations.qll | 29 ++----------------- 2 files changed, 11 insertions(+), 39 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/Exclusions.qll b/cpp/common/src/codingstandards/cpp/Exclusions.qll index b718f6535d..e6a477b220 100644 --- a/cpp/common/src/codingstandards/cpp/Exclusions.qll +++ b/cpp/common/src/codingstandards/cpp/Exclusions.qll @@ -35,19 +35,14 @@ predicate isExcluded(Element e, Query query, string reason) { ) and reason = "Query has an associated deviation record for the element's file." or - // The element is on the same line as a suppression comment - exists(Comment c | - c = dr.getACodeIdentifierComment() and - query = dr.getQuery() - | - exists(string filepath, int endLine | - // Comment occurs on the same line as the end line of the element - e.getLocation().hasLocationInfo(filepath, _, _, endLine, _) and - c.getLocation().hasLocationInfo(filepath, endLine, _, _, _) - ) - ) and - reason = - "Query has an associated deviation record with a code identifier that is applied to the element." + // The element is annotated by a code identifier that deviates this rule + exists(CodeIdentifierDeviation deviationInCode | + dr.getQuery() = query and + deviationInCode = dr.getACodeIdentifierDeviation() and + deviationInCode.isElementMatching(e) and + reason = + "Query has an associated deviation record with a code identifier that is applied to the element." + ) ) or // The effective category of the query is 'Disapplied'. diff --git a/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll b/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll index 4dfadd12eb..2388f95a37 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll @@ -8,6 +8,7 @@ import cpp import semmle.code.cpp.XML import codingstandards.cpp.exclusions.RuleMetadata import codingstandards.cpp.Config +import CodeIdentifierDeviation predicate applyDeviationsAtQueryLevel() { not exists(CodingStandardsReportDeviatedAlerts reportDeviatedResults | @@ -219,32 +220,8 @@ class DeviationRecord extends XmlElement { else result = getADeviationPermit().getCodeIdentifier() } - /** Gets a comment which starts or ends with the code identifier comment. */ - Comment getACodeIdentifierComment() { - exists(string text | - ( - result instanceof CppStyleComment and - // strip the beginning slashes - text = result.getContents().suffix(2).trim() - or - result instanceof CStyleComment and - // strip both the beginning /* and the end */ the comment - exists(string text0 | - text0 = result.getContents().suffix(2) and - text = text0.prefix(text0.length() - 2).trim() - ) and - // The /* */ comment must be a single-line comment - not text.matches("%\n%") - ) and - ( - // Code identifier appears at the start of the comment (modulo whitespace) - text.prefix(getCodeIdentifier().length()) = getCodeIdentifier() - or - // Code identifier appears at the end of the comment (modulo whitespace) - text.suffix(text.length() - getCodeIdentifier().length()) = getCodeIdentifier() - ) - ) - } + /** Gets a code identifier deviation in code which starts or ends with the code identifier comment. */ + CodeIdentifierDeviation getACodeIdentifierDeviation() { this = result.getDeviationRecord() } /** Gets the `rule-id` specified for this record, if any. */ private string getRawRuleId() { result = getAChild("rule-id").getTextValue() } From e36828d9236f6c8c1fbfb631dc639aa6724f92cd Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 3 Dec 2024 12:05:28 +0000 Subject: [PATCH 064/370] Deviations: Add test cases for new code-identifier deviations --- .../TypeLongDoubleUsed.expected | 4 +++ .../deviations/deviations_basic_test/main.cpp | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected index 7b78d54892..a4e045edcf 100644 --- a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected +++ b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected @@ -1 +1,5 @@ | main.cpp:13:15:13:16 | d1 | Use of long double type. | +| main.cpp:18:15:18:16 | d4 | Use of long double type. | +| main.cpp:21:15:21:16 | d6 | Use of long double type. | +| main.cpp:30:15:30:17 | d10 | Use of long double type. | +| main.cpp:38:15:38:17 | d14 | Use of long double type. | diff --git a/cpp/common/test/deviations/deviations_basic_test/main.cpp b/cpp/common/test/deviations/deviations_basic_test/main.cpp index 0b302ea1f2..53258f00fd 100644 --- a/cpp/common/test/deviations/deviations_basic_test/main.cpp +++ b/cpp/common/test/deviations/deviations_basic_test/main.cpp @@ -12,5 +12,30 @@ int main(int argc, char **argv) { getX(); // NON_COMPLIANT long double d1; // NON_COMPLIANT (A0-4-2) long double d2; // a-0-4-2-deviation COMPLIANT[DEVIATED] + + long double d3; // DEVIATION(a-0-4-2-deviation) COMPLIANT[DEVIATED] + + long double d4; // NON_COMPLIANT (A0-4-2) + // DEVIATION_NEXT_LINE(a-0-4-2-deviation) + long double d5; // COMPLIANT[DEVIATED] + long double d6; // NON_COMPLIANT (A0-4-2) + + // DEVIATION_BEGIN(a-0-4-2-deviation) + long double d7; // COMPLIANT[DEVIATED] + getX(); // NON_COMPLIANT (A0-1-2) + long double d8; // COMPLIANT[DEVIATED] + getX(); // NON_COMPLIANT (A0-1-2) + long double d9; // COMPLIANT[DEVIATED] + // DEVIATION_END(a-0-4-2-deviation) + long double d10; // NON_COMPLIANT (A0-4-2) + // DEVIATION_BEGIN(a-0-4-2-deviation) + long double d11; // COMPLIANT[DEVIATED] + getX(); // NON_COMPLIANT (A0-1-2) + long double d12; // COMPLIANT[DEVIATED] + getX(); // NON_COMPLIANT (A0-1-2) + long double d13; // COMPLIANT[DEVIATED] + // DEVIATION_END(a-0-4-2-deviation) + long double d14; // NON_COMPLIANT (A0-4-2) + getX(); // NON_COMPLIANT (A0-1-2) return 0; } \ No newline at end of file From e0779350a71ca7cbcafaa483017ff686aba7724e Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 3 Dec 2024 12:06:53 +0000 Subject: [PATCH 065/370] Update user manual for new code identifier deviations --- docs/user_manual.md | 49 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/docs/user_manual.md b/docs/user_manual.md index 4c020dc73b..7ad4dc4208 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -29,7 +29,8 @@ | 0.21.0 | 2024-05-01 | Luke Cartey | Add MISRA C++ 2023 as under development, and clarify MISRA C 2012 coverage. | | 0.22.0 | 2024-10-02 | Luke Cartey | Add MISRA C 2023 as under development, and clarify MISRA C 2012 coverage. | | 0.23.0 | 2024-10-21 | Luke Cartey | Add assembly as a hazard. | -| 0.24.0 | 2024-10-22 | Luke Cartey | Add CodeQL packs as a usable output, update release artifacts list. | +| 0.24.0 | 2024-10-22 | Luke Cartey | Add CodeQL packs as a usable output, update release artifacts list. | +| 0.25.0 | 2024-12-03 | Luke Cartey | Discuss support for new deviation code identifier formats | ## Release information @@ -405,7 +406,7 @@ The example describes three ways of scoping a deviation: 1. The deviation for `A18-1-1` applies to any source file in the same or a child directory of the directory containing the example `coding-standards.yml`. 2. The deviation for `A18-5-1` applies to any source file in the directory `foo/bar` or a child directory of `foo/bar` relative to the directory containing the `coding-standards.yml`. -3. The deviation for `A0-4-2` applies to any source element that has a comment residing on **the same line** containing the identifier specified in `code-identifier`. +3. The deviation for `A0-4-2` applies to any source element that marked by a comment containing the identifier specified in `code-identifier`. The different acceptable formats are discussed in the next section. The activation of the deviation mechanism requires an extra step in the database creation process. This extra step is the invocation of the Python script `path/to/codeql-coding-standards/scripts/configuration/process_coding_standards_config.py` that is part of the coding standards code scanning pack. @@ -420,6 +421,50 @@ The `process_coding_standards_config.py` has a dependency on the package `pyyaml `pip3 install -r path/to/codeql-coding-standards/scripts/configuration/requirements.txt` +##### Deviation code identifiers + +A code identifier specified in a deviation record can be applied to certain results in the code by adding a comment marker consisting of a `code-identifier` with some optional annotations. The supported marker annotation formats are: + + - `` - the deviation applies to results on the current line. + - `DEVIATION()` - the deviation applies to results on the current line. + - `DEVIATION_NEXT_LINE()` - this deviation applies to results on the next line. + - `DEVIATION_BEGIN()` - marks the beginning of a range of lines where the deviation applies. + - `DEVIATION_END()` - marks the end of a range of lines where the deviation applies. + +Here are some examples, using the deviation record with the `a-0-4-2-deviation` code-identifier specified above: +```cpp + long double x1; // NON_COMPLIANT + + long double x2; // a-0-4-2-deviation - COMPLIANT + long double x3; // COMPLIANT - a-0-4-2-deviation + + long double x4; // DEVIATION(a-0-4-2-deviation) - COMPLIANT + long double x5; // COMPLIANT - DEVIATION(a-0-4-2-deviation) + + // DEVIATION_NEXT_LINE(a-0-4-2-deviation) + long double x6; // COMPLIANT + + // DEVIATION_BEGIN(a-0-4-2-deviation) + long double x7; // COMPLIANT + // DEVIATION_END(a-0-4-2-deviation) +``` + +`DEVIATION_END` markers will pair with the closest unmatched `DEVIATION_BEGIN` for the same `code-identifier`. Consider this example: +```cpp +1 | // DEVIATION_BEGIN(a-0-4-2-deviation) +2 | +3 | // DEVIATION_BEGIN(a-0-4-2-deviation) +4 | +5 | // DEVIATION_END(a-0-4-2-deviation) +6 | +7 | // DEVIATION_END(a-0-4-2-deviation) +``` +Here, Line 1 will pair with Line 7, and Line 3 will pair with Line 8. + +A `DEVIATION_END` without a matching `DEVIATION_BEGIN`, or `DEVIATION_BEGIN` without a matching `DEVIATION_END` is invalid and will be ignored. + +`DEVIATION_BEGIN` and `DEVIATION_END` markers only apply within a single file. Markers cannot be paired across files, and deviations do not apply to included files. + ##### Deviation permit The current implementation supports _deviation permits_ as described in the [MISRA Compliance:2020](https://www.misra.org.uk/app/uploads/2021/06/MISRA-Compliance-2020.pdf) section _4.3 Deviation permits_. From 9a1cbf3e1ddd88bbb6c8ca7b6eb61f5a9b9513aa Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 3 Dec 2024 15:02:22 +0000 Subject: [PATCH 066/370] Cvalue widening change note --- change_notes/2024-10-23-cvalue-widening.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 change_notes/2024-10-23-cvalue-widening.md diff --git a/change_notes/2024-10-23-cvalue-widening.md b/change_notes/2024-10-23-cvalue-widening.md new file mode 100644 index 0000000000..1d7a0f876a --- /dev/null +++ b/change_notes/2024-10-23-cvalue-widening.md @@ -0,0 +1,2 @@ + - `M5-0-3`, `M5-0-7`, `M5-0-8`, `M5-0-9` - `CvalueExpressionConvertedToDifferentUnderlyingType.ql`, `ExplicitFloatingIntegralConversionOfACValueExpr.ql`, `ExplicitWideningConversionOfACValueExpr.ql`, `ExplicitSignedness.ql`: + - Reduce false positives from misidentifying an explicitly casted expression used as a function argument or return value as a `cvalue`. From d77250ae1823f43e26875993df50d490525249d9 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Wed, 4 Dec 2024 16:40:28 +0000 Subject: [PATCH 067/370] C++: Change an 'extends' to an 'instanceof' to make the query compile even if IRGuard is a final class. --- .../rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.ql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/c/cert/src/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.ql b/c/cert/src/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.ql index ab121a5cc6..0e3bf26124 100644 --- a/c/cert/src/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.ql +++ b/c/cert/src/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.ql @@ -20,17 +20,17 @@ import semmle.code.cpp.controlflow.Guards * A check on `signal` call return value * `if (signal(SIGINT, handler) == SIG_ERR)` */ -class SignalCheckOperation extends EqualityOperation, GuardCondition { +class SignalCheckOperation extends EqualityOperation instanceof GuardCondition { BasicBlock errorSuccessor; SignalCheckOperation() { this.getAnOperand() = any(MacroInvocation m | m.getMacroName() = "SIG_ERR").getExpr() and ( this.getOperator() = "==" and - this.controls(errorSuccessor, true) + super.controls(errorSuccessor, true) or this.getOperator() = "!=" and - this.controls(errorSuccessor, false) + super.controls(errorSuccessor, false) ) } From 466f16ec87d17af43abcb67357f7c503a3a2512b Mon Sep 17 00:00:00 2001 From: lcartey <5377966+lcartey@users.noreply.github.com> Date: Wed, 4 Dec 2024 18:01:54 +0000 Subject: [PATCH 068/370] Upgrading `github/codeql` dependency to 2.18.4 --- c/cert/src/codeql-pack.lock.yml | 20 ++++++++++++------- c/cert/src/qlpack.yml | 2 +- c/cert/test/codeql-pack.lock.yml | 20 ++++++++++++------- c/common/src/codeql-pack.lock.yml | 20 ++++++++++++------- c/common/src/qlpack.yml | 2 +- c/common/test/codeql-pack.lock.yml | 20 ++++++++++++------- c/misra/src/codeql-pack.lock.yml | 20 ++++++++++++------- c/misra/src/qlpack.yml | 2 +- c/misra/test/codeql-pack.lock.yml | 20 ++++++++++++------- cpp/autosar/src/codeql-pack.lock.yml | 20 ++++++++++++------- cpp/autosar/src/qlpack.yml | 2 +- cpp/autosar/test/codeql-pack.lock.yml | 20 ++++++++++++------- cpp/cert/src/codeql-pack.lock.yml | 20 ++++++++++++------- cpp/cert/src/qlpack.yml | 2 +- cpp/cert/test/codeql-pack.lock.yml | 20 ++++++++++++------- cpp/common/src/codeql-pack.lock.yml | 20 ++++++++++++------- cpp/common/src/qlpack.yml | 2 +- cpp/common/test/codeql-pack.lock.yml | 20 ++++++++++++------- cpp/misra/src/codeql-pack.lock.yml | 20 ++++++++++++------- cpp/misra/src/qlpack.yml | 2 +- cpp/misra/test/codeql-pack.lock.yml | 20 ++++++++++++------- cpp/report/src/codeql-pack.lock.yml | 20 ++++++++++++------- cpp/report/src/qlpack.yml | 2 +- .../queries/codeql-pack.lock.yml | 20 ++++++++++++------- scripts/generate_modules/queries/qlpack.yml | 2 +- supported_codeql_configs.json | 6 +++--- 26 files changed, 220 insertions(+), 124 deletions(-) diff --git a/c/cert/src/codeql-pack.lock.yml b/c/cert/src/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/c/cert/src/codeql-pack.lock.yml +++ b/c/cert/src/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/c/cert/src/qlpack.yml b/c/cert/src/qlpack.yml index 00a8221f28..f7454d1ff0 100644 --- a/c/cert/src/qlpack.yml +++ b/c/cert/src/qlpack.yml @@ -5,4 +5,4 @@ suites: codeql-suites license: MIT dependencies: codeql/common-c-coding-standards: '*' - codeql/cpp-all: 0.12.9 + codeql/cpp-all: 1.4.2 diff --git a/c/cert/test/codeql-pack.lock.yml b/c/cert/test/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/c/cert/test/codeql-pack.lock.yml +++ b/c/cert/test/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/c/common/src/codeql-pack.lock.yml b/c/common/src/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/c/common/src/codeql-pack.lock.yml +++ b/c/common/src/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/c/common/src/qlpack.yml b/c/common/src/qlpack.yml index 41bf42d337..1930faeeb0 100644 --- a/c/common/src/qlpack.yml +++ b/c/common/src/qlpack.yml @@ -3,4 +3,4 @@ version: 2.39.0-dev license: MIT dependencies: codeql/common-cpp-coding-standards: '*' - codeql/cpp-all: 0.12.9 + codeql/cpp-all: 1.4.2 diff --git a/c/common/test/codeql-pack.lock.yml b/c/common/test/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/c/common/test/codeql-pack.lock.yml +++ b/c/common/test/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/c/misra/src/codeql-pack.lock.yml b/c/misra/src/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/c/misra/src/codeql-pack.lock.yml +++ b/c/misra/src/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/c/misra/src/qlpack.yml b/c/misra/src/qlpack.yml index b160f27b6e..656394ad1d 100644 --- a/c/misra/src/qlpack.yml +++ b/c/misra/src/qlpack.yml @@ -6,4 +6,4 @@ license: MIT default-suite-file: codeql-suites/misra-c-default.qls dependencies: codeql/common-c-coding-standards: '*' - codeql/cpp-all: 0.12.9 + codeql/cpp-all: 1.4.2 diff --git a/c/misra/test/codeql-pack.lock.yml b/c/misra/test/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/c/misra/test/codeql-pack.lock.yml +++ b/c/misra/test/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/cpp/autosar/src/codeql-pack.lock.yml b/cpp/autosar/src/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/cpp/autosar/src/codeql-pack.lock.yml +++ b/cpp/autosar/src/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/cpp/autosar/src/qlpack.yml b/cpp/autosar/src/qlpack.yml index cd37cef87e..e1843eb2e7 100644 --- a/cpp/autosar/src/qlpack.yml +++ b/cpp/autosar/src/qlpack.yml @@ -5,4 +5,4 @@ suites: codeql-suites license: MIT dependencies: codeql/common-cpp-coding-standards: '*' - codeql/cpp-all: 0.12.9 + codeql/cpp-all: 1.4.2 diff --git a/cpp/autosar/test/codeql-pack.lock.yml b/cpp/autosar/test/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/cpp/autosar/test/codeql-pack.lock.yml +++ b/cpp/autosar/test/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/cpp/cert/src/codeql-pack.lock.yml b/cpp/cert/src/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/cpp/cert/src/codeql-pack.lock.yml +++ b/cpp/cert/src/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/cpp/cert/src/qlpack.yml b/cpp/cert/src/qlpack.yml index 464a5172fc..949087dfd5 100644 --- a/cpp/cert/src/qlpack.yml +++ b/cpp/cert/src/qlpack.yml @@ -4,5 +4,5 @@ description: CERT C++ 2016 suites: codeql-suites license: MIT dependencies: - codeql/cpp-all: 0.12.9 + codeql/cpp-all: 1.4.2 codeql/common-cpp-coding-standards: '*' diff --git a/cpp/cert/test/codeql-pack.lock.yml b/cpp/cert/test/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/cpp/cert/test/codeql-pack.lock.yml +++ b/cpp/cert/test/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/cpp/common/src/codeql-pack.lock.yml b/cpp/common/src/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/cpp/common/src/codeql-pack.lock.yml +++ b/cpp/common/src/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/cpp/common/src/qlpack.yml b/cpp/common/src/qlpack.yml index 3912f3531f..1cfc63d8d9 100644 --- a/cpp/common/src/qlpack.yml +++ b/cpp/common/src/qlpack.yml @@ -2,6 +2,6 @@ name: codeql/common-cpp-coding-standards version: 2.39.0-dev license: MIT dependencies: - codeql/cpp-all: 0.12.9 + codeql/cpp-all: 1.4.2 dataExtensions: - ext/*.model.yml diff --git a/cpp/common/test/codeql-pack.lock.yml b/cpp/common/test/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/cpp/common/test/codeql-pack.lock.yml +++ b/cpp/common/test/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/cpp/misra/src/codeql-pack.lock.yml b/cpp/misra/src/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/cpp/misra/src/codeql-pack.lock.yml +++ b/cpp/misra/src/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/cpp/misra/src/qlpack.yml b/cpp/misra/src/qlpack.yml index c27400fc8e..4f94ff4bec 100644 --- a/cpp/misra/src/qlpack.yml +++ b/cpp/misra/src/qlpack.yml @@ -5,4 +5,4 @@ default-suite: codeql-suites/misra-cpp-default.qls license: MIT dependencies: codeql/common-cpp-coding-standards: '*' - codeql/cpp-all: 0.12.9 + codeql/cpp-all: 1.4.2 diff --git a/cpp/misra/test/codeql-pack.lock.yml b/cpp/misra/test/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/cpp/misra/test/codeql-pack.lock.yml +++ b/cpp/misra/test/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/cpp/report/src/codeql-pack.lock.yml b/cpp/report/src/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/cpp/report/src/codeql-pack.lock.yml +++ b/cpp/report/src/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/cpp/report/src/qlpack.yml b/cpp/report/src/qlpack.yml index 6477e52747..73f4cf3276 100644 --- a/cpp/report/src/qlpack.yml +++ b/cpp/report/src/qlpack.yml @@ -2,4 +2,4 @@ name: codeql/report-cpp-coding-standards version: 2.39.0-dev license: MIT dependencies: - codeql/cpp-all: 0.12.9 + codeql/cpp-all: 1.4.2 diff --git a/scripts/generate_modules/queries/codeql-pack.lock.yml b/scripts/generate_modules/queries/codeql-pack.lock.yml index 2cbbccee53..910a6e060e 100644 --- a/scripts/generate_modules/queries/codeql-pack.lock.yml +++ b/scripts/generate_modules/queries/codeql-pack.lock.yml @@ -2,17 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.12.9 + version: 1.4.2 codeql/dataflow: - version: 0.2.3 + version: 1.1.1 + codeql/mad: + version: 1.0.7 codeql/rangeanalysis: - version: 0.0.11 + version: 1.0.7 codeql/ssa: - version: 0.2.12 + version: 1.0.7 codeql/tutorial: - version: 0.2.12 + version: 1.0.7 + codeql/typeflow: + version: 1.0.7 codeql/typetracking: - version: 0.2.12 + version: 1.0.7 codeql/util: - version: 0.2.12 + version: 1.0.7 + codeql/xml: + version: 1.0.7 compiled: false diff --git a/scripts/generate_modules/queries/qlpack.yml b/scripts/generate_modules/queries/qlpack.yml index fea871b973..88a48269e7 100644 --- a/scripts/generate_modules/queries/qlpack.yml +++ b/scripts/generate_modules/queries/qlpack.yml @@ -2,4 +2,4 @@ name: codeql/standard-library-extraction-cpp-coding-standards version: 0.0.0 license: MIT dependencies: - codeql/cpp-all: 0.12.9 + codeql/cpp-all: 1.4.2 diff --git a/supported_codeql_configs.json b/supported_codeql_configs.json index e8b2597100..b143f67fe9 100644 --- a/supported_codeql_configs.json +++ b/supported_codeql_configs.json @@ -1,9 +1,9 @@ { "supported_environment": [ { - "codeql_cli": "2.16.6", - "codeql_standard_library": "codeql-cli/v2.16.6", - "codeql_cli_bundle": "codeql-bundle-v2.16.6" + "codeql_cli": "2.18.4", + "codeql_standard_library": "codeql-cli/v2.18.4", + "codeql_cli_bundle": "codeql-bundle-v2.18.4" } ], "supported_language": [ From 585b864eccb3b836659b41941f1d87c8eaabe374 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Wed, 4 Dec 2024 23:02:33 +0000 Subject: [PATCH 069/370] ValidContainerElementAccess: Address new FPs We had some new false positives because in 2.18.4 string taint is tracked into the qualifier of a string operation, such as insert. This caused us to erroneously identify the container itself as a reference to an element of the container. This has been addressed by excluding uses of the owning container from pointer or reference access. --- cpp/common/src/codingstandards/cpp/Iterators.qll | 4 +++- .../ValidContainerElementAccess.expected | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/Iterators.qll b/cpp/common/src/codingstandards/cpp/Iterators.qll index 8add8598fc..76751aa87b 100644 --- a/cpp/common/src/codingstandards/cpp/Iterators.qll +++ b/cpp/common/src/codingstandards/cpp/Iterators.qll @@ -37,7 +37,9 @@ class ContainerPointerOrReferenceAccess extends ContainerAccess { ) and localTaint(DataFlow::exprNode(fc), DataFlow::exprNode(this)) and (getUnderlyingType() instanceof ReferenceType or getUnderlyingType() instanceof PointerType) and - fc.getQualifier().(VariableAccess).getTarget() = owningContainer + fc.getQualifier().(VariableAccess).getTarget() = owningContainer and + // Exclude cases where we see taint into the owning container + not this = owningContainer.getAnAccess() ) } diff --git a/cpp/common/test/rules/validcontainerelementaccess/ValidContainerElementAccess.expected b/cpp/common/test/rules/validcontainerelementaccess/ValidContainerElementAccess.expected index 1738cbe330..988846beef 100644 --- a/cpp/common/test/rules/validcontainerelementaccess/ValidContainerElementAccess.expected +++ b/cpp/common/test/rules/validcontainerelementaccess/ValidContainerElementAccess.expected @@ -7,6 +7,4 @@ | test.cpp:89:15:89:16 | it | Elements of $@ not accessed with valid reference, pointer, or iterator because of a prior $@. | test.cpp:86:20:86:20 | d | container | test.cpp:92:7:92:12 | call to insert | invalidation | | test.cpp:91:9:91:10 | it | Elements of $@ not accessed with valid reference, pointer, or iterator because of a prior $@. | test.cpp:86:20:86:20 | d | container | test.cpp:92:7:92:12 | call to insert | invalidation | | test.cpp:98:56:98:58 | loc | Elements of $@ not accessed with valid reference, pointer, or iterator because of a prior $@. | test.cpp:96:44:96:46 | str | container | test.cpp:99:9:99:14 | call to insert | invalidation | -| test.cpp:99:5:99:7 | str | Elements of $@ not accessed with valid reference, pointer, or iterator because of a prior $@. | test.cpp:96:44:96:46 | str | container | test.cpp:99:9:99:14 | call to insert | invalidation | | test.cpp:99:16:99:18 | loc | Elements of $@ not accessed with valid reference, pointer, or iterator because of a prior $@. | test.cpp:96:44:96:46 | str | container | test.cpp:99:9:99:14 | call to insert | invalidation | -| test.cpp:106:11:106:13 | str | Elements of $@ not accessed with valid reference, pointer, or iterator because of a prior $@. | test.cpp:103:45:103:47 | str | container | test.cpp:106:15:106:20 | call to insert | invalidation | From 365c090bc85532c53605b43b1f47aa8c7a765ed9 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 5 Dec 2024 10:18:40 +0000 Subject: [PATCH 070/370] Update expected results files after upgrade - Rule 1.5 has an extra data flow node that is harmless. - The other rules had changes to the .ql which affected the location of the deprecated data flow library warnings. --- .../UngetcCallOnStreamPositionZero.expected | 2 ++ ...rrayFunctionArgumentNumberOfElements.expected | 12 ++++++------ ...mpUsedToCompareNullTerminatedStrings.expected | 8 ++++---- ...penForReadAndWriteOnDifferentStreams.expected | 2 +- .../AttemptToWriteToAReadOnlyStream.expected | 12 ++++++------ ...BeComparedWithUnmodifiedReturnValues.expected | 16 ++++++++-------- 6 files changed, 27 insertions(+), 25 deletions(-) diff --git a/c/misra/test/rules/RULE-1-5/UngetcCallOnStreamPositionZero.expected b/c/misra/test/rules/RULE-1-5/UngetcCallOnStreamPositionZero.expected index ff25a58e3c..fb8d44ea19 100644 --- a/c/misra/test/rules/RULE-1-5/UngetcCallOnStreamPositionZero.expected +++ b/c/misra/test/rules/RULE-1-5/UngetcCallOnStreamPositionZero.expected @@ -1,7 +1,9 @@ edges +| test.c:39:16:39:20 | *call to fopen | test.c:39:16:39:20 | *call to fopen | provenance | | | test.c:39:16:39:20 | *call to fopen | test.c:41:15:41:18 | *file | provenance | | nodes | test.c:39:16:39:20 | *call to fopen | semmle.label | *call to fopen | +| test.c:39:16:39:20 | *call to fopen | semmle.label | *call to fopen | | test.c:41:15:41:18 | *file | semmle.label | *file | subpaths #select diff --git a/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected b/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected index cb4422f5f1..174c6aa40f 100644 --- a/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected +++ b/c/misra/test/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.expected @@ -1,9 +1,9 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:47,36-44) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:48,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:50,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:55,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:71,28-36) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:71,51-59) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:48,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:49,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:51,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:56,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:72,28-36) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ArrayFunctionArgumentNumberOfElements.ql:72,51-59) | test.c:18:6:18:6 | 0 | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter | | test.c:19:6:19:7 | ar | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter | | test.c:21:6:21:9 | ar2p | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter | diff --git a/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected b/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected index cf45b21eb4..5ae49919a9 100644 --- a/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected +++ b/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected @@ -1,7 +1,7 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:22,54-62) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:23,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:49,20-28) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:57,43-56) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:23,54-62) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:24,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:50,20-28) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (MemcmpUsedToCompareNullTerminatedStrings.ql:58,43-56) edges | test.c:12:13:12:15 | a | test.c:14:10:14:10 | a | provenance | | | test.c:12:13:12:15 | a | test.c:23:13:23:13 | a | provenance | | diff --git a/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected b/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected index 6360b21973..0365f4980d 100644 --- a/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected +++ b/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected @@ -1,4 +1,4 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (FileOpenForReadAndWriteOnDifferentStreams.ql:38,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (FileOpenForReadAndWriteOnDifferentStreams.ql:39,9-17) | test.c:6:14:6:18 | call to fopen | The same file was already opened $@. Files should not be read and written at the same time using different streams. | test.c:5:14:5:18 | call to fopen | here | | test.c:17:14:17:18 | call to fopen | The same file was already opened $@. Files should not be read and written at the same time using different streams. | test.c:16:14:16:18 | call to fopen | here | | test.c:33:14:33:18 | call to fopen | The same file was already opened $@. Files should not be read and written at the same time using different streams. | test.c:32:14:32:18 | call to fopen | here | diff --git a/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected b/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected index 88dca316a2..dbf08e3d3d 100644 --- a/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected +++ b/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected @@ -1,8 +1,8 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:18,32-40) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:19,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:24,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:30,21-29) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:32,6-14) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:35,28-36) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:19,32-40) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:20,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:25,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:31,21-29) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:33,6-14) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:36,28-36) | test.c:10:3:10:9 | call to fprintf | Attempt to write to a $@ opened as read-only. | test.c:9:14:9:18 | call to fopen | stream | | test.c:15:3:15:9 | call to fprintf | Attempt to write to a $@ opened as read-only. | test.c:18:14:18:18 | call to fopen | stream | diff --git a/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected b/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected index a7ee20c0b0..83a10a46fb 100644 --- a/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected +++ b/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected @@ -1,10 +1,10 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:22,28-36) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:23,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:27,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:36,23-31) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:41,17-25) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:50,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:58,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:58,46-54) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:23,28-36) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:24,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:28,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:37,23-31) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:42,17-25) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:51,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:59,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:59,46-54) | test.c:6:7:6:20 | ... != ... | The check is not reliable as the type of the return value of $@ is converted. | test.c:5:14:5:20 | call to getchar | call to getchar | | test.c:13:7:13:15 | ... != ... | The check is not reliable as the type of the return value of $@ is converted. | test.c:12:14:12:20 | call to getchar | call to getchar | From 7595aa41a7e0bfff32776d5a679e5f9366b30528 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 5 Dec 2024 10:54:28 +0000 Subject: [PATCH 071/370] Add FALSE_NEGATIVE markers for #811 https://github.com/github/codeql-coding-standards/issues/811 --- cpp/autosar/test/rules/A12-8-6/test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/autosar/test/rules/A12-8-6/test.cpp b/cpp/autosar/test/rules/A12-8-6/test.cpp index 6a31ca60ae..d197fc18fb 100644 --- a/cpp/autosar/test/rules/A12-8-6/test.cpp +++ b/cpp/autosar/test/rules/A12-8-6/test.cpp @@ -12,8 +12,8 @@ class DerivedClass1 // COMPLIANT - not a base class itself // Base class with compiler generated move/copy is not compliant, because they // are public by default -class BaseClass2 {}; // NON_COMPLIANT - compiler generated move and assignment - // are in contravention +class BaseClass2 {}; // NON_COMPLIANT[FALSE_NEGATIVE] - compiler generated move + // and assignment are in contravention class DerivedClass2 // COMPLIANT - not a base class itself : public BaseClass2 {}; @@ -87,7 +87,7 @@ template class BaseClass7 { BaseClass7 &operator=(BaseClass7 const &) = default; // NON_COMPLIANT BaseClass7 &operator=(BaseClass7 &&) = default; // NON_COMPLIANT int operator=(int i); // COMPLIANT - not an assignment operator -}; // COMPLIANT +}; template class DerivedClass7 // COMPLIANT - not a base class itself @@ -121,7 +121,7 @@ class DerivedClass9 // COMPLIANT - not a base class itself T t; }; -template class BaseClass9 { // NON_COMPLIANT +template class BaseClass9 { // NON_COMPLIANT[FALSE_NEGATIVE] public: BaseClass9() {} From d7be5cca7f47055a1de40a2e51b308680147c852 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 5 Dec 2024 10:55:05 +0000 Subject: [PATCH 072/370] Add change note for upgrade --- change_notes/2024-12-05-upgrade-to-2.18.4.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 change_notes/2024-12-05-upgrade-to-2.18.4.md diff --git a/change_notes/2024-12-05-upgrade-to-2.18.4.md b/change_notes/2024-12-05-upgrade-to-2.18.4.md new file mode 100644 index 0000000000..6f3d4ba404 --- /dev/null +++ b/change_notes/2024-12-05-upgrade-to-2.18.4.md @@ -0,0 +1,3 @@ +- Updated the CodeQL version to `2.18.4`. +- `A12-8-6` - `CopyAndMoveNotDeclaredProtected.ql`: + - Implicitly created copy and move constructors will no longer be flagged in tenplate instantiations when they are unused, or trivial (tracked at https://github.com/github/codeql-coding-standards/issues/811). \ No newline at end of file From 0aa1f5f6965b7835fdcabab09fa60f1b8eea7208 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 5 Dec 2024 22:45:24 +0000 Subject: [PATCH 073/370] Remove no longer needed false positive markers --- cpp/common/test/rules/validcontainerelementaccess/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/common/test/rules/validcontainerelementaccess/test.cpp b/cpp/common/test/rules/validcontainerelementaccess/test.cpp index d9e2c2d89a..55c94cf8f1 100644 --- a/cpp/common/test/rules/validcontainerelementaccess/test.cpp +++ b/cpp/common/test/rules/validcontainerelementaccess/test.cpp @@ -96,14 +96,14 @@ void f8(const int *ar) { void f9(const std::string &s, std::string &str) { std::string::iterator loc = str.begin(); for (auto i = s.begin(), e = s.end(); i != e; ++i, ++loc) { // NON_COMPLIANT - str.insert(loc, 'c'); // NON_COMPLIANT[FALSE POSITIVE for str] + str.insert(loc, 'c'); // NON_COMPLIANT } } void f10(const std::string &s, std::string &str) { std::string::iterator loc = str.begin(); for (auto i = s.begin(), e = s.end(); i != e; ++i, ++loc) { // COMPLIANT - loc = str.insert(loc, 'c'); // COMPLIANT[FALSE POSITIVE] + loc = str.insert(loc, 'c'); // COMPLIANT } } From 27efc319d67e44524f3eeeae10b61b85f71671c0 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Fri, 6 Dec 2024 22:53:18 +0000 Subject: [PATCH 074/370] Remove unused Scope import --- cpp/cert/src/rules/DCL53-CPP/LocalFunctionDeclaration.ql | 1 - 1 file changed, 1 deletion(-) diff --git a/cpp/cert/src/rules/DCL53-CPP/LocalFunctionDeclaration.ql b/cpp/cert/src/rules/DCL53-CPP/LocalFunctionDeclaration.ql index 3f91530c84..368c0a05e4 100644 --- a/cpp/cert/src/rules/DCL53-CPP/LocalFunctionDeclaration.ql +++ b/cpp/cert/src/rules/DCL53-CPP/LocalFunctionDeclaration.ql @@ -13,7 +13,6 @@ import cpp import codingstandards.cpp.cert -import codingstandards.cpp.Scope class LocalUserFunctionDeclarationEntry extends FunctionDeclarationEntry { DeclStmt ds; From 0c92f2efa9b6305fae4e3e188c5eab2939f71886 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Fri, 6 Dec 2024 23:54:56 +0000 Subject: [PATCH 075/370] DCL53-CPP: Migrate to hidesStrict Any conflicting variable will be, by definition, in a different scope. --- .../LocalConstructorInitializedObjectHidesIdentifier.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/cert/src/rules/DCL53-CPP/LocalConstructorInitializedObjectHidesIdentifier.ql b/cpp/cert/src/rules/DCL53-CPP/LocalConstructorInitializedObjectHidesIdentifier.ql index 237ebbe985..f6fe18a3db 100644 --- a/cpp/cert/src/rules/DCL53-CPP/LocalConstructorInitializedObjectHidesIdentifier.ql +++ b/cpp/cert/src/rules/DCL53-CPP/LocalConstructorInitializedObjectHidesIdentifier.ql @@ -20,6 +20,6 @@ from UserVariable v, UserVariable hidden where not isExcluded(v, ScopePackage::localConstructorInitializedObjectHidesIdentifierQuery()) and v.getInitializer().getExpr() instanceof ConstructorCall and - hides(hidden, v) + hidesStrict(hidden, v) select v, "The declaration declares variable " + v.getName() + " that hides $@", hidden, hidden.getName() From 90d4127a7bc8c8f3a9a09541f39aebb50f25a98d Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sat, 7 Dec 2024 00:04:46 +0000 Subject: [PATCH 076/370] Scope: Remove hides(..) and related predicates There are no more consumers of hides(..). In addition, it doesn't make sense conceptually to look for variables in the same scope with the same name, as scopes will prohibit using the same name in the same scope. Reviewing real world cases where this occurs, they all seem to be extractor oddities (multiple copies of parameters for the same function etc.) which provides further evidence that this mode is not required. --- cpp/common/src/codingstandards/cpp/Scope.qll | 28 -------------------- 1 file changed, 28 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/Scope.qll b/cpp/common/src/codingstandards/cpp/Scope.qll index d9a81b98e3..b05c5dc9c4 100644 --- a/cpp/common/src/codingstandards/cpp/Scope.qll +++ b/cpp/common/src/codingstandards/cpp/Scope.qll @@ -160,15 +160,6 @@ predicate inSameTranslationUnit(File f1, File f2) { ) } -/** - * Gets a user variable which occurs in the "potential scope" of variable `v`. - */ -cached -UserVariable getPotentialScopeOfVariable(UserVariable v) { - result = getPotentialScopeOfVariable_candidate(v) and - inSameTranslationUnit(v.getFile(), result.getFile()) -} - /** * Gets a user variable which occurs in the "outer scope" of variable `v`. */ @@ -203,15 +194,6 @@ class TranslationUnit extends SourceFile { } } -/** Holds if `v2` may hide `v1`. */ -private predicate hides_candidate(UserVariable v1, UserVariable v2) { - not v1 = v2 and - v2 = getPotentialScopeOfVariable(v1) and - v1.getName() = v2.getName() and - // Member variables cannot hide other variables nor be hidden because the can be referenced through their qualified name. - not (v1.isMember() or v2.isMember()) -} - /** Holds if `v2` may hide `v1`. */ private predicate hides_candidateStrict(UserVariable v1, UserVariable v2) { not v1 = v2 and @@ -256,16 +238,6 @@ private Stmt getEnclosingStmt(LocalScopeVariable v) { ) } -/** Holds if `v2` hides `v1`. */ -predicate hides(UserVariable v1, UserVariable v2) { - hides_candidate(v1, v2) and - // Confirm that there's no closer candidate variable which `v2` hides - not exists(UserVariable mid | - hides_candidate(v1, mid) and - hides_candidate(mid, v2) - ) -} - /** Holds if `v2` strictly (`v2` is in an inner scope compared to `v1`) hides `v1`. */ predicate hidesStrict(UserVariable v1, UserVariable v2) { hides_candidateStrict(v1, v2) and From 6b5021a923702d9b85bca2e923ff279b8e5fd69f Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 8 Dec 2024 17:23:28 +0000 Subject: [PATCH 077/370] Scope: Add getParentScope testing - Expose the internal getParentScope for testing. - Add test cases --- cpp/common/src/codingstandards/cpp/Scope.qll | 107 ++++++++++-------- .../cpp/scope/ParentScope.expected | 96 ++++++++++++++++ .../codingstandards/cpp/scope/ParentScope.ql | 5 + .../codingstandards/cpp/scope/test.cpp | 37 ++++++ 4 files changed, 195 insertions(+), 50 deletions(-) create mode 100644 cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected create mode 100644 cpp/common/test/library/codingstandards/cpp/scope/ParentScope.ql create mode 100644 cpp/common/test/library/codingstandards/cpp/scope/test.cpp diff --git a/cpp/common/src/codingstandards/cpp/Scope.qll b/cpp/common/src/codingstandards/cpp/Scope.qll index b05c5dc9c4..9af5c8e21c 100644 --- a/cpp/common/src/codingstandards/cpp/Scope.qll +++ b/cpp/common/src/codingstandards/cpp/Scope.qll @@ -5,54 +5,59 @@ import cpp /** - * Gets the parent scope of this `Element`, if any. - * A scope is a `Type` (`Class` / `Enum`), a `Namespace`, a `Block`, a `Function`, - * or certain kinds of `Statement`. - * Differs from `Element::getParentScope` when `e` is a `LoopControlVariable` + * Internal module, exposed for testing. */ -private Element getParentScope(Element e) { - /* - * A `Block` cannot have a `ForStmt` as its parent scope so we have to special case - * for loop bodies to ensure that identifiers inside the loop bodies have the for stmt as a parent scope. - * If this is not the case then `i2` in the following example cannot be in `i1`'s potential scope, because - * the parent scope of `i1` is the `ForStmt` while the transitive closure of the parent scope for `i2` doesn't include - * outer scope. Blocks can only have blocks as parent scopes. - * void f() { - * for( int i1; ... ) { - * for (int i2; ...) { - * } - * } - * } +module Internal { + /** + * Gets the parent scope of this `Element`, if any. + * A scope is a `Type` (`Class` / `Enum`), a `Namespace`, a `Block`, a `Function`, + * or certain kinds of `Statement`. + * Differs from `Element::getParentScope` when `e` is a `LoopControlVariable` */ - - exists(Loop loop | loop.getStmt() = e and result = loop) - or - exists(IfStmt ifStmt | - (ifStmt.getThen() = e or ifStmt.getElse() = e) and - result = ifStmt - ) - or - exists(SwitchStmt switchStmt | switchStmt.getStmt() = e and result = switchStmt) - or - not result.(Loop).getStmt() = e and - not result.(IfStmt).getThen() = e and - not result.(IfStmt).getElse() = e and - not result.(SwitchStmt).getStmt() = e and - if exists(e.getParentScope()) - then result = e.getParentScope() - else ( - // Statements do no have a parent scope, so return the enclosing block. - result = e.(Stmt).getEnclosingBlock() + Element getParentScope(Element e) { + /* + * A `Block` cannot have a `ForStmt` as its parent scope so we have to special case + * for loop bodies to ensure that identifiers inside the loop bodies have the for stmt as a parent scope. + * If this is not the case then `i2` in the following example cannot be in `i1`'s potential scope, because + * the parent scope of `i1` is the `ForStmt` while the transitive closure of the parent scope for `i2` doesn't include + * outer scope. Blocks can only have blocks as parent scopes. + * void f() { + * for( int i1; ... ) { + * for (int i2; ...) { + * } + * } + * } + */ + + exists(Loop loop | loop.getStmt() = e and result = loop) + or + exists(IfStmt ifStmt | + (ifStmt.getThen() = e or ifStmt.getElse() = e) and + result = ifStmt + ) or - result = e.(Expr).getEnclosingBlock() + exists(SwitchStmt switchStmt | switchStmt.getStmt() = e and result = switchStmt) or - // Catch block parameters don't have an enclosing scope, so attach them to the - // the block itself - exists(CatchBlock cb | - e = cb.getParameter() and - result = cb + not result.(Loop).getStmt() = e and + not result.(IfStmt).getThen() = e and + not result.(IfStmt).getElse() = e and + not result.(SwitchStmt).getStmt() = e and + if exists(e.getParentScope()) + then result = e.getParentScope() + else ( + // Statements do no have a parent scope, so return the enclosing block. + result = e.(Stmt).getEnclosingBlock() + or + result = e.(Expr).getEnclosingBlock() + or + // Catch block parameters don't have an enclosing scope, so attach them to the + // the block itself + exists(CatchBlock cb | + e = cb.getParameter() and + result = cb + ) ) - ) + } } /** A variable which is defined by the user, rather than being from a third party or compiler generated. */ @@ -68,19 +73,19 @@ class UserVariable extends Variable { /** An element which is the parent scope of at least one other element in the program. */ class Scope extends Element { - Scope() { this = getParentScope(_) } + Scope() { this = Internal::getParentScope(_) } - UserVariable getAVariable() { getParentScope(result) = this } + UserVariable getAVariable() { Internal::getParentScope(result) = this } int getNumberOfVariables() { result = count(getAVariable()) } Scope getAnAncestor() { result = this.getStrictParent+() } - Scope getStrictParent() { result = getParentScope(this) } + Scope getStrictParent() { result = Internal::getParentScope(this) } - Declaration getADeclaration() { getParentScope(result) = this } + Declaration getADeclaration() { Internal::getParentScope(result) = this } - Expr getAnExpr() { this = getParentScope(result) } + Expr getAnExpr() { this = Internal::getParentScope(result) } private predicate getLocationInfo( PreprocessorBranchDirective pbd, string file1, string file2, int startline1, int startline2 @@ -112,9 +117,11 @@ class Scope extends Element { predicate isGenerated() { this instanceof GeneratedBlockStmt } int getDepth() { - exists(Scope parent | parent = getParentScope(this) and result = 1 + parent.getDepth()) + exists(Scope parent | + parent = Internal::getParentScope(this) and result = 1 + parent.getDepth() + ) or - not exists(getParentScope(this)) and result = 0 + not exists(Internal::getParentScope(this)) and result = 0 } } diff --git a/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected b/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected new file mode 100644 index 0000000000..0d36cc980d --- /dev/null +++ b/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected @@ -0,0 +1,96 @@ +| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | operator= | +| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | operator= | +| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:8:7:8:7 | operator= | +| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:8:7:8:7 | operator= | +| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:27:28:27:28 | (unnamed constructor) | +| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:27:28:27:28 | (unnamed constructor) | +| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:27:28:27:28 | operator= | +| file://:0:0:0:0 | __va_list_tag | file://:0:0:0:0 | (global namespace) | +| file://:0:0:0:0 | fp_offset | file://:0:0:0:0 | __va_list_tag | +| file://:0:0:0:0 | gp_offset | file://:0:0:0:0 | __va_list_tag | +| file://:0:0:0:0 | operator= | file://:0:0:0:0 | __va_list_tag | +| file://:0:0:0:0 | operator= | file://:0:0:0:0 | __va_list_tag | +| file://:0:0:0:0 | overflow_arg_area | file://:0:0:0:0 | __va_list_tag | +| file://:0:0:0:0 | reg_save_area | file://:0:0:0:0 | __va_list_tag | +| test.cpp:1:5:1:7 | id1 | file://:0:0:0:0 | (global namespace) | +| test.cpp:3:11:3:13 | ns1 | file://:0:0:0:0 | (global namespace) | +| test.cpp:4:5:4:7 | id1 | test.cpp:3:11:3:13 | ns1 | +| test.cpp:6:11:6:13 | ns1::ns2 | test.cpp:3:11:3:13 | ns1 | +| test.cpp:7:5:7:7 | id1 | test.cpp:6:11:6:13 | ns1::ns2 | +| test.cpp:8:7:8:7 | C1 | test.cpp:8:7:8:8 | C1 | +| test.cpp:8:7:8:7 | operator= | test.cpp:8:7:8:8 | C1 | +| test.cpp:8:7:8:7 | operator= | test.cpp:8:7:8:8 | C1 | +| test.cpp:8:7:8:8 | C1 | test.cpp:6:11:6:13 | ns1::ns2 | +| test.cpp:9:7:9:9 | id1 | test.cpp:8:7:8:8 | C1 | +| test.cpp:10:8:10:17 | test_scope | test.cpp:8:7:8:8 | C1 | +| test.cpp:10:23:10:25 | id1 | test.cpp:10:8:10:17 | test_scope | +| test.cpp:10:28:34:3 | { ... } | test.cpp:10:8:10:17 | test_scope | +| test.cpp:11:5:33:5 | for(...;...;...) ... | test.cpp:10:28:34:3 | { ... } | +| test.cpp:11:10:11:17 | declaration | test.cpp:10:28:34:3 | { ... } | +| test.cpp:11:14:11:16 | id1 | test.cpp:11:5:33:5 | for(...;...;...) ... | +| test.cpp:11:19:11:21 | id1 | test.cpp:10:28:34:3 | { ... } | +| test.cpp:11:19:11:25 | ... < ... | test.cpp:10:28:34:3 | { ... } | +| test.cpp:11:25:11:25 | 1 | test.cpp:10:28:34:3 | { ... } | +| test.cpp:11:28:11:30 | id1 | test.cpp:10:28:34:3 | { ... } | +| test.cpp:11:28:11:32 | ... ++ | test.cpp:10:28:34:3 | { ... } | +| test.cpp:11:35:33:5 | { ... } | test.cpp:10:28:34:3 | { ... } | +| test.cpp:11:35:33:5 | { ... } | test.cpp:11:5:33:5 | for(...;...;...) ... | +| test.cpp:12:7:32:7 | for(...;...;...) ... | test.cpp:11:35:33:5 | { ... } | +| test.cpp:12:12:12:19 | declaration | test.cpp:11:35:33:5 | { ... } | +| test.cpp:12:16:12:18 | id1 | test.cpp:12:7:32:7 | for(...;...;...) ... | +| test.cpp:12:21:12:23 | id1 | test.cpp:11:35:33:5 | { ... } | +| test.cpp:12:21:12:27 | ... < ... | test.cpp:11:35:33:5 | { ... } | +| test.cpp:12:27:12:27 | 1 | test.cpp:11:35:33:5 | { ... } | +| test.cpp:12:30:12:32 | id1 | test.cpp:11:35:33:5 | { ... } | +| test.cpp:12:30:12:34 | ... ++ | test.cpp:11:35:33:5 | { ... } | +| test.cpp:12:37:32:7 | { ... } | test.cpp:11:35:33:5 | { ... } | +| test.cpp:12:37:32:7 | { ... } | test.cpp:12:7:32:7 | for(...;...;...) ... | +| test.cpp:13:9:31:9 | { ... } | test.cpp:12:37:32:7 | { ... } | +| test.cpp:14:11:14:18 | declaration | test.cpp:13:9:31:9 | { ... } | +| test.cpp:14:15:14:17 | id1 | test.cpp:13:9:31:9 | { ... } | +| test.cpp:16:11:20:11 | if (...) ... | test.cpp:13:9:31:9 | { ... } | +| test.cpp:16:15:16:17 | id1 | test.cpp:13:9:31:9 | { ... } | +| test.cpp:16:15:16:22 | ... == ... | test.cpp:13:9:31:9 | { ... } | +| test.cpp:16:22:16:22 | 0 | test.cpp:13:9:31:9 | { ... } | +| test.cpp:16:25:18:11 | { ... } | test.cpp:13:9:31:9 | { ... } | +| test.cpp:16:25:18:11 | { ... } | test.cpp:16:11:20:11 | if (...) ... | +| test.cpp:17:13:17:20 | declaration | test.cpp:16:25:18:11 | { ... } | +| test.cpp:17:17:17:19 | id1 | test.cpp:16:25:18:11 | { ... } | +| test.cpp:18:18:20:11 | { ... } | test.cpp:13:9:31:9 | { ... } | +| test.cpp:18:18:20:11 | { ... } | test.cpp:16:11:20:11 | if (...) ... | +| test.cpp:19:13:19:20 | declaration | test.cpp:18:18:20:11 | { ... } | +| test.cpp:19:17:19:19 | id1 | test.cpp:18:18:20:11 | { ... } | +| test.cpp:21:11:25:11 | switch (...) ... | test.cpp:13:9:31:9 | { ... } | +| test.cpp:21:19:21:21 | id1 | test.cpp:13:9:31:9 | { ... } | +| test.cpp:21:24:25:11 | { ... } | test.cpp:13:9:31:9 | { ... } | +| test.cpp:21:24:25:11 | { ... } | test.cpp:21:11:25:11 | switch (...) ... | +| test.cpp:22:11:22:17 | case ...: | test.cpp:21:24:25:11 | { ... } | +| test.cpp:22:16:22:16 | 0 | test.cpp:21:24:25:11 | { ... } | +| test.cpp:23:13:23:20 | declaration | test.cpp:21:24:25:11 | { ... } | +| test.cpp:23:17:23:19 | id1 | test.cpp:21:24:25:11 | { ... } | +| test.cpp:24:13:24:18 | break; | test.cpp:21:24:25:11 | { ... } | +| test.cpp:25:11:25:11 | label ...: | test.cpp:13:9:31:9 | { ... } | +| test.cpp:26:11:28:11 | try { ... } | test.cpp:13:9:31:9 | { ... } | +| test.cpp:26:15:28:11 | { ... } | test.cpp:13:9:31:9 | { ... } | +| test.cpp:27:13:27:53 | declaration | test.cpp:26:15:28:11 | { ... } | +| test.cpp:27:18:27:24 | lambda1 | test.cpp:26:15:28:11 | { ... } | +| test.cpp:27:27:27:52 | [...](...){...} | test.cpp:26:15:28:11 | { ... } | +| test.cpp:27:27:27:52 | {...} | test.cpp:26:15:28:11 | { ... } | +| test.cpp:27:28:27:28 | (unnamed constructor) | file://:0:0:0:0 | decltype([...](...){...}) | +| test.cpp:27:28:27:28 | (unnamed constructor) | file://:0:0:0:0 | decltype([...](...){...}) | +| test.cpp:27:28:27:28 | (unnamed constructor) | file://:0:0:0:0 | decltype([...](...){...}) | +| test.cpp:27:28:27:28 | operator= | file://:0:0:0:0 | decltype([...](...){...}) | +| test.cpp:27:29:27:29 | id1 | file://:0:0:0:0 | decltype([...](...){...}) | +| test.cpp:27:29:27:31 | id1 | test.cpp:26:15:28:11 | { ... } | +| test.cpp:27:33:27:33 | operator() | file://:0:0:0:0 | decltype([...](...){...}) | +| test.cpp:27:36:27:52 | { ... } | test.cpp:27:33:27:33 | operator() | +| test.cpp:27:38:27:50 | declaration | test.cpp:27:36:27:52 | { ... } | +| test.cpp:27:42:27:44 | id1 | test.cpp:27:36:27:52 | { ... } | +| test.cpp:27:47:27:49 | 10 | test.cpp:27:36:27:52 | { ... } | +| test.cpp:27:52:27:52 | return ... | test.cpp:27:36:27:52 | { ... } | +| test.cpp:28:24:28:26 | id1 | test.cpp:28:29:30:11 | { ... } | +| test.cpp:28:29:30:11 | | test.cpp:13:9:31:9 | { ... } | +| test.cpp:28:29:30:11 | { ... } | test.cpp:13:9:31:9 | { ... } | +| test.cpp:29:13:29:20 | declaration | test.cpp:28:29:30:11 | { ... } | +| test.cpp:29:17:29:19 | id1 | test.cpp:28:29:30:11 | { ... } | +| test.cpp:34:3:34:3 | return ... | test.cpp:10:28:34:3 | { ... } | diff --git a/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.ql b/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.ql new file mode 100644 index 0000000000..47d27fb0f0 --- /dev/null +++ b/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.ql @@ -0,0 +1,5 @@ +import codingstandards.cpp.Scope + +from Element e, Element parent +where Internal::getParentScope(e) = parent +select e, parent diff --git a/cpp/common/test/library/codingstandards/cpp/scope/test.cpp b/cpp/common/test/library/codingstandards/cpp/scope/test.cpp new file mode 100644 index 0000000000..a0b617916d --- /dev/null +++ b/cpp/common/test/library/codingstandards/cpp/scope/test.cpp @@ -0,0 +1,37 @@ +int id1; + +namespace ns1 { +int id1; // COMPLIANT + +namespace ns2 { +int id1; // COMPLIANT +class C1 { + int id1; + void test_scope(int id1) { + for (int id1; id1 < 1; id1++) { + for (int id1; id1 < 1; id1++) { + { + int id1; + + if (id1 == 0) { + int id1; + } else { + int id1; + } + switch (id1) { + case 0: + int id1; + break; + } + try { + auto lambda1 = [id1]() { int id1 = 10; }; + } catch (int id1) { + int id1; + } + } + } + } + } +}; +} // namespace ns2 +} // namespace ns1 From b8b41312c24fa6d9ce511a5d0543ddef08c7f6ee Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 8 Dec 2024 17:26:09 +0000 Subject: [PATCH 078/370] Scope: Address logic flaw creating multiple parents We adjust the parent scope explicitly for loops, if statements and switch statements, but, due to a logic bug, we previously retained the existing results provided by Element.getParentScope(). --- cpp/common/src/codingstandards/cpp/Scope.qll | 7 +++---- .../library/codingstandards/cpp/scope/ParentScope.expected | 5 ----- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/Scope.qll b/cpp/common/src/codingstandards/cpp/Scope.qll index 9af5c8e21c..ce8c5be113 100644 --- a/cpp/common/src/codingstandards/cpp/Scope.qll +++ b/cpp/common/src/codingstandards/cpp/Scope.qll @@ -38,10 +38,9 @@ module Internal { or exists(SwitchStmt switchStmt | switchStmt.getStmt() = e and result = switchStmt) or - not result.(Loop).getStmt() = e and - not result.(IfStmt).getThen() = e and - not result.(IfStmt).getElse() = e and - not result.(SwitchStmt).getStmt() = e and + not exists(Loop loop | loop.getStmt() = e) and + not exists(IfStmt ifStmt | ifStmt.getThen() = e or ifStmt.getElse() = e) and + not exists(SwitchStmt switchStmt | switchStmt.getStmt() = e) and if exists(e.getParentScope()) then result = e.getParentScope() else ( diff --git a/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected b/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected index 0d36cc980d..6335394970 100644 --- a/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected +++ b/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected @@ -33,7 +33,6 @@ | test.cpp:11:25:11:25 | 1 | test.cpp:10:28:34:3 | { ... } | | test.cpp:11:28:11:30 | id1 | test.cpp:10:28:34:3 | { ... } | | test.cpp:11:28:11:32 | ... ++ | test.cpp:10:28:34:3 | { ... } | -| test.cpp:11:35:33:5 | { ... } | test.cpp:10:28:34:3 | { ... } | | test.cpp:11:35:33:5 | { ... } | test.cpp:11:5:33:5 | for(...;...;...) ... | | test.cpp:12:7:32:7 | for(...;...;...) ... | test.cpp:11:35:33:5 | { ... } | | test.cpp:12:12:12:19 | declaration | test.cpp:11:35:33:5 | { ... } | @@ -43,7 +42,6 @@ | test.cpp:12:27:12:27 | 1 | test.cpp:11:35:33:5 | { ... } | | test.cpp:12:30:12:32 | id1 | test.cpp:11:35:33:5 | { ... } | | test.cpp:12:30:12:34 | ... ++ | test.cpp:11:35:33:5 | { ... } | -| test.cpp:12:37:32:7 | { ... } | test.cpp:11:35:33:5 | { ... } | | test.cpp:12:37:32:7 | { ... } | test.cpp:12:7:32:7 | for(...;...;...) ... | | test.cpp:13:9:31:9 | { ... } | test.cpp:12:37:32:7 | { ... } | | test.cpp:14:11:14:18 | declaration | test.cpp:13:9:31:9 | { ... } | @@ -52,17 +50,14 @@ | test.cpp:16:15:16:17 | id1 | test.cpp:13:9:31:9 | { ... } | | test.cpp:16:15:16:22 | ... == ... | test.cpp:13:9:31:9 | { ... } | | test.cpp:16:22:16:22 | 0 | test.cpp:13:9:31:9 | { ... } | -| test.cpp:16:25:18:11 | { ... } | test.cpp:13:9:31:9 | { ... } | | test.cpp:16:25:18:11 | { ... } | test.cpp:16:11:20:11 | if (...) ... | | test.cpp:17:13:17:20 | declaration | test.cpp:16:25:18:11 | { ... } | | test.cpp:17:17:17:19 | id1 | test.cpp:16:25:18:11 | { ... } | -| test.cpp:18:18:20:11 | { ... } | test.cpp:13:9:31:9 | { ... } | | test.cpp:18:18:20:11 | { ... } | test.cpp:16:11:20:11 | if (...) ... | | test.cpp:19:13:19:20 | declaration | test.cpp:18:18:20:11 | { ... } | | test.cpp:19:17:19:19 | id1 | test.cpp:18:18:20:11 | { ... } | | test.cpp:21:11:25:11 | switch (...) ... | test.cpp:13:9:31:9 | { ... } | | test.cpp:21:19:21:21 | id1 | test.cpp:13:9:31:9 | { ... } | -| test.cpp:21:24:25:11 | { ... } | test.cpp:13:9:31:9 | { ... } | | test.cpp:21:24:25:11 | { ... } | test.cpp:21:11:25:11 | switch (...) ... | | test.cpp:22:11:22:17 | case ...: | test.cpp:21:24:25:11 | { ... } | | test.cpp:22:16:22:16 | 0 | test.cpp:21:24:25:11 | { ... } | From 1f8e2baedb543b5a4318fc87d63b797865902f18 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 8 Dec 2024 17:31:41 +0000 Subject: [PATCH 079/370] Scope: Ensure loop entries have correct parent scope All direct children of a for loop should have the for loop itself as the scope. --- cpp/common/src/codingstandards/cpp/Scope.qll | 4 ++-- .../codingstandards/cpp/scope/ParentScope.expected | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/Scope.qll b/cpp/common/src/codingstandards/cpp/Scope.qll index ce8c5be113..ad99ab8bd4 100644 --- a/cpp/common/src/codingstandards/cpp/Scope.qll +++ b/cpp/common/src/codingstandards/cpp/Scope.qll @@ -29,7 +29,7 @@ module Internal { * } */ - exists(Loop loop | loop.getStmt() = e and result = loop) + exists(Loop loop | loop.getAChild() = e and result = loop) or exists(IfStmt ifStmt | (ifStmt.getThen() = e or ifStmt.getElse() = e) and @@ -38,7 +38,7 @@ module Internal { or exists(SwitchStmt switchStmt | switchStmt.getStmt() = e and result = switchStmt) or - not exists(Loop loop | loop.getStmt() = e) and + not exists(Loop loop | loop.getAChild() = e) and not exists(IfStmt ifStmt | ifStmt.getThen() = e or ifStmt.getElse() = e) and not exists(SwitchStmt switchStmt | switchStmt.getStmt() = e) and if exists(e.getParentScope()) diff --git a/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected b/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected index 6335394970..34a48c8065 100644 --- a/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected +++ b/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected @@ -26,22 +26,22 @@ | test.cpp:10:23:10:25 | id1 | test.cpp:10:8:10:17 | test_scope | | test.cpp:10:28:34:3 | { ... } | test.cpp:10:8:10:17 | test_scope | | test.cpp:11:5:33:5 | for(...;...;...) ... | test.cpp:10:28:34:3 | { ... } | -| test.cpp:11:10:11:17 | declaration | test.cpp:10:28:34:3 | { ... } | +| test.cpp:11:10:11:17 | declaration | test.cpp:11:5:33:5 | for(...;...;...) ... | | test.cpp:11:14:11:16 | id1 | test.cpp:11:5:33:5 | for(...;...;...) ... | | test.cpp:11:19:11:21 | id1 | test.cpp:10:28:34:3 | { ... } | -| test.cpp:11:19:11:25 | ... < ... | test.cpp:10:28:34:3 | { ... } | +| test.cpp:11:19:11:25 | ... < ... | test.cpp:11:5:33:5 | for(...;...;...) ... | | test.cpp:11:25:11:25 | 1 | test.cpp:10:28:34:3 | { ... } | | test.cpp:11:28:11:30 | id1 | test.cpp:10:28:34:3 | { ... } | -| test.cpp:11:28:11:32 | ... ++ | test.cpp:10:28:34:3 | { ... } | +| test.cpp:11:28:11:32 | ... ++ | test.cpp:11:5:33:5 | for(...;...;...) ... | | test.cpp:11:35:33:5 | { ... } | test.cpp:11:5:33:5 | for(...;...;...) ... | | test.cpp:12:7:32:7 | for(...;...;...) ... | test.cpp:11:35:33:5 | { ... } | -| test.cpp:12:12:12:19 | declaration | test.cpp:11:35:33:5 | { ... } | +| test.cpp:12:12:12:19 | declaration | test.cpp:12:7:32:7 | for(...;...;...) ... | | test.cpp:12:16:12:18 | id1 | test.cpp:12:7:32:7 | for(...;...;...) ... | | test.cpp:12:21:12:23 | id1 | test.cpp:11:35:33:5 | { ... } | -| test.cpp:12:21:12:27 | ... < ... | test.cpp:11:35:33:5 | { ... } | +| test.cpp:12:21:12:27 | ... < ... | test.cpp:12:7:32:7 | for(...;...;...) ... | | test.cpp:12:27:12:27 | 1 | test.cpp:11:35:33:5 | { ... } | | test.cpp:12:30:12:32 | id1 | test.cpp:11:35:33:5 | { ... } | -| test.cpp:12:30:12:34 | ... ++ | test.cpp:11:35:33:5 | { ... } | +| test.cpp:12:30:12:34 | ... ++ | test.cpp:12:7:32:7 | for(...;...;...) ... | | test.cpp:12:37:32:7 | { ... } | test.cpp:12:7:32:7 | for(...;...;...) ... | | test.cpp:13:9:31:9 | { ... } | test.cpp:12:37:32:7 | { ... } | | test.cpp:14:11:14:18 | declaration | test.cpp:13:9:31:9 | { ... } | From 63a60b1855f00c96a63e16242055ab2f660782f8 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 8 Dec 2024 18:19:26 +0000 Subject: [PATCH 080/370] Scope: Address performance issues with excludedViaNestedNamespace Add pragma_inline to ensure we consider this as a post-filtering step. --- cpp/common/src/codingstandards/cpp/Scope.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpp/common/src/codingstandards/cpp/Scope.qll b/cpp/common/src/codingstandards/cpp/Scope.qll index ad99ab8bd4..3e1bb6c803 100644 --- a/cpp/common/src/codingstandards/cpp/Scope.qll +++ b/cpp/common/src/codingstandards/cpp/Scope.qll @@ -269,6 +269,8 @@ predicate hasBlockScope(Declaration decl) { exists(BlockStmt b | b.getADeclarati /** * identifiers in nested (named/nonglobal) namespaces are exceptions to hiding due to being able access via fully qualified ids */ +bindingset[outerDecl, innerDecl] +pragma[inline_late] predicate excludedViaNestedNamespaces(UserVariable outerDecl, UserVariable innerDecl) { exists(Namespace inner, Namespace outer | outer.getAChildNamespace+() = inner and From 1bd839c34c39e3546484d666ebe8b15d0e9e0451 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sat, 7 Dec 2024 00:43:37 +0000 Subject: [PATCH 081/370] Scope: Improve performance of hidesStrict Improves performance by: - Capturing for each scope the list of names defined by nested scopes - Use that to determine hidden identifiers for a scope. - Separately determine the hiding identifiers for a scope. This addresses performance issues in the now deleted predicate getOuterScopesOfVariable_candidate(). --- cpp/common/src/codingstandards/cpp/Scope.qll | 119 +++++++++++++------ 1 file changed, 82 insertions(+), 37 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/Scope.qll b/cpp/common/src/codingstandards/cpp/Scope.qll index 3e1bb6c803..8e618cb21e 100644 --- a/cpp/common/src/codingstandards/cpp/Scope.qll +++ b/cpp/common/src/codingstandards/cpp/Scope.qll @@ -122,39 +122,77 @@ class Scope extends Element { or not exists(Internal::getParentScope(this)) and result = 0 } -} -class GeneratedBlockStmt extends BlockStmt { - GeneratedBlockStmt() { this.getLocation() instanceof UnknownLocation } -} + /** + * Holds if `name` is declared in this scope, or in a nested scope. + */ + private predicate isNameDeclaredInThisOrNestedScope(string name) { + name = getAVariable().getName() + or + isNameDeclaredInNestedScope(name) + } + + /** + * Holds if `name` is declared in a nested scope. + */ + private predicate isNameDeclaredInNestedScope(string name) { + exists(Scope child | + child.getStrictParent() = this and + child.isNameDeclaredInThisOrNestedScope(name) + ) + } + + /** + * Holds if `name` is declared in this scope and is hidden in a child scope. + */ + private predicate isDeclaredNameHiddenByChild(string name) { + isNameDeclaredInNestedScope(name) and + name = getAVariable().getName() + } + + /** + * Gets a variable with `name` which is hidden in at least one nested scope. + */ + UserVariable getAHiddenVariable(string name) { + result = getAVariable() and + result.getName() = name and + isDeclaredNameHiddenByChild(name) + } -/** Gets a variable that is in the potential scope of variable `v`. */ -private UserVariable getPotentialScopeOfVariable_candidate(UserVariable v) { - exists(Scope s | - result = s.getAVariable() and + /** + * Holds if `name` is declared above this scope and hidden by this or a nested scope. + */ + private predicate isNameDeclaredAboveHiddenByThisOrNested(string name) { ( - // Variable in an ancestor scope, but only if there are less than 100 variables in this scope - v = s.getAnAncestor().getAVariable() and - s.getNumberOfVariables() < 100 + this.getStrictParent().isDeclaredNameHiddenByChild(name) or + this.getStrictParent().isNameDeclaredAboveHiddenByThisOrNested(name) + ) and + isNameDeclaredInThisOrNestedScope(name) + } + + /** + * Gets a variable with `name` which is declared above and hidden by a variable in this or a nested scope. + */ + UserVariable getAHidingVariable(string name) { + isNameDeclaredAboveHiddenByThisOrNested(name) and + ( + // Declared in this scope + getAVariable().getName() = name and + result = getAVariable() and + result.getName() = name or - // In the same scope, but not the same variable, and choose just one to report - v = s.getAVariable() and - not result = v and - v.getName() <= result.getName() + // Declared in a child scope + exists(Scope child | + child.getStrictParent() = this and + child.isNameDeclaredInThisOrNestedScope(name) and + result = child.getAHidingVariable(name) + ) ) - ) + } } -/** Gets a variable that is in the potential scope of variable `v`. */ -private UserVariable getOuterScopesOfVariable_candidate(UserVariable v) { - exists(Scope s | - result = s.getAVariable() and - ( - // Variable in an ancestor scope, but only if there are less than 100 variables in this scope - v = s.getAnAncestor().getAVariable() and - s.getNumberOfVariables() < 100 - ) - ) +class GeneratedBlockStmt extends BlockStmt { + GeneratedBlockStmt() { this.getLocation() instanceof UnknownLocation } } /** Holds if there exists a translation unit that includes both `f1` and `f2`. */ @@ -167,12 +205,17 @@ predicate inSameTranslationUnit(File f1, File f2) { } /** - * Gets a user variable which occurs in the "outer scope" of variable `v`. + * Holds if there exists a translation unit that includes both `f1` and `f2`. + * + * This version is late bound. */ -cached -UserVariable getPotentialScopeOfVariableStrict(UserVariable v) { - result = getOuterScopesOfVariable_candidate(v) and - inSameTranslationUnit(v.getFile(), result.getFile()) +bindingset[f1, f2] +pragma[inline_late] +predicate inSameTranslationUnitLate(File f1, File f2) { + exists(TranslationUnit c | + c.getAUserFile() = f1 and + c.getAUserFile() = f2 + ) } /** A file that is a C/C++ source file */ @@ -200,12 +243,14 @@ class TranslationUnit extends SourceFile { } } -/** Holds if `v2` may hide `v1`. */ -private predicate hides_candidateStrict(UserVariable v1, UserVariable v2) { - not v1 = v2 and - v2 = getPotentialScopeOfVariableStrict(v1) and - v1.getName() = v2.getName() and - // Member variables cannot hide other variables nor be hidden because the can be referenced through their qualified name. +/** Holds if `v2` strictly (`v2` is in an inner scope compared to `v1`) hides `v1`. */ +predicate hides_candidateStrict(UserVariable v1, UserVariable v2) { + exists(Scope s, string name | + v1 = s.getStrictParent().getAHiddenVariable(name) and + v2 = s.getAHidingVariable(name) and + not v1 = v2 + ) and + inSameTranslationUnitLate(v1.getFile(), v2.getFile()) and not (v1.isMember() or v2.isMember()) and ( // If v1 is a local variable, ensure that v1 is declared before v2 From f25507e821aeae14df6e2b676599b57768016387 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 8 Dec 2024 19:20:03 +0000 Subject: [PATCH 082/370] Scope: Add a child scope accessor --- cpp/common/src/codingstandards/cpp/Scope.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpp/common/src/codingstandards/cpp/Scope.qll b/cpp/common/src/codingstandards/cpp/Scope.qll index 8e618cb21e..1c9a621b39 100644 --- a/cpp/common/src/codingstandards/cpp/Scope.qll +++ b/cpp/common/src/codingstandards/cpp/Scope.qll @@ -80,6 +80,8 @@ class Scope extends Element { Scope getAnAncestor() { result = this.getStrictParent+() } + Scope getAChildScope() { result.getStrictParent() = this } + Scope getStrictParent() { result = Internal::getParentScope(this) } Declaration getADeclaration() { Internal::getParentScope(result) = this } From b5ff407e07197d229664b462503916f1da268104 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 8 Dec 2024 19:20:40 +0000 Subject: [PATCH 083/370] Scope: Adopt use of getAChildScope() --- cpp/common/src/codingstandards/cpp/Scope.qll | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/Scope.qll b/cpp/common/src/codingstandards/cpp/Scope.qll index 1c9a621b39..d0f5995537 100644 --- a/cpp/common/src/codingstandards/cpp/Scope.qll +++ b/cpp/common/src/codingstandards/cpp/Scope.qll @@ -138,10 +138,7 @@ class Scope extends Element { * Holds if `name` is declared in a nested scope. */ private predicate isNameDeclaredInNestedScope(string name) { - exists(Scope child | - child.getStrictParent() = this and - child.isNameDeclaredInThisOrNestedScope(name) - ) + this.getAChildScope().isNameDeclaredInThisOrNestedScope(name) } /** @@ -173,7 +170,8 @@ class Scope extends Element { } /** - * Gets a variable with `name` which is declared above and hidden by a variable in this or a nested scope. + * Gets a variable with `name` which is declared in a scope above this one, and hidden by a variable in this or a + * nested scope. */ UserVariable getAHidingVariable(string name) { isNameDeclaredAboveHiddenByThisOrNested(name) and @@ -185,7 +183,7 @@ class Scope extends Element { or // Declared in a child scope exists(Scope child | - child.getStrictParent() = this and + getAChildScope() = child and child.isNameDeclaredInThisOrNestedScope(name) and result = child.getAHidingVariable(name) ) @@ -248,8 +246,8 @@ class TranslationUnit extends SourceFile { /** Holds if `v2` strictly (`v2` is in an inner scope compared to `v1`) hides `v1`. */ predicate hides_candidateStrict(UserVariable v1, UserVariable v2) { exists(Scope s, string name | - v1 = s.getStrictParent().getAHiddenVariable(name) and - v2 = s.getAHidingVariable(name) and + v1 = s.getAHiddenVariable(name) and + v2 = s.getAChildScope().getAHidingVariable(name) and not v1 = v2 ) and inSameTranslationUnitLate(v1.getFile(), v2.getFile()) and From dbd3fe6eeb10a1db03b2599765632a80539557e7 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 8 Dec 2024 22:27:35 +0000 Subject: [PATCH 084/370] Scope: Fix the parent scope of catch blocks We now tie the Handler into the TryStmt, and catch-block parameters into the Handler for a consistent AST hierarchy. --- cpp/common/src/codingstandards/cpp/Scope.qll | 18 ++++++++++-------- .../cpp/scope/ParentScope.expected | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/Scope.qll b/cpp/common/src/codingstandards/cpp/Scope.qll index d0f5995537..1027e251f2 100644 --- a/cpp/common/src/codingstandards/cpp/Scope.qll +++ b/cpp/common/src/codingstandards/cpp/Scope.qll @@ -38,23 +38,25 @@ module Internal { or exists(SwitchStmt switchStmt | switchStmt.getStmt() = e and result = switchStmt) or + // A catch-block parameter, whose parent is the `Handler` + exists(CatchBlock c | c.getParameter() = e and result = c.getParent()) + or + // A catch-block `Handler`, whose parent is the `TryStmt` + e.(Handler).getParent() = result + or not exists(Loop loop | loop.getAChild() = e) and not exists(IfStmt ifStmt | ifStmt.getThen() = e or ifStmt.getElse() = e) and not exists(SwitchStmt switchStmt | switchStmt.getStmt() = e) and + not exists(CatchBlock c | c.getParameter() = e) and + not e instanceof Handler and if exists(e.getParentScope()) then result = e.getParentScope() else ( - // Statements do no have a parent scope, so return the enclosing block. + // Statements do not have a parent scope, so return the enclosing block. result = e.(Stmt).getEnclosingBlock() or + // Expressions do not have a parent scope, so return the enclosing block. result = e.(Expr).getEnclosingBlock() - or - // Catch block parameters don't have an enclosing scope, so attach them to the - // the block itself - exists(CatchBlock cb | - e = cb.getParameter() and - result = cb - ) ) } } diff --git a/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected b/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected index 34a48c8065..e2152773af 100644 --- a/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected +++ b/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected @@ -83,8 +83,8 @@ | test.cpp:27:42:27:44 | id1 | test.cpp:27:36:27:52 | { ... } | | test.cpp:27:47:27:49 | 10 | test.cpp:27:36:27:52 | { ... } | | test.cpp:27:52:27:52 | return ... | test.cpp:27:36:27:52 | { ... } | -| test.cpp:28:24:28:26 | id1 | test.cpp:28:29:30:11 | { ... } | -| test.cpp:28:29:30:11 | | test.cpp:13:9:31:9 | { ... } | +| test.cpp:28:24:28:26 | id1 | test.cpp:28:29:30:11 | | +| test.cpp:28:29:30:11 | | test.cpp:26:11:28:11 | try { ... } | | test.cpp:28:29:30:11 | { ... } | test.cpp:13:9:31:9 | { ... } | | test.cpp:29:13:29:20 | declaration | test.cpp:28:29:30:11 | { ... } | | test.cpp:29:17:29:19 | id1 | test.cpp:28:29:30:11 | { ... } | From 61521e0144707fe65c611988f2412d86af94e07c Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 8 Dec 2024 23:20:37 +0000 Subject: [PATCH 085/370] Scope: Simplify mechanism for identifying declaration order --- cpp/common/src/codingstandards/cpp/Scope.qll | 50 +++++++------------- 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/Scope.qll b/cpp/common/src/codingstandards/cpp/Scope.qll index 1027e251f2..c716896356 100644 --- a/cpp/common/src/codingstandards/cpp/Scope.qll +++ b/cpp/common/src/codingstandards/cpp/Scope.qll @@ -247,48 +247,30 @@ class TranslationUnit extends SourceFile { /** Holds if `v2` strictly (`v2` is in an inner scope compared to `v1`) hides `v1`. */ predicate hides_candidateStrict(UserVariable v1, UserVariable v2) { - exists(Scope s, string name | - v1 = s.getAHiddenVariable(name) and - v2 = s.getAChildScope().getAHidingVariable(name) and + exists(Scope parentScope, Scope childScope, string name | + v1 = parentScope.getAHiddenVariable(name) and + childScope = parentScope.getAChildScope() and + v2 = childScope.getAHidingVariable(name) and not v1 = v2 - ) and - inSameTranslationUnitLate(v1.getFile(), v2.getFile()) and - not (v1.isMember() or v2.isMember()) and - ( - // If v1 is a local variable, ensure that v1 is declared before v2 + | + // If v1 is a local variable defined in a `DeclStmt` ensure that it is declared before `v2`, + // otherwise it would not be hidden ( - v1 instanceof LocalVariable and - // Ignore variables declared in conditional expressions, as they apply to - // the nested scope - not v1 = any(ConditionDeclExpr cde).getVariable() and - // Ignore variables declared in loops - not exists(Loop l | l.getADeclaration() = v1) + parentScope instanceof BlockStmt and + exists(DeclStmt ds | ds.getADeclaration() = v1) and + exists(parentScope.(BlockStmt).getIndexOfStmt(childScope)) ) implies exists(BlockStmt bs, DeclStmt v1Stmt, Stmt v2Stmt | - v1 = v1Stmt.getADeclaration() and - getEnclosingStmt(v2).getParentStmt*() = v2Stmt + bs = parentScope and + v2Stmt = childScope and + v1Stmt.getADeclaration() = v1 | bs.getIndexOfStmt(v1Stmt) <= bs.getIndexOfStmt(v2Stmt) ) - ) -} - -/** - * Gets the enclosing statement of the given variable, if any. - */ -private Stmt getEnclosingStmt(LocalScopeVariable v) { - result.(DeclStmt).getADeclaration() = v - or - exists(ConditionDeclExpr cde | - cde.getVariable() = v and - result = cde.getEnclosingStmt() - ) - or - exists(CatchBlock cb | - cb.getParameter() = v and - result = cb.getEnclosingStmt() - ) + ) and + inSameTranslationUnitLate(v1.getFile(), v2.getFile()) and + not (v1.isMember() or v2.isMember()) } /** Holds if `v2` strictly (`v2` is in an inner scope compared to `v1`) hides `v1`. */ From 47b3fb272f27f2fd7f06ab09d0c1195a7d06a16d Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 9 Dec 2024 12:15:50 +0000 Subject: [PATCH 086/370] Scope: refactor hides calculation to expose pairs of variables Behaviour preserving refactor to allow future filtering of invalid pairs of variables during the traversal algorithm. For example, whether a variable declared within a lambda variable hides an outer scope variable depends on the type and nature of the variable. By exposing pairs of candidate variables, we can more easily filter on these conditions. --- cpp/common/src/codingstandards/cpp/Scope.qll | 54 ++++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/Scope.qll b/cpp/common/src/codingstandards/cpp/Scope.qll index c716896356..6ca3fc8657 100644 --- a/cpp/common/src/codingstandards/cpp/Scope.qll +++ b/cpp/common/src/codingstandards/cpp/Scope.qll @@ -78,6 +78,14 @@ class Scope extends Element { UserVariable getAVariable() { Internal::getParentScope(result) = this } + /** + * Gets the `Variable` with the given `name` that is declared in this scope. + */ + UserVariable getVariable(string name) { + result = getAVariable() and + result.getName() = name + } + int getNumberOfVariables() { result = count(getAVariable()) } Scope getAnAncestor() { result = this.getStrictParent+() } @@ -152,9 +160,9 @@ class Scope extends Element { } /** - * Gets a variable with `name` which is hidden in at least one nested scope. + * Gets a variable with `name` which is potentially hidden in at least one nested scope. */ - UserVariable getAHiddenVariable(string name) { + private UserVariable getAPotentiallyHiddenVariable(string name) { result = getAVariable() and result.getName() = name and isDeclaredNameHiddenByChild(name) @@ -163,34 +171,43 @@ class Scope extends Element { /** * Holds if `name` is declared above this scope and hidden by this or a nested scope. */ - private predicate isNameDeclaredAboveHiddenByThisOrNested(string name) { - ( - this.getStrictParent().isDeclaredNameHiddenByChild(name) or - this.getStrictParent().isNameDeclaredAboveHiddenByThisOrNested(name) + UserVariable getAVariableHiddenByThisOrNestedScope(string name) { + exists(Scope parent | parent = this.getStrictParent() | + result = parent.getAPotentiallyHiddenVariable(name) or + result = parent.getAVariableHiddenByThisOrNestedScope(name) ) and isNameDeclaredInThisOrNestedScope(name) } /** - * Gets a variable with `name` which is declared in a scope above this one, and hidden by a variable in this or a - * nested scope. + * Holds if `hiddenVariable` and `hidingVariable` are a candidate hiding pair at this scope. */ - UserVariable getAHidingVariable(string name) { - isNameDeclaredAboveHiddenByThisOrNested(name) and + private predicate hidesCandidate( + UserVariable hiddenVariable, UserVariable hidingVariable, string name + ) { ( // Declared in this scope - getAVariable().getName() = name and - result = getAVariable() and - result.getName() = name + hidingVariable = getVariable(name) and + hiddenVariable = getAVariableHiddenByThisOrNestedScope(name) or // Declared in a child scope exists(Scope child | getAChildScope() = child and - child.isNameDeclaredInThisOrNestedScope(name) and - result = child.getAHidingVariable(name) + child.hidesCandidate(hiddenVariable, hidingVariable, name) ) ) } + + /** + * Holds if `hiddenVariable` is declared in this scope and hidden by `hidingVariable`. + */ + predicate hides(UserVariable hiddenVariable, UserVariable hidingVariable, Scope childScope) { + exists(string name | + hiddenVariable = getAPotentiallyHiddenVariable(name) and + childScope = getAChildScope() and + childScope.hidesCandidate(hiddenVariable, hidingVariable, name) + ) + } } class GeneratedBlockStmt extends BlockStmt { @@ -247,12 +264,7 @@ class TranslationUnit extends SourceFile { /** Holds if `v2` strictly (`v2` is in an inner scope compared to `v1`) hides `v1`. */ predicate hides_candidateStrict(UserVariable v1, UserVariable v2) { - exists(Scope parentScope, Scope childScope, string name | - v1 = parentScope.getAHiddenVariable(name) and - childScope = parentScope.getAChildScope() and - v2 = childScope.getAHidingVariable(name) and - not v1 = v2 - | + exists(Scope parentScope, Scope childScope | parentScope.hides(v1, v2, childScope) | // If v1 is a local variable defined in a `DeclStmt` ensure that it is declared before `v2`, // otherwise it would not be hidden ( From 9b7e1299fc91d9845f5e9250d33102b6fb627755 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 9 Dec 2024 12:27:50 +0000 Subject: [PATCH 087/370] Scope: Special case lambda expressions Lambda expressions have special visibility rules that affect identifier hiding, which we incorporate into the Scope hiding calculations. Note: Lambda expressions are not currently tied into the parent scope hierarchy, so this change doesn't affect calculations until getParentScope(Element e) is extended to support them. --- cpp/common/src/codingstandards/cpp/Scope.qll | 59 ++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/cpp/common/src/codingstandards/cpp/Scope.qll b/cpp/common/src/codingstandards/cpp/Scope.qll index 6ca3fc8657..c705137d8c 100644 --- a/cpp/common/src/codingstandards/cpp/Scope.qll +++ b/cpp/common/src/codingstandards/cpp/Scope.qll @@ -3,6 +3,19 @@ */ import cpp +import codingstandards.cpp.ConstHelpers + +/** + * a `Variable` that is nonvolatile and const + * and of type `IntegralOrEnumType` + */ +class NonVolatileConstIntegralOrEnumVariable extends Variable { + NonVolatileConstIntegralOrEnumVariable() { + not this.isVolatile() and + this.isConst() and + this.getUnspecifiedType() instanceof IntegralOrEnumType + } +} /** * Internal module, exposed for testing. @@ -210,6 +223,52 @@ class Scope extends Element { } } +/** + * A scope representing the generated `operator()` of a lambda function. + */ +class LambdaScope extends Scope { + Closure closure; + + LambdaScope() { this = closure.getLambdaFunction() } + + override UserVariable getAVariableHiddenByThisOrNestedScope(string name) { + // Handle special cases for lambdas + exists(UserVariable hiddenVariable, LambdaExpression lambdaExpr | + // Find the variable that is potentially hidden inside the lambda + hiddenVariable = super.getAVariableHiddenByThisOrNestedScope(name) and + result = hiddenVariable and + lambdaExpr = closure.getLambdaExpression() + | + // A definition can be hidden if it is in scope and it is captured by the lambda, + exists(LambdaCapture cap | + lambdaExpr.getACapture() = cap and + // The outer declaration is captured by the lambda + hiddenVariable.getAnAccess() = cap.getInitializer() + ) + or + // it is is non-local, + hiddenVariable instanceof GlobalVariable + or + // it has static or thread local storage duration, + (hiddenVariable.isThreadLocal() or hiddenVariable.isStatic()) + or + //it is a reference that has been initialized with a constant expression. + hiddenVariable.getType().stripTopLevelSpecifiers() instanceof ReferenceType and + hiddenVariable.getInitializer().getExpr() instanceof Literal + or + // //it const non-volatile integral or enumeration type and has been initialized with a constant expression + hiddenVariable instanceof NonVolatileConstIntegralOrEnumVariable and + hiddenVariable.getInitializer().getExpr() instanceof Literal + or + //it is constexpr and has no mutable members + hiddenVariable.isConstexpr() and + not exists(Class c | + c = hiddenVariable.getType() and not c.getAMember() instanceof MutableVariable + ) + ) + } +} + class GeneratedBlockStmt extends BlockStmt { GeneratedBlockStmt() { this.getLocation() instanceof UnknownLocation } } From 117d0fba033e58ac03d7903ada230e2a09114972 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 9 Dec 2024 12:30:30 +0000 Subject: [PATCH 088/370] Scope: Extend getParentScope for lambda expressions Lambda functions are tied into the parent statement of their declaring lambda expression, which enables Scope's hiding predicates to calculate hiding behaviour for lambda expressions. --- cpp/common/src/codingstandards/cpp/Scope.qll | 11 +++++++++++ .../codingstandards/cpp/scope/ParentScope.expected | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/Scope.qll b/cpp/common/src/codingstandards/cpp/Scope.qll index c705137d8c..5438c17133 100644 --- a/cpp/common/src/codingstandards/cpp/Scope.qll +++ b/cpp/common/src/codingstandards/cpp/Scope.qll @@ -57,11 +57,22 @@ module Internal { // A catch-block `Handler`, whose parent is the `TryStmt` e.(Handler).getParent() = result or + // The parent scope of a lambda is the scope in which the lambda expression is defined. + // + // Lambda functions are defined in a generated `Closure` class, as the `operator()` function. We choose the + // enclosing statement of the lambda expression as the parent scope of the lambda function. This is so we can + // determine the order of definition if a variable is defined in the same scope as the lambda expression. + exists(Closure lambdaClosure | + lambdaClosure.getLambdaFunction() = e and + lambdaClosure.getLambdaExpression().getEnclosingStmt() = result + ) + or not exists(Loop loop | loop.getAChild() = e) and not exists(IfStmt ifStmt | ifStmt.getThen() = e or ifStmt.getElse() = e) and not exists(SwitchStmt switchStmt | switchStmt.getStmt() = e) and not exists(CatchBlock c | c.getParameter() = e) and not e instanceof Handler and + not exists(Closure lambdaClosure | lambdaClosure.getLambdaFunction() = e) and if exists(e.getParentScope()) then result = e.getParentScope() else ( diff --git a/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected b/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected index e2152773af..90aa3b30c8 100644 --- a/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected +++ b/cpp/common/test/library/codingstandards/cpp/scope/ParentScope.expected @@ -77,7 +77,7 @@ | test.cpp:27:28:27:28 | operator= | file://:0:0:0:0 | decltype([...](...){...}) | | test.cpp:27:29:27:29 | id1 | file://:0:0:0:0 | decltype([...](...){...}) | | test.cpp:27:29:27:31 | id1 | test.cpp:26:15:28:11 | { ... } | -| test.cpp:27:33:27:33 | operator() | file://:0:0:0:0 | decltype([...](...){...}) | +| test.cpp:27:33:27:33 | operator() | test.cpp:27:13:27:53 | declaration | | test.cpp:27:36:27:52 | { ... } | test.cpp:27:33:27:33 | operator() | | test.cpp:27:38:27:50 | declaration | test.cpp:27:36:27:52 | { ... } | | test.cpp:27:42:27:44 | id1 | test.cpp:27:36:27:52 | { ... } | From 411ecde2794bb92bb6981ee6107044d66d5de4ac Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 9 Dec 2024 12:32:08 +0000 Subject: [PATCH 089/370] IdentifierHidden: remove lambda special casing This removes the special handling of lambda expressions, which was causing performance issues. Instead, we rely on the new behviour of the Scope library, which calculates identifier hiding for lambda expressions as part of the main calculation. This has one semantic change - the new code applies `isInSameTranslationUnit`, which reduces false positives where the identifier "hiding" in a lambda occurred with an outer variable in a different translation unit. --- .../identifierhidden/IdentifierHidden.qll | 66 +------------------ 1 file changed, 1 insertion(+), 65 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/rules/identifierhidden/IdentifierHidden.qll b/cpp/common/src/codingstandards/cpp/rules/identifierhidden/IdentifierHidden.qll index 9534c2f78a..39d24299b8 100644 --- a/cpp/common/src/codingstandards/cpp/rules/identifierhidden/IdentifierHidden.qll +++ b/cpp/common/src/codingstandards/cpp/rules/identifierhidden/IdentifierHidden.qll @@ -9,75 +9,11 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import codingstandards.cpp.Scope -import codingstandards.cpp.ConstHelpers abstract class IdentifierHiddenSharedQuery extends Query { } Query getQuery() { result instanceof IdentifierHiddenSharedQuery } -/** - * a `Variable` that is nonvolatile and const - * and of type `IntegralOrEnumType` - */ -class NonVolatileConstIntegralOrEnumVariable extends Variable { - NonVolatileConstIntegralOrEnumVariable() { - not this.isVolatile() and - this.isConst() and - this.getUnspecifiedType() instanceof IntegralOrEnumType - } -} - -/** - * Holds if declaration `innerDecl`, declared in a lambda, hides a declaration `outerDecl` by the lambda. - */ -predicate hiddenInLambda(UserVariable outerDecl, UserVariable innerDecl) { - exists( - Scope innerScope, LambdaExpression lambdaExpr, Scope lambdaExprScope, Scope outerScope, - Closure lambdaClosure - | - // The variable `innerDecl` is declared inside of the lambda. - innerScope.getADeclaration() = innerDecl and - // Because a lambda is compiled down to a closure, we need to use the closure to determine if the declaration - // is part of the lambda. - innerScope.getAnAncestor() = lambdaClosure and - // Next we determine the scope of the lambda expression to determine if `outerDecl` is visible in the scope of the lambda. - lambdaClosure.getLambdaExpression() = lambdaExpr and - lambdaExprScope.getAnExpr() = lambdaExpr and - outerScope.getADeclaration() = outerDecl and - lambdaExprScope.getStrictParent*() = outerScope and - ( - // A definition can be hidden if it is in scope and it is captured by the lambda, - exists(LambdaCapture cap | - lambdaExpr.getACapture() = cap and - // The outer declaration is captured by the lambda - outerDecl.getAnAccess() = cap.getInitializer() - ) - or - // it is is non-local, - outerDecl instanceof GlobalVariable - or - // it has static or thread local storage duration, - (outerDecl.isThreadLocal() or outerDecl.isStatic()) - or - //it is a reference that has been initialized with a constant expression. - outerDecl.getType().stripTopLevelSpecifiers() instanceof ReferenceType and - outerDecl.getInitializer().getExpr() instanceof Literal - or - // //it const non-volatile integral or enumeration type and has been initialized with a constant expression - outerDecl instanceof NonVolatileConstIntegralOrEnumVariable and - outerDecl.getInitializer().getExpr() instanceof Literal - or - //it is constexpr and has no mutable members - outerDecl.isConstexpr() and - not exists(Class c | - c = outerDecl.getType() and not c.getAMember() instanceof MutableVariable - ) - ) and - // Finally, the variables must have the same names. - innerDecl.getName() = outerDecl.getName() - ) -} - query predicate problems( UserVariable innerDecl, string message, UserVariable outerDecl, string varName ) { @@ -86,7 +22,7 @@ query predicate problems( //ignore template variables for this rule not outerDecl instanceof TemplateVariable and not innerDecl instanceof TemplateVariable and - (hidesStrict(outerDecl, innerDecl) or hiddenInLambda(outerDecl, innerDecl)) and + hidesStrict(outerDecl, innerDecl) and not excludedViaNestedNamespaces(outerDecl, innerDecl) and varName = outerDecl.getName() and message = "Variable is hiding variable $@." From 52e1bc142013d35d1ebb6050111b7939dc1f25cb Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 9 Dec 2024 12:54:54 +0000 Subject: [PATCH 090/370] IdentifierHiding - Add change note --- change_notes/2024-12-08-identifier-hiding.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 change_notes/2024-12-08-identifier-hiding.md diff --git a/change_notes/2024-12-08-identifier-hiding.md b/change_notes/2024-12-08-identifier-hiding.md new file mode 100644 index 0000000000..0600c9e6ee --- /dev/null +++ b/change_notes/2024-12-08-identifier-hiding.md @@ -0,0 +1,4 @@ + - `A2-10-1` - `IdentifierHiding.ql`: + - Improved evaluation performance. + - Addressed false negatives where nested loops used the same variable name. + - Exclude cases where a variable declared in a lambda expression shadowed a globa or namespace variable that did not appear in the same translation unit. From cf315bad52bb20208ab84809f90310e3875bb7b3 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 9 Dec 2024 12:57:12 +0000 Subject: [PATCH 091/370] Add extra change note entry --- change_notes/2024-12-08-identifier-hiding.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/change_notes/2024-12-08-identifier-hiding.md b/change_notes/2024-12-08-identifier-hiding.md index 0600c9e6ee..c983f5390a 100644 --- a/change_notes/2024-12-08-identifier-hiding.md +++ b/change_notes/2024-12-08-identifier-hiding.md @@ -2,3 +2,6 @@ - Improved evaluation performance. - Addressed false negatives where nested loops used the same variable name. - Exclude cases where a variable declared in a lambda expression shadowed a globa or namespace variable that did not appear in the same translation unit. + - `RULE-5-3` - `IdentifierHidingC.ql`: + - Improved evaluation performance. + - Addressed false negatives where nested loops used the same variable name. \ No newline at end of file From c56e1ce54401c05d5f27c9c86a843625f6f6b37c Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 9 Dec 2024 23:34:03 +0000 Subject: [PATCH 092/370] TypographicallyDifferent: Update after changes to Scope Scope no longer provides a suitable predicate for determining variables in nested scopes. Instead, first determine the set of conflicting names, then identify a set of variables which are conflicting, and are hidden within a nested scope. --- ...entifiersNotTypographicallyUnambiguous.qll | 47 ++++++++++++++++--- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/rules/differentidentifiersnottypographicallyunambiguous/DifferentIdentifiersNotTypographicallyUnambiguous.qll b/cpp/common/src/codingstandards/cpp/rules/differentidentifiersnottypographicallyunambiguous/DifferentIdentifiersNotTypographicallyUnambiguous.qll index 87a4580ab3..5c7475883e 100644 --- a/cpp/common/src/codingstandards/cpp/rules/differentidentifiersnottypographicallyunambiguous/DifferentIdentifiersNotTypographicallyUnambiguous.qll +++ b/cpp/common/src/codingstandards/cpp/rules/differentidentifiersnottypographicallyunambiguous/DifferentIdentifiersNotTypographicallyUnambiguous.qll @@ -46,16 +46,32 @@ string step1(string s) { string step2(string s) { s = "m_" and result = "rn" } -predicate violation(UserVariable v1, UserVariable v2) { - v2 = getPotentialScopeOfVariable(v1) and +class VariableName extends string { + VariableName() { exists(UserVariable uv | uv.getName() = this) } + + string getCanon() { + result = + this.toLowerCase() + .replaceAll("_", "") + .regexpReplaceAll("[il]", "1") + .replaceAll("s", "5") + .replaceAll("z", "2") + .replaceAll("b", "8") + .replaceAll("h", "n") + .replaceAll("m", "rn") + .replaceAll("o", "0") + } +} + +predicate isConflictingName(VariableName name1, VariableName name2) { exists(string s1, string s2 | // over-approximate a match, because it is cheaper to compute - getCanon(v1) = getCanon(v2) and - v1 != v2 and - not v1.getName() = v2.getName() and + name1.getCanon() = name2.getCanon() and + // Exclude identical names + not name1 = name2 and // expand 'm' to 'm_' to match either 'm_' or 'rn' - s1 = v1.getName().replaceAll("_", "").replaceAll("m", "m_") and - s2 = v2.getName().replaceAll("_", "").replaceAll("m", "m_") and + s1 = name1.replaceAll("_", "").replaceAll("m", "m_") and + s2 = name2.replaceAll("_", "").replaceAll("m", "m_") and // at this point the strings must have equal length, the substitutions do not expand nor contract the string s1.length() = s2.length() and forall(int i | i in [0 .. s1.length() - 1] | @@ -87,6 +103,23 @@ predicate violation(UserVariable v1, UserVariable v2) { ) } +predicate violation(UserVariable v1, UserVariable v2) { + exists(string name1, string name2 | + isConflictingName(name1, name2) and + exists(Scope parentScope, Scope childScope | + parentScope.getVariable(name1) = v1 and + childScope.getVariable(name2) = v2 + | + childScope.getStrictParent+() = parentScope + or + // Disambiguate names in the same scope by name order + childScope = parentScope and + name1 < name2 + ) and + inSameTranslationUnitLate(v1.getFile(), v2.getFile()) + ) +} + query predicate problems( UserVariable v, string message, UserVariable v1, string v1Description, UserVariable v2, string v2Description From 125650c582ec38fb4785940444fdf6fe927c4efd Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 9 Dec 2024 16:37:57 -0800 Subject: [PATCH 093/370] Address review feedback --- c/misra/src/codeql-suites/misra-c-default.qls | 1 + c/misra/src/codeql-suites/misra-c-strict.qls | 8 ++++ .../RULE-2-8/UnusedObjectDefinition.expected | 2 + c/misra/test/rules/RULE-2-8/test.c | 18 +++++++++ .../cpp/deadcode/UnusedObjects.qll | 10 +++-- .../cpp/deadcode/UnusedVariables.qll | 39 ++++++++++++++----- docs/development_handbook.md | 2 + docs/user_manual.md | 13 ++++++- rule_packages/c/DeadCode2.json | 5 ++- 9 files changed, 82 insertions(+), 16 deletions(-) create mode 100644 c/misra/src/codeql-suites/misra-c-strict.qls diff --git a/c/misra/src/codeql-suites/misra-c-default.qls b/c/misra/src/codeql-suites/misra-c-default.qls index 343379a2b3..f72a63ba49 100644 --- a/c/misra/src/codeql-suites/misra-c-default.qls +++ b/c/misra/src/codeql-suites/misra-c-default.qls @@ -7,4 +7,5 @@ - exclude: tags contain: - external/misra/audit + - external/misra/strict - external/misra/default-disabled diff --git a/c/misra/src/codeql-suites/misra-c-strict.qls b/c/misra/src/codeql-suites/misra-c-strict.qls new file mode 100644 index 0000000000..6fb642424c --- /dev/null +++ b/c/misra/src/codeql-suites/misra-c-strict.qls @@ -0,0 +1,8 @@ +- description: MISRA C 2012 (Strict) +- qlpack: codeql/misra-c-coding-standards +- include: + kind: + - problem + - path-problem + tags contain: + - external/misra/strict diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected index fc6f320539..ce7e198122 100644 --- a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected +++ b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected @@ -6,3 +6,5 @@ | test.c:45:9:45:10 | definition of g6 | Unused object definition 'g6'. | test.c:45:9:45:10 | test.c:45:9:45:10 | | | test.c:51:5:51:6 | definition of g7 | Unused object definition 'g7'. | test.c:51:5:51:6 | test.c:51:5:51:6 | | | test.c:64:3:64:18 | ONLY_DEF_VAR(x) | Unused object definition 'l2' from macro '$@'. | test.c:60:1:60:34 | test.c:60:1:60:34 | ONLY_DEF_VAR | +| test.c:117:11:117:13 | definition of g10 | Unused object definition 'g10'. | test.c:117:11:117:13 | test.c:117:11:117:13 | | +| test.c:122:13:122:14 | definition of l2 | Unused object definition 'l2'. | test.c:122:13:122:14 | test.c:122:13:122:14 | | diff --git a/c/misra/test/rules/RULE-2-8/test.c b/c/misra/test/rules/RULE-2-8/test.c index 21a2479163..cffb4f2e33 100644 --- a/c/misra/test/rules/RULE-2-8/test.c +++ b/c/misra/test/rules/RULE-2-8/test.c @@ -111,3 +111,21 @@ void f8() { void f9() { DEF_ATTR_UNUSED_INNER_VAR(); // COMPLIANT } + +// Const variable tests: +const int g9 = 1; // COMPLIANT +const int g10 = 1; // NON-COMPLIANT + +void f10() { + g9; + const int l1 = 1; // COMPLIANT + const int l2 = 1; // NON-COMPLIANT + l1; +} + +// Side effects should not disable this rule: +void f11() { + int l1 = 1; // COMPLIANT + int l2 = l1++; // COMPLIANT + l2; +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll b/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll index 70944dfad4..96dcc8d315 100644 --- a/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll +++ b/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll @@ -1,4 +1,5 @@ import cpp +import codingstandards.cpp.deadcode.UnusedVariables import codingstandards.cpp.alertreporting.HoldsForAllCopies import codingstandards.cpp.alertreporting.DeduplicateMacroResults @@ -15,10 +16,13 @@ import codingstandards.cpp.alertreporting.DeduplicateMacroResults */ class UnusedObjectDefinition extends VariableDeclarationEntry { UnusedObjectDefinition() { + ( + getVariable() instanceof BasePotentiallyUnusedLocalVariable + or + getVariable() instanceof BasePotentiallyUnusedGlobalOrNamespaceVariable + ) and not exists(VariableAccess access | access.getTarget() = getVariable()) and - getVariable().getDefinition() = this and - not this instanceof ParameterDeclarationEntry and - not getVariable() instanceof MemberVariable + getVariable().getDefinition() = this } /* Dead objects with these attributes are reported in the "strict" queries. */ diff --git a/cpp/common/src/codingstandards/cpp/deadcode/UnusedVariables.qll b/cpp/common/src/codingstandards/cpp/deadcode/UnusedVariables.qll index 912d2babcd..b896fb6f9e 100644 --- a/cpp/common/src/codingstandards/cpp/deadcode/UnusedVariables.qll +++ b/cpp/common/src/codingstandards/cpp/deadcode/UnusedVariables.qll @@ -36,11 +36,11 @@ predicate declarationHasSideEffects(Variable v) { v.getType() instanceof TemplateDependentType } -/** A `LocalVariable` which is a candidate for being unused. */ -class PotentiallyUnusedLocalVariable extends LocalVariable { - PotentiallyUnusedLocalVariable() { - // Ignore variables declared in macro expansions - not exists(DeclStmt ds | ds.getADeclaration() = this and ds.isInMacroExpansion()) and +/** + * A `LocalVariable` which is a candidate for being unused, and may or may not be defined in a macro. + */ +class BasePotentiallyUnusedLocalVariable extends LocalVariable { + BasePotentiallyUnusedLocalVariable() { // Ignore variables where initializing the variable has side effects not declarationHasSideEffects(this) and // TODO non POD types with initializers? Also, do something different with templates? exists(Function f | f = getFunction() | @@ -56,6 +56,16 @@ class PotentiallyUnusedLocalVariable extends LocalVariable { } } +/** + * A `LocalVariable` which is a candidate for being unused, and not defined in a macro. + */ +class PotentiallyUnusedLocalVariable extends BasePotentiallyUnusedLocalVariable { + PotentiallyUnusedLocalVariable() { + // Ignore variables declared in macro expansions + not exists(DeclStmt ds | ds.getADeclaration() = this and ds.isInMacroExpansion()) + } +} + /** Holds if `mf` is "defined" in this database. */ predicate isDefined(MemberFunction mf) { exists(MemberFunction definedMemberFunction | @@ -105,13 +115,11 @@ class PotentiallyUnusedMemberVariable extends MemberVariable { } } -/** A `GlobalOrNamespaceVariable` which is potentially unused. */ -class PotentiallyUnusedGlobalOrNamespaceVariable extends GlobalOrNamespaceVariable { - PotentiallyUnusedGlobalOrNamespaceVariable() { +/** A `GlobalOrNamespaceVariable` which is potentially unused and may or may not be defined in a macro */ +class BasePotentiallyUnusedGlobalOrNamespaceVariable extends GlobalOrNamespaceVariable { + BasePotentiallyUnusedGlobalOrNamespaceVariable() { // A non-defined variable may never be used hasDefinition() and - // Not declared in a macro expansion - not isInMacroExpansion() and // No side-effects from declaration not declarationHasSideEffects(this) and // exclude uninstantiated template members @@ -121,6 +129,17 @@ class PotentiallyUnusedGlobalOrNamespaceVariable extends GlobalOrNamespaceVariab } } +/** + * A `GlobalOrNamespaceVariable` which is potentially unused, and is not defined in a macro. +*/ +class PotentiallyUnusedGlobalOrNamespaceVariable extends BasePotentiallyUnusedGlobalOrNamespaceVariable +{ + PotentiallyUnusedGlobalOrNamespaceVariable() { + // Not declared in a macro expansion + not isInMacroExpansion() + } +} + predicate isUnused(Variable variable) { not exists(variable.getAnAccess()) and variable.getInitializer().fromSource() diff --git a/docs/development_handbook.md b/docs/development_handbook.md index dc50bf59ff..97c615ba2e 100644 --- a/docs/development_handbook.md +++ b/docs/development_handbook.md @@ -51,6 +51,8 @@ Each coding standard consists of a list of "guidelines", however not all the gui For some of the rules which are not amenable to static analysis, we may opt to provide a query which aids with "auditing" the rules. For example, AUTOSAR includes a rule (A10-0-1) "Public inheritance shall be used to implement 'is-a' relationship.". This is not directly amenable to static analysis, because it requires external context around the concept being modeled. However, we can provide an "audit" rule which reports all the public and private inheritance relationships in the program, so they can be manually verified. +For other rules, there may be means of indicating that a contravention is intentional, and where requiring a _devation report_ may be extra burdensome on developers and require double-entry. These results should be reported under a "strict" query. For instance, `RULE-2-8` "A project should not contain unused object definitions," where adding `__attribute__((unused))` may be preferable in order to suppress compiler warnings (which _deviation reports_ do not do) and are highly indicative of an intentional contravention by a developer. + For each rule which will be implemented with a query we have assigned a "rule package". Rule packages represent sets of rules, possibly across standards, that will be implemented together. Examples of rule packages include "Exceptions", "Naming", "Pointers" and so forth. By implementing queries for related rules together, we intend to maximize the amount of code shared between queries, and to ensure query developers can gain a deep understanding of that specific topic. The canonical list of rules, with implementation categorization and assigned rule packages, are stored in this repository in the `rules.csv` file. diff --git a/docs/user_manual.md b/docs/user_manual.md index db0f836339..1ddf68870e 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -71,6 +71,7 @@ For each rule we therefore identify whether it is supportable or not. Furthermor - **Automated** - the queries for the rule find contraventions directly. - **Audit only** - the queries for the rule does not find contraventions directly, but instead report a list of _candidates_ that can be used as input into a manual audit. For example, `A10-0-1` (_Public inheritance shall be used to implement 'is-a' relationship_) is not directly amenable to static analysis, but CodeQL can be used to produce a list of all the locations that use public inheritance so they can be manually reviewed. +- **Strict only** - the queries for the rule find contraventions directly, but find results which are strongly indicated to be intentional, and where adding a _deviation report_ may be extra burden on developers. For example, in `RULE-2-8` (_A project should not contain unused object definitions_), declaring objects with `__attribute__((unused))` may be preferable to a _deviation report_, which will not suppress relevant compiler warnings, and therefore would otherwise require developer double-entry. Each supported rule is implemented as one or more CodeQL queries, with each query covering an aspect of the rule. In many coding standards, the rules cover non-trivial semantic properties of the codebase under analysis. @@ -214,14 +215,22 @@ The following flags may be passed to the `database analyze` command to adjust th The output of this command will be a [SARIF file](https://sarifweb.azurewebsites.net/) called `.sarif`. -#### Running the analysis for audit level queries +#### Running the analysis for strict and/or audit level queries -Optionally, you may want to run the "audit" level queries. These queries produce lists of results that do not directly highlight contraventions of the rule. Instead, they identify locations in the code that can be manually audited to verify the absence of problems for that particular rule. +Optionally, you may want to run the "strict" or "audit" level queries. + +Audit queries produce lists of results that do not directly highlight contraventions of the rule. Instead, they identify locations in the code that can be manually audited to verify the absence of problems for that particular rule. ```bash codeql database analyze --format=sarifv2.1.0 --output=.sarif path/to/ path/to/codeql-coding-standards/cpp//src/codeql-suites/-audit.qls... ``` +Strict queries identify contraventions in the code that strongly suggest they are deliberate, and where adding an explicit _deviation report_ may be extra burden on developers. + +```bash +codeql database analyze --format=sarifv2.1.0 --output=.sarif path/to/ path/to/codeql-coding-standards/cpp//src/codeql-suites/-strict.qls... +``` + For each Coding Standard you want to run, add a trailing entry in the following format: `path/to/codeql-coding-standards/cpp//src/codeql-suites/-default.qls`. #### Producing an analysis report diff --git a/rule_packages/c/DeadCode2.json b/rule_packages/c/DeadCode2.json index da114a2349..b897f595e6 100644 --- a/rule_packages/c/DeadCode2.json +++ b/rule_packages/c/DeadCode2.json @@ -60,7 +60,10 @@ ] } ], - "title": "A project should not contain unused object definitions" + "title": "A project should not contain unused object definitions", + "implementation_scope": { + "description": "Unused object definitions marked with `__attribute__((unused))` (and `used`, `maybe_used`, `cleanup`) are separately reported under the 'strict' query suite. This is because these attributes strongly indicate the contravention is intentional, and a deviation report alone will not suppress compiler warnings." + } } } } \ No newline at end of file From 003feefeafe2d02809060551c07aa1aa5d5a25ca Mon Sep 17 00:00:00 2001 From: Fernando Jose Date: Tue, 10 Dec 2024 11:50:33 +0900 Subject: [PATCH 094/370] Exclude rvalue references from const in AUTOSAR rule 7-1-1. --- .../A7-1-1/DeclarationUnmodifiedObjectMissingConstSpecifier.ql | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/autosar/src/rules/A7-1-1/DeclarationUnmodifiedObjectMissingConstSpecifier.ql b/cpp/autosar/src/rules/A7-1-1/DeclarationUnmodifiedObjectMissingConstSpecifier.ql index ff07bcbdb2..b961acce64 100644 --- a/cpp/autosar/src/rules/A7-1-1/DeclarationUnmodifiedObjectMissingConstSpecifier.ql +++ b/cpp/autosar/src/rules/A7-1-1/DeclarationUnmodifiedObjectMissingConstSpecifier.ql @@ -38,6 +38,7 @@ where not exists(LambdaExpression lc | lc.getACapture().getField() = v) and not v.isFromUninstantiatedTemplate(_) and not v.isCompilerGenerated() and + not v.getType() instanceof RValueReferenceType and //if the instantiation is not constexpr but the template is, still exclude it as a candidate not exists(TemplateVariable b | b.getAnInstantiation() = v and b.isConstexpr()) select v, "Non-constant variable " + v.getName() + cond + " and is not modified." From 18b92ec47d9121d990a12c7b59b8f956b3a59fdc Mon Sep 17 00:00:00 2001 From: Fernando Jose Date: Tue, 10 Dec 2024 12:42:56 +0900 Subject: [PATCH 095/370] Add change note. --- change_notes/2024-12-10-udpate-a7-1-1.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 change_notes/2024-12-10-udpate-a7-1-1.md diff --git a/change_notes/2024-12-10-udpate-a7-1-1.md b/change_notes/2024-12-10-udpate-a7-1-1.md new file mode 100644 index 0000000000..6efa1ae01f --- /dev/null +++ b/change_notes/2024-12-10-udpate-a7-1-1.md @@ -0,0 +1,2 @@ +- `A7-1-1` - `DeclarationUnmodifiedObjectMissingConstSpecifier.ql`: + - Exclude rvalue references. From 4d31f5f11cd33031a87d1c1ff070c791f0049529 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Tue, 10 Dec 2024 01:16:51 -0500 Subject: [PATCH 096/370] Update change_notes/2024-12-08-identifier-hiding.md Co-authored-by: Fernando Jose --- change_notes/2024-12-08-identifier-hiding.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change_notes/2024-12-08-identifier-hiding.md b/change_notes/2024-12-08-identifier-hiding.md index c983f5390a..b769b16e57 100644 --- a/change_notes/2024-12-08-identifier-hiding.md +++ b/change_notes/2024-12-08-identifier-hiding.md @@ -1,7 +1,7 @@ - `A2-10-1` - `IdentifierHiding.ql`: - Improved evaluation performance. - Addressed false negatives where nested loops used the same variable name. - - Exclude cases where a variable declared in a lambda expression shadowed a globa or namespace variable that did not appear in the same translation unit. + - Exclude cases where a variable declared in a lambda expression shadowed a global or namespace variable that did not appear in the same translation unit. - `RULE-5-3` - `IdentifierHidingC.ql`: - Improved evaluation performance. - Addressed false negatives where nested loops used the same variable name. \ No newline at end of file From 0673c778943ceda34d7156bf5108f6b9d3a87960 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Fri, 29 Nov 2024 15:20:54 +0000 Subject: [PATCH 097/370] A15-4-4: Support deviation on the function declaration --- cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql | 2 +- cpp/autosar/test/rules/A15-4-4/test.cpp | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql b/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql index 7701a8a1ea..bbdb8d93f3 100644 --- a/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql +++ b/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql @@ -21,7 +21,7 @@ import codingstandards.cpp.exceptions.ExceptionFlow from Function f where - not isExcluded(f, Exceptions1Package::missingNoExceptQuery()) and + not isExcluded(f.getADeclarationEntry(), Exceptions1Package::missingNoExceptQuery()) and // No thrown exceptions not exists(getAFunctionThrownType(f, _)) and // But not marked noexcept(true) diff --git a/cpp/autosar/test/rules/A15-4-4/test.cpp b/cpp/autosar/test/rules/A15-4-4/test.cpp index 1f9d0d5a85..faae76ca8e 100644 --- a/cpp/autosar/test/rules/A15-4-4/test.cpp +++ b/cpp/autosar/test/rules/A15-4-4/test.cpp @@ -56,4 +56,12 @@ std::string test_fp_reported_in_424( s3.append(s1.c_str(), s1.size()); s3.append(s2.c_str(), s2.size()); return s3; -} \ No newline at end of file +} + +void test_no_except_deviated_decl(); // a-15-4-4-deviation + +void test_no_except_deviated_decl() {} + +void test_no_except_deviated_defn(); + +void test_no_except_deviated_defn() {} // a-15-4-4-deviation \ No newline at end of file From 5e753af5dc4e815a3de2046dc94b1f08a42a5824 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 10 Dec 2024 13:44:36 +0000 Subject: [PATCH 098/370] Add change note --- change_notes/2024-12-10-a15-4-4-deviations.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 change_notes/2024-12-10-a15-4-4-deviations.md diff --git a/change_notes/2024-12-10-a15-4-4-deviations.md b/change_notes/2024-12-10-a15-4-4-deviations.md new file mode 100644 index 0000000000..4a595e3e00 --- /dev/null +++ b/change_notes/2024-12-10-a15-4-4-deviations.md @@ -0,0 +1,2 @@ + - `A15-4-4` - `MissingNoExcept.ql`: + - Enable deviations on either declarations or definitions. \ No newline at end of file From 9492933c0ac32ac1a98b2bcb51e8f985f5ce5d3b Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 10 Dec 2024 08:25:01 -0800 Subject: [PATCH 099/370] Format --- cpp/common/src/codingstandards/cpp/deadcode/UnusedVariables.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/deadcode/UnusedVariables.qll b/cpp/common/src/codingstandards/cpp/deadcode/UnusedVariables.qll index b896fb6f9e..a7accd5252 100644 --- a/cpp/common/src/codingstandards/cpp/deadcode/UnusedVariables.qll +++ b/cpp/common/src/codingstandards/cpp/deadcode/UnusedVariables.qll @@ -131,7 +131,7 @@ class BasePotentiallyUnusedGlobalOrNamespaceVariable extends GlobalOrNamespaceVa /** * A `GlobalOrNamespaceVariable` which is potentially unused, and is not defined in a macro. -*/ + */ class PotentiallyUnusedGlobalOrNamespaceVariable extends BasePotentiallyUnusedGlobalOrNamespaceVariable { PotentiallyUnusedGlobalOrNamespaceVariable() { From 8c31c8c296b5992b931fe1cbc8b338b89e8dc048 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 10 Dec 2024 08:26:37 -0800 Subject: [PATCH 100/370] format c --- c/misra/test/rules/RULE-2-8/test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/c/misra/test/rules/RULE-2-8/test.c b/c/misra/test/rules/RULE-2-8/test.c index cffb4f2e33..ef40dfb2a4 100644 --- a/c/misra/test/rules/RULE-2-8/test.c +++ b/c/misra/test/rules/RULE-2-8/test.c @@ -113,7 +113,7 @@ void f9() { } // Const variable tests: -const int g9 = 1; // COMPLIANT +const int g9 = 1; // COMPLIANT const int g10 = 1; // NON-COMPLIANT void f10() { @@ -125,7 +125,7 @@ void f10() { // Side effects should not disable this rule: void f11() { - int l1 = 1; // COMPLIANT + int l1 = 1; // COMPLIANT int l2 = l1++; // COMPLIANT l2; } \ No newline at end of file From 7631a61cdd55ec9b46804941bdd04d65d3a40f38 Mon Sep 17 00:00:00 2001 From: knewbury01 Date: Tue, 10 Dec 2024 21:27:28 +0000 Subject: [PATCH 101/370] Bump version to 2.40.0-dev --- c/cert/src/qlpack.yml | 2 +- c/cert/test/qlpack.yml | 2 +- c/common/src/qlpack.yml | 2 +- c/common/test/qlpack.yml | 2 +- c/misra/src/qlpack.yml | 2 +- c/misra/test/qlpack.yml | 2 +- cpp/autosar/src/qlpack.yml | 2 +- cpp/autosar/test/qlpack.yml | 2 +- cpp/cert/src/qlpack.yml | 2 +- cpp/cert/test/qlpack.yml | 2 +- cpp/common/src/qlpack.yml | 2 +- cpp/common/test/qlpack.yml | 2 +- cpp/misra/src/qlpack.yml | 2 +- cpp/misra/test/qlpack.yml | 2 +- cpp/report/src/qlpack.yml | 2 +- docs/user_manual.md | 12 ++++++------ 16 files changed, 21 insertions(+), 21 deletions(-) diff --git a/c/cert/src/qlpack.yml b/c/cert/src/qlpack.yml index f7454d1ff0..2778e44435 100644 --- a/c/cert/src/qlpack.yml +++ b/c/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards -version: 2.39.0-dev +version: 2.40.0-dev description: CERT C 2016 suites: codeql-suites license: MIT diff --git a/c/cert/test/qlpack.yml b/c/cert/test/qlpack.yml index a79ef5f692..461ebe9677 100644 --- a/c/cert/test/qlpack.yml +++ b/c/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards-tests -version: 2.39.0-dev +version: 2.40.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/common/src/qlpack.yml b/c/common/src/qlpack.yml index 1930faeeb0..f39f3cb1c4 100644 --- a/c/common/src/qlpack.yml +++ b/c/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards -version: 2.39.0-dev +version: 2.40.0-dev license: MIT dependencies: codeql/common-cpp-coding-standards: '*' diff --git a/c/common/test/qlpack.yml b/c/common/test/qlpack.yml index 41737a34ec..d417a17df2 100644 --- a/c/common/test/qlpack.yml +++ b/c/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards-tests -version: 2.39.0-dev +version: 2.40.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/misra/src/qlpack.yml b/c/misra/src/qlpack.yml index 656394ad1d..9aceed1a49 100644 --- a/c/misra/src/qlpack.yml +++ b/c/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards -version: 2.39.0-dev +version: 2.40.0-dev description: MISRA C 2012 suites: codeql-suites license: MIT diff --git a/c/misra/test/qlpack.yml b/c/misra/test/qlpack.yml index 3acb8455b1..d53bc95f28 100644 --- a/c/misra/test/qlpack.yml +++ b/c/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards-tests -version: 2.39.0-dev +version: 2.40.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/autosar/src/qlpack.yml b/cpp/autosar/src/qlpack.yml index e1843eb2e7..f44ad54c74 100644 --- a/cpp/autosar/src/qlpack.yml +++ b/cpp/autosar/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards -version: 2.39.0-dev +version: 2.40.0-dev description: AUTOSAR C++14 Guidelines R22-11, R21-11, R20-11, R19-11 and R19-03 suites: codeql-suites license: MIT diff --git a/cpp/autosar/test/qlpack.yml b/cpp/autosar/test/qlpack.yml index e7e8d3e2ce..178d8cc314 100644 --- a/cpp/autosar/test/qlpack.yml +++ b/cpp/autosar/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards-tests -version: 2.39.0-dev +version: 2.40.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/cert/src/qlpack.yml b/cpp/cert/src/qlpack.yml index 949087dfd5..735dd9f5b4 100644 --- a/cpp/cert/src/qlpack.yml +++ b/cpp/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards -version: 2.39.0-dev +version: 2.40.0-dev description: CERT C++ 2016 suites: codeql-suites license: MIT diff --git a/cpp/cert/test/qlpack.yml b/cpp/cert/test/qlpack.yml index ba7415c43e..3a6d02e7d4 100644 --- a/cpp/cert/test/qlpack.yml +++ b/cpp/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards-tests -version: 2.39.0-dev +version: 2.40.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/common/src/qlpack.yml b/cpp/common/src/qlpack.yml index 1cfc63d8d9..1ae6dfd997 100644 --- a/cpp/common/src/qlpack.yml +++ b/cpp/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards -version: 2.39.0-dev +version: 2.40.0-dev license: MIT dependencies: codeql/cpp-all: 1.4.2 diff --git a/cpp/common/test/qlpack.yml b/cpp/common/test/qlpack.yml index 3f061a2920..90236b203e 100644 --- a/cpp/common/test/qlpack.yml +++ b/cpp/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards-tests -version: 2.39.0-dev +version: 2.40.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/misra/src/qlpack.yml b/cpp/misra/src/qlpack.yml index 4f94ff4bec..96fc96ce24 100644 --- a/cpp/misra/src/qlpack.yml +++ b/cpp/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards -version: 2.39.0-dev +version: 2.40.0-dev description: MISRA C++ 2023 default-suite: codeql-suites/misra-cpp-default.qls license: MIT diff --git a/cpp/misra/test/qlpack.yml b/cpp/misra/test/qlpack.yml index e79e5934fa..207facda4e 100644 --- a/cpp/misra/test/qlpack.yml +++ b/cpp/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards-tests -version: 2.39.0-dev +version: 2.40.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/report/src/qlpack.yml b/cpp/report/src/qlpack.yml index 73f4cf3276..e569153ae8 100644 --- a/cpp/report/src/qlpack.yml +++ b/cpp/report/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/report-cpp-coding-standards -version: 2.39.0-dev +version: 2.40.0-dev license: MIT dependencies: codeql/cpp-all: 1.4.2 diff --git a/docs/user_manual.md b/docs/user_manual.md index 4c020dc73b..952a9a3c99 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -33,14 +33,14 @@ ## Release information -This user manual documents release `2.39.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). +This user manual documents release `2.40.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). The release page documents the release notes and contains the following artifacts part of the release: - `coding-standards-codeql-packs-2.37.0-dev.zip`: CodeQL packs that can be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `code-scanning-cpp-query-pack-2.39.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `supported_rules_list_2.39.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. -- `supported_rules_list_2.39.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. -- `user_manual_2.39.0-dev.md`: This user manual. +- `code-scanning-cpp-query-pack-2.40.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. +- `supported_rules_list_2.40.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. +- `supported_rules_list_2.40.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. +- `user_manual_2.40.0-dev.md`: This user manual. - `Source Code (zip)`: A zip archive containing the contents of https://github.com/github/codeql-coding-standards - `Source Code (tar.gz)`: A GZip compressed tar archive containing the contents of https://github.com/github/codeql-coding-standards - `checksums.txt`: A text file containing sha256 checksums for the aforementioned artifacts. @@ -573,7 +573,7 @@ This section describes known failure modes for "CodeQL Coding Standards" and des | | Out of space | Less output. Some files may be only be partially analyzed, or not analyzed at all. | Error reported on the command line. | Increase space. If it remains an issue report space consumption issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False positives | More output. Results are reported which are not violations of the guidelines. | All reported results must be reviewed. | Report false positive issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False negatives | Less output. Violations of the guidelines are not reported. | Other validation and verification processes during software development should be used to complement the analysis performed by CodeQL Coding Standards. | Report false negative issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.39.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | +| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.40.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | | | Incorrect deviation record specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation records with a reason. Ensure that all deviation records are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Incorrect deviation permit specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation permits with a reason. Ensure that all deviation permits are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Unapproved use of a deviation record | Less output. Results for guideline violations are not reported. | Validate that the deviation record use is approved by verifying the approved-by attribute of the deviation record specification. | Ensure that each raised deviation record is approved by an independent approver through an auditable process. | From 78ae4ce64cc8b7188234e618aa3ae33fd57d3f30 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 10 Dec 2024 18:03:04 -0800 Subject: [PATCH 102/370] Implement MISRA-C clarifications from amendments3, 4, at TC2. Some amendments were improperly categorized, fixed. Rule 10.1 also had an additional amendment (amdt4 and tc2). --- amendments.csv | 53 ++++++++++++++++--------------- rule_packages/c/Banned.json | 2 +- rule_packages/c/Contracts6.json | 2 +- rule_packages/c/Pointers1.json | 2 +- rule_packages/c/SideEffects1.json | 2 +- 5 files changed, 31 insertions(+), 30 deletions(-) diff --git a/amendments.csv b/amendments.csv index ce285a29ba..2d7254efec 100644 --- a/amendments.csv +++ b/amendments.csv @@ -9,41 +9,42 @@ c,MISRA-C-2012,Amendment3,RULE-10-4,Yes,Refine,No,Import c,MISRA-C-2012,Amendment3,RULE-10-5,Yes,Expand,No,Easy c,MISRA-C-2012,Amendment3,RULE-10-7,Yes,Refine,No,Import c,MISRA-C-2012,Amendment3,RULE-10-8,Yes,Refine,No,Import -c,MISRA-C-2012,Amendment3,RULE-21-11,Yes,Clarification,No,Import +c,MISRA-C-2012,Amendment3,RULE-21-11,Yes,Clarification,Yes,Import c,MISRA-C-2012,Amendment3,RULE-21-12,Yes,Replace,No,Easy c,MISRA-C-2012,Amendment4,RULE-11-3,Yes,Expand,No,Easy c,MISRA-C-2012,Amendment4,RULE-11-8,Yes,Expand,No,Easy c,MISRA-C-2012,Amendment4,RULE-13-2,Yes,Expand,No,Very Hard c,MISRA-C-2012,Amendment4,RULE-18-6,Yes,Expand,No,Medium c,MISRA-C-2012,Amendment4,RULE-18-8,Yes,Split,Yes,Easy -c,MISRA-C-2012,Corrigendum2,RULE-2-2,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-2-7,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-3-1,Yes,Refine,No,Easy -c,MISRA-C-2012,Corrigendum2,RULE-8-6,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-8-9,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-9-4,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-10-1,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-18-3,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-1-4,Yes,Replace,No,Easy -c,MISRA-C-2012,Corrigendum2,RULE-9-1,Yes,Refine,No,Easy -c,MISRA-C-2012,Corrigendum2,RULE-9-2,Yes,Refine,No,Import -c,MISRA-C-2012,Corrigendum2,DIR-4-10,Yes,Clarification,No,Import +c,MISRA-C-2012,Amendment4,RULE-2-2,Yes,Clarification,Yes,Import +c,MISRA-C-2012,Amendment4,RULE-2-7,Yes,Clarification,Yes,Import +c,MISRA-C-2012,Amendment4,RULE-3-1,Yes,Refine,No,Easy +c,MISRA-C-2012,Amendment4,RULE-8-6,Yes,Clarification,Yes,Import +c,MISRA-C-2012,Amendment4,RULE-8-9,Yes,Clarification,Yes,Import +c,MISRA-C-2012,Amendment4,RULE-9-4,Yes,Clarification,Yes,Import +c,MISRA-C-2012,Amendment4,RULE-10-1,Yes,Clarification,Yes,Import +c,MISRA-C-2012,Amendment4,RULE-18-3,Yes,Clarification,Yes,Import +c,MISRA-C-2012,Amendment4,RULE-1-4,Yes,Replace,No,Easy +c,MISRA-C-2012,Amendment4,RULE-9-1,Yes,Refine,No,Easy +c,MISRA-C-2012,Amendment4,RULE-9-2,Yes,Refine,No,Import +c,MISRA-C-2012,Corrigendum2,DIR-4-10,Yes,Clarification,Yes,Import c,MISRA-C-2012,Corrigendum2,RULE-7-4,Yes,Refine,No,Easy -c,MISRA-C-2012,Corrigendum2,RULE-8-2,Yes,Clarification,No,Import +c,MISRA-C-2012,Corrigendum2,RULE-8-2,Yes,Clarification,Yes,Import c,MISRA-C-2012,Corrigendum2,RULE-8-3,Yes,Refine,No,Easy -c,MISRA-C-2012,Corrigendum2,RULE-8-7,Yes,Clarification,No,Import +c,MISRA-C-2012,Corrigendum2,RULE-8-7,Yes,Clarification,Yes,Import +c,MISRA-C-2012,Corrigendum2,RULE-10-1,Yes,Clarification,Yes,Import c,MISRA-C-2012,Corrigendum2,RULE-10-2,Yes,Refine,No,Easy -c,MISRA-C-2012,Corrigendum2,RULE-10-3,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-11-3,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-11-6,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-13-2,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-13-6,Yes,Clarification,No,Import +c,MISRA-C-2012,Corrigendum2,RULE-10-3,Yes,Clarification,Yes,Import +c,MISRA-C-2012,Corrigendum2,RULE-11-3,Yes,Clarification,Yes,Import +c,MISRA-C-2012,Corrigendum2,RULE-11-6,Yes,Clarification,Yes,Import +c,MISRA-C-2012,Corrigendum2,RULE-13-2,Yes,Clarification,Yes,Import +c,MISRA-C-2012,Corrigendum2,RULE-13-6,Yes,Clarification,Yes,Import c,MISRA-C-2012,Corrigendum2,RULE-14-3,Yes,Refine,No,Easy -c,MISRA-C-2012,Corrigendum2,RULE-15-7,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-17-4,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-17-5,Yes,Clarification,No,Import +c,MISRA-C-2012,Corrigendum2,RULE-15-7,Yes,Clarification,Yes,Import +c,MISRA-C-2012,Corrigendum2,RULE-17-4,Yes,Clarification,Yes,Import +c,MISRA-C-2012,Corrigendum2,RULE-17-5,Yes,Clarification,Yes,Import c,MISRA-C-2012,Corrigendum2,RULE-18-1,Yes,Refine,No,Easy -c,MISRA-C-2012,Corrigendum2,RULE-20-14,No,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-21-19,Yes,Clarification,No,Import +c,MISRA-C-2012,Corrigendum2,RULE-20-14,No,Clarification,Yes,Import +c,MISRA-C-2012,Corrigendum2,RULE-21-19,Yes,Clarification,Yes,Import c,MISRA-C-2012,Corrigendum2,RULE-21-20,Yes,Refine,No,Easy -c,MISRA-C-2012,Corrigendum2,RULE-22-9,Yes,Clarification,No,Import \ No newline at end of file +c,MISRA-C-2012,Corrigendum2,RULE-22-9,Yes,Clarification,Yes,Import \ No newline at end of file diff --git a/rule_packages/c/Banned.json b/rule_packages/c/Banned.json index d3825f8f30..4decbae6f2 100644 --- a/rule_packages/c/Banned.json +++ b/rule_packages/c/Banned.json @@ -104,7 +104,7 @@ }, "RULE-21-11": { "properties": { - "obligation": "required" + "obligation": "advisory" }, "queries": [ { diff --git a/rule_packages/c/Contracts6.json b/rule_packages/c/Contracts6.json index 4dbae7e121..c46ef2f710 100644 --- a/rule_packages/c/Contracts6.json +++ b/rule_packages/c/Contracts6.json @@ -26,7 +26,7 @@ "MISRA-C-2012": { "RULE-17-5": { "properties": { - "obligation": "advisory" + "obligation": "required" }, "queries": [ { diff --git a/rule_packages/c/Pointers1.json b/rule_packages/c/Pointers1.json index 29b658d823..5f53d15702 100644 --- a/rule_packages/c/Pointers1.json +++ b/rule_packages/c/Pointers1.json @@ -244,7 +244,7 @@ ] } ], - "title": "The relational operators >, >=, < and <= shall not be applied to objects of pointer type except where they point into the same object" + "title": "The relational operators >, >=, < and <= shall not be applied to expressions of pointer type except where they point into the same object" }, "RULE-18-4": { "properties": { diff --git a/rule_packages/c/SideEffects1.json b/rule_packages/c/SideEffects1.json index 9ecb79447d..9d91fce671 100644 --- a/rule_packages/c/SideEffects1.json +++ b/rule_packages/c/SideEffects1.json @@ -166,7 +166,7 @@ }, "RULE-13-6": { "properties": { - "obligation": "mandatory" + "obligation": "required" }, "queries": [ { From 08fdda904d09921412d6ee1d3e85d2c5484cc07d Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 10 Dec 2024 18:10:39 -0800 Subject: [PATCH 103/370] Regenerate query files --- c/misra/src/rules/RULE-13-6/SizeofOperandWithSideEffect.ql | 2 +- .../rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.ql | 2 +- c/misra/src/rules/RULE-21-11/StandardHeaderFileTgmathhUsed.ql | 2 +- cpp/common/src/codingstandards/cpp/exclusions/c/Banned.qll | 2 +- cpp/common/src/codingstandards/cpp/exclusions/c/Contracts6.qll | 2 +- .../src/codingstandards/cpp/exclusions/c/SideEffects1.qll | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/c/misra/src/rules/RULE-13-6/SizeofOperandWithSideEffect.ql b/c/misra/src/rules/RULE-13-6/SizeofOperandWithSideEffect.ql index ec1551c2a6..759ad9b06a 100644 --- a/c/misra/src/rules/RULE-13-6/SizeofOperandWithSideEffect.ql +++ b/c/misra/src/rules/RULE-13-6/SizeofOperandWithSideEffect.ql @@ -9,7 +9,7 @@ * @tags external/misra/id/rule-13-6 * correctness * external/misra/c/2012/third-edition-first-revision - * external/misra/obligation/mandatory + * external/misra/obligation/required */ import cpp diff --git a/c/misra/src/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.ql b/c/misra/src/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.ql index 9673b39eb2..1a142ddb22 100644 --- a/c/misra/src/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.ql +++ b/c/misra/src/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.ql @@ -9,7 +9,7 @@ * @tags external/misra/id/rule-17-5 * correctness * external/misra/c/2012/third-edition-first-revision - * external/misra/obligation/advisory + * external/misra/obligation/required */ import cpp diff --git a/c/misra/src/rules/RULE-21-11/StandardHeaderFileTgmathhUsed.ql b/c/misra/src/rules/RULE-21-11/StandardHeaderFileTgmathhUsed.ql index 1c6b1bcd3d..50c4d48cb6 100644 --- a/c/misra/src/rules/RULE-21-11/StandardHeaderFileTgmathhUsed.ql +++ b/c/misra/src/rules/RULE-21-11/StandardHeaderFileTgmathhUsed.ql @@ -8,7 +8,7 @@ * @tags external/misra/id/rule-21-11 * correctness * external/misra/c/2012/third-edition-first-revision - * external/misra/obligation/required + * external/misra/obligation/advisory */ import cpp diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Banned.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Banned.qll index 888e0863a3..f8a4e027bb 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/Banned.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Banned.qll @@ -77,7 +77,7 @@ predicate isBannedQueryMetadata(Query query, string queryId, string ruleId, stri // `@id` for the `standardHeaderFileTgmathhUsed` query "c/misra/standard-header-file-tgmathh-used" and ruleId = "RULE-21-11" and - category = "required" + category = "advisory" or query = // `Query` instance for the `exceptionHandlingFeaturesOfFenvhUsed` query diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Contracts6.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Contracts6.qll index bd897bd79f..eed78ae507 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/Contracts6.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Contracts6.qll @@ -25,7 +25,7 @@ predicate isContracts6QueryMetadata(Query query, string queryId, string ruleId, // `@id` for the `arrayFunctionArgumentNumberOfElements` query "c/misra/array-function-argument-number-of-elements" and ruleId = "RULE-17-5" and - category = "advisory" + category = "required" or query = // `Query` instance for the `valueReturnedByAFunctionNotUsed` query diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/SideEffects1.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/SideEffects1.qll index 24175cdfb7..ec8ab3eae8 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/SideEffects1.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/SideEffects1.qll @@ -104,7 +104,7 @@ predicate isSideEffects1QueryMetadata(Query query, string queryId, string ruleId // `@id` for the `sizeofOperandWithSideEffect` query "c/misra/sizeof-operand-with-side-effect" and ruleId = "RULE-13-6" and - category = "mandatory" + category = "required" } module SideEffects1Package { From dbb452317756c635407229676c5d19fc31e3b817 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 12 Dec 2024 17:15:17 -0800 Subject: [PATCH 104/370] Address most MISRA C 2012 rule amendments in Amendment3. Does not address amendments that are covered in other PRs (clarifications) or Generics behavior. Most updates related to complex floating types. One update related to emergent language features. --- amendments.csv | 18 +- .../c/misra/EssentialTypes.qll | 28 +- ...ainNumericalTypeUsedOverExplicitTypedef.ql | 58 ++- .../OperandsOfAnInappropriateEssentialType.ql | 68 ++- .../AssignmentOfIncompatibleEssentialType.ql | 6 + ...andsWithMismatchedEssentialTypeCategory.ql | 5 + .../InappropriateEssentialTypeCast.ql | 6 +- ...ImplicitConversionOfCompositeExpression.ql | 6 +- .../InappropriateCastOfCompositeExpression.ql | 21 +- .../RULE-14-1/LoopOverEssentiallyFloatType.ql | 2 +- ...ericalTypeUsedOverExplicitTypedef.expected | 40 +- c/misra/test/rules/DIR-4-6/test.c | 11 +- .../EmergentLanguageFeaturesUsed.expected | 14 - c/misra/test/rules/RULE-1-4/test.c | 32 +- ...ndsOfAnInappropriateEssentialType.expected | 392 +++++++++--------- .../PointerTypeOnLogicalOperator.expected | 10 +- c/misra/test/rules/RULE-10-1/test.c | 169 ++++++-- ...gnmentOfIncompatibleEssentialType.expected | 321 ++++++++------ c/misra/test/rules/RULE-10-3/test.c | 283 +++++++++---- ...thMismatchedEssentialTypeCategory.expected | 23 +- c/misra/test/rules/RULE-10-4/test.c | 9 + .../InappropriateEssentialTypeCast.expected | 45 +- c/misra/test/rules/RULE-10-5/test.c | 90 ++-- ...itConversionOfCompositeExpression.expected | 4 + c/misra/test/rules/RULE-10-7/test.c | 14 + ...ropriateCastOfCompositeExpression.expected | 10 +- c/misra/test/rules/RULE-10-8/test.c | 25 ++ .../src/codingstandards/cpp/Emergent.qll | 34 -- 28 files changed, 1104 insertions(+), 640 deletions(-) diff --git a/amendments.csv b/amendments.csv index ce285a29ba..0f588b0e05 100644 --- a/amendments.csv +++ b/amendments.csv @@ -1,14 +1,14 @@ language,standard,amendment,rule_id,supportable,implementation_category,implemented,difficulty -c,MISRA-C-2012,Amendment3,DIR-4-6,Yes,Expand,No,Easy +c,MISRA-C-2012,Amendment3,DIR-4-6,Yes,Expand,Yes,Easy c,MISRA-C-2012,Amendment3,DIR-4-9,Yes,Refine,No,Easy c,MISRA-C-2012,Amendment3,DIR-4-11,Yes,Refine,No,Import -c,MISRA-C-2012,Amendment3,RULE-1-4,Yes,Replace,No,Easy -c,MISRA-C-2012,Amendment3,RULE-10-1,Yes,Replace,No,Easy -c,MISRA-C-2012,Amendment3,RULE-10-3,Yes,Refine,No,Easy -c,MISRA-C-2012,Amendment3,RULE-10-4,Yes,Refine,No,Import -c,MISRA-C-2012,Amendment3,RULE-10-5,Yes,Expand,No,Easy -c,MISRA-C-2012,Amendment3,RULE-10-7,Yes,Refine,No,Import -c,MISRA-C-2012,Amendment3,RULE-10-8,Yes,Refine,No,Import +c,MISRA-C-2012,Amendment3,RULE-1-4,Yes,Replace,Yes,Easy +c,MISRA-C-2012,Amendment3,RULE-10-1,Yes,Replace,Yes,Easy +c,MISRA-C-2012,Amendment3,RULE-10-3,Yes,Refine,Yes,Easy +c,MISRA-C-2012,Amendment3,RULE-10-4,Yes,Refine,Yes,Import +c,MISRA-C-2012,Amendment3,RULE-10-5,Yes,Expand,Yes,Easy +c,MISRA-C-2012,Amendment3,RULE-10-7,Yes,Refine,Yes,Import +c,MISRA-C-2012,Amendment3,RULE-10-8,Yes,Refine,Yes,Import c,MISRA-C-2012,Amendment3,RULE-21-11,Yes,Clarification,No,Import c,MISRA-C-2012,Amendment3,RULE-21-12,Yes,Replace,No,Easy c,MISRA-C-2012,Amendment4,RULE-11-3,Yes,Expand,No,Easy @@ -24,7 +24,7 @@ c,MISRA-C-2012,Corrigendum2,RULE-8-9,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-9-4,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-10-1,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-18-3,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-1-4,Yes,Replace,No,Easy +c,MISRA-C-2012,Corrigendum2,RULE-1-4,Yes,Replace,Yes,Easy c,MISRA-C-2012,Corrigendum2,RULE-9-1,Yes,Refine,No,Easy c,MISRA-C-2012,Corrigendum2,RULE-9-2,Yes,Refine,No,Import c,MISRA-C-2012,Corrigendum2,DIR-4-10,Yes,Clarification,No,Import diff --git a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll index 4783547ed2..98c110f979 100644 --- a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll +++ b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll @@ -6,13 +6,17 @@ import codingstandards.c.misra import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils import MisraExpressions +newtype TEssentialFloatCategory = + Real() or + Complex() + newtype TEssentialTypeCategory = EssentiallyBooleanType() or EssentiallyCharacterType() or EssentiallyEnumType() or EssentiallySignedType() or EssentiallyUnsignedType() or - EssentiallyFloatingType() + EssentiallyFloatingType(TEssentialFloatCategory c) /** An essential type category, as specified by Appendix D.1. */ class EssentialTypeCategory extends TEssentialTypeCategory { @@ -27,7 +31,9 @@ class EssentialTypeCategory extends TEssentialTypeCategory { or this = EssentiallyUnsignedType() and result = "essentially Unsigned type" or - this = EssentiallyFloatingType() and result = "essentially Floating type" + this = EssentiallyFloatingType(Real()) and result = "essentially Floating type" + or + this = EssentiallyFloatingType(Complex()) and result = "essentially Complex Floating type" } } @@ -143,8 +149,11 @@ EssentialTypeCategory getEssentialTypeCategory(Type type) { essentialType instanceof NamedEnumType and not essentialType instanceof MisraBoolType or - result = EssentiallyFloatingType() and - essentialType instanceof FloatingPointType + result = EssentiallyFloatingType(Real()) and + essentialType instanceof RealNumberType + or + result = EssentiallyFloatingType(Complex()) and + essentialType instanceof ComplexNumberType ) } @@ -166,6 +175,17 @@ Type getEssentialType(Expr e) { Type getEssentialTypeBeforeConversions(Expr e) { result = e.(EssentialExpr).getEssentialType() } +/** + * For most essential types, `Type.getSize()` is correct, except for complex floating types. + * + * For complex floating types, the size is the size of the real part, so we divide by 2. + */ +int getEssentialSize(Type essentialType) { + if getEssentialTypeCategory(essentialType) = EssentiallyFloatingType(Complex()) + then result = essentialType.getSize() / 2 + else result = essentialType.getSize() +} + class EssentialExpr extends Expr { Type getEssentialType() { result = this.getType() } diff --git a/c/misra/src/rules/DIR-4-6/PlainNumericalTypeUsedOverExplicitTypedef.ql b/c/misra/src/rules/DIR-4-6/PlainNumericalTypeUsedOverExplicitTypedef.ql index 3891d8c99f..0e6c902441 100644 --- a/c/misra/src/rules/DIR-4-6/PlainNumericalTypeUsedOverExplicitTypedef.ql +++ b/c/misra/src/rules/DIR-4-6/PlainNumericalTypeUsedOverExplicitTypedef.ql @@ -29,6 +29,8 @@ class BuiltInNumericType extends BuiltInType { this instanceof DoubleType or this instanceof LongDoubleType + or + this instanceof ComplexNumberType } } @@ -38,22 +40,64 @@ predicate forbiddenBuiltinNumericUsedInDecl(Variable var, string message) { message = "The type " + var.getType() + " is not a fixed-width numeric type." } +class SizedTypeString extends string { + string pattern; + int size; + + bindingset[this] + pragma[inline] + SizedTypeString() { + pattern = "(u?int|c?float)(4|8|16|32|64|128)_t" and + this.regexpMatch(pattern) and + size = this.regexpCapture(pattern, 2).toInt() + } + + bindingset[this] + pragma[inline] + int getSize() { result = size } + + bindingset[this] + pragma[inline] + predicate isComplex() { this.charAt(0) = "c" } +} + +predicate forbiddenComplexType(CTypedefType typedef, string message) { + typedef.getName().(SizedTypeString).isComplex() and + ( + if typedef.getBaseType().stripTopLevelSpecifiers() instanceof ComplexNumberType + then + typedef.getSize() * 8 != typedef.getName().(SizedTypeString).getSize() * 2 and + message = "The typedef type " + typedef.getName() + " does not have its indicated real size." + else message = "The typedef type " + typedef.getName() + " is not a complex type." + ) +} + +predicate forbiddenRealType(CTypedefType typedef, string message) { + not typedef.getName().(SizedTypeString).isComplex() and + ( + if typedef.getBaseType().stripTopLevelSpecifiers() instanceof ComplexNumberType + then message = "The typedef name " + typedef.getName() + " does not indicate a complex type." + else ( + typedef.getSize() * 8 != typedef.getName().(SizedTypeString).getSize() and + message = "The typedef type " + typedef.getName() + " does not have its indicated size." + ) + ) +} + predicate forbiddenTypedef(CTypedefType typedef, string message) { /* If the typedef's name contains an explicit size */ ( - if typedef.getName().regexpMatch("u?(int|float)(4|8|16|32|64|128)_t") + if typedef.getName() instanceof SizedTypeString then ( - /* Then the actual type size should match. */ - not typedef.getSize() * 8 = - // times 8 because getSize() gets the size in bytes - typedef.getName().regexpCapture("u?(int|float)(4|8|16|32|64|128)_t", 2).toInt() and - message = "The typedef type " + typedef.getName() + " does not have its indicated size." + forbiddenRealType(typedef, message) + or + forbiddenComplexType(typedef, message) ) else ( ( // type def is to a built in numeric type typedef.getBaseType() instanceof BuiltInNumericType and // but does not include the size in the name - not typedef.getName().regexpMatch("u?(int|float)(4|8|16|32|64|128)_t") + not typedef.getName() instanceof SizedTypeString or // this is a typedef to a forbidden type def forbiddenTypedef(typedef.getBaseType(), _) diff --git a/c/misra/src/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.ql b/c/misra/src/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.ql index 10b24b8c8a..d06ba09f3d 100644 --- a/c/misra/src/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.ql +++ b/c/misra/src/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.ql @@ -16,6 +16,15 @@ import cpp import codingstandards.c.misra import codingstandards.c.misra.EssentialTypes +predicate hasComparableFloatValue(Expr e) { + exists(float value | + value = e.getValue().toFloat() or + value = -e.(UnaryMinusExpr).getOperand().getValue().toFloat() + | + value in [0.0, "Infinity".toFloat(), -"Infinity".toFloat()] + ) +} + /** * Holds if the operator `operator` has an operand `child` that is of an inappropriate essential type * according to MISRA C 2012 Rule 10.1. @@ -33,8 +42,11 @@ predicate isInappropriateEssentialType( etc = EssentiallyCharacterType() and rationaleId = 4 or - etc = EssentiallyFloatingType() and + etc = EssentiallyFloatingType(Real()) and rationaleId = 1 + or + etc = EssentiallyFloatingType(Complex()) and + rationaleId = 9 ) or child = operator.(UnaryPlusExpr).getOperand() and @@ -64,8 +76,6 @@ predicate isInappropriateEssentialType( rationaleId = 8 ) or - // The table only talks about + and -, but below it clarifies ++ and -- are also considered to - // be equivalent. child = [ operator.(AddExpr).getAnOperand(), operator.(SubExpr).getAnOperand(), @@ -80,6 +90,13 @@ predicate isInappropriateEssentialType( rationaleId = 5 ) or + child = + [operator.(IncrementOperation).getAnOperand(), operator.(DecrementOperation).getAnOperand()] and + ( + etc = EssentiallyFloatingType(Complex()) and + rationaleId = 9 + ) + or child = [ operator.(DivExpr).getAnOperand(), operator.(MulExpr).getAnOperand(), @@ -107,13 +124,26 @@ predicate isInappropriateEssentialType( etc = EssentiallyEnumType() and rationaleId = 5 or - etc = EssentiallyFloatingType() and + etc = EssentiallyFloatingType(Real()) and rationaleId = 1 + or + etc = EssentiallyFloatingType(Complex()) and + rationaleId = 9 ) or child = operator.(RelationalOperation).getAnOperand() and - etc = EssentiallyBooleanType() and - rationaleId = 3 + ( + etc = EssentiallyBooleanType() and + rationaleId = 3 + or + etc = EssentiallyFloatingType(Complex()) and + rationaleId = 9 + ) + or + child = operator.(EqualityOperation).getAnOperand() and + rationaleId = 10 and + not hasComparableFloatValue(operator.(EqualityOperation).getAnOperand()) and + etc = EssentiallyFloatingType(_) or child = [operator.(NotExpr).getAnOperand(), operator.(BinaryLogicalOperation).getAnOperand()] and rationaleId = 2 and @@ -126,7 +156,7 @@ predicate isInappropriateEssentialType( or etc = EssentiallyUnsignedType() or - etc = EssentiallyFloatingType() + etc = EssentiallyFloatingType(_) ) or child = @@ -147,8 +177,11 @@ predicate isInappropriateEssentialType( etc = EssentiallySignedType() and rationaleId = 6 or - etc = EssentiallyFloatingType() and + etc = EssentiallyFloatingType(Real()) and rationaleId = 1 + or + etc = EssentiallyFloatingType(Complex()) and + rationaleId = 9 ) or child = @@ -171,8 +204,11 @@ predicate isInappropriateEssentialType( etc = EssentiallySignedType() and rationaleId = 7 or - etc = EssentiallyFloatingType() and + etc = EssentiallyFloatingType(Real()) and rationaleId = 1 + or + etc = EssentiallyFloatingType(Complex()) and + rationaleId = 9 ) or child = @@ -197,8 +233,11 @@ predicate isInappropriateEssentialType( etc = EssentiallySignedType() and rationaleId = 6 or - etc = EssentiallyFloatingType() and + etc = EssentiallyFloatingType(Real()) and rationaleId = 1 + or + etc = EssentiallyFloatingType(Complex()) and + rationaleId = 9 ) or child = operator.(ConditionalExpr).getCondition() and @@ -215,7 +254,7 @@ predicate isInappropriateEssentialType( etc = EssentiallyUnsignedType() and rationaleId = 2 or - etc = EssentiallyFloatingType() and + etc = EssentiallyFloatingType(_) and rationaleId = 2 ) ) @@ -245,6 +284,13 @@ string getRationaleMessage(int rationaleId, EssentialTypeCategory etc) { rationaleId = 8 and result = "Operand of essentially Unsigned type will be converted to a signed type with the signedness dependent on the implemented size of int." + or + rationaleId = 9 and + result = "Use of essentially Complex type in this way is a constraint violation." + or + rationaleId = 10 and + result = + "Floating point numbers have inherent error such that comparisons should consider precision and not exact equality." } from Expr operator, Expr child, int rationaleId, EssentialTypeCategory etc diff --git a/c/misra/src/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.ql b/c/misra/src/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.ql index af120fb13d..7574531332 100644 --- a/c/misra/src/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.ql +++ b/c/misra/src/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.ql @@ -48,5 +48,11 @@ where lValueTypeCategory = EssentiallyUnsignedType() and const >= 0 and const <= 2.pow(lValueEssentialType.getSize() * 8) + ) and + // Exception 4: Real floating point values may be assignable to complex floating point values + not ( + lValueTypeCategory = EssentiallyFloatingType(Complex()) and + rValueTypeCategory = EssentiallyFloatingType(Real()) and + lValueEssentialType.getSize() >= rValueEssentialType.getSize() * 2 ) select rValue, message diff --git a/c/misra/src/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.ql b/c/misra/src/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.ql index d1fed06319..71681ad3bc 100644 --- a/c/misra/src/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.ql +++ b/c/misra/src/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.ql @@ -30,6 +30,11 @@ where rightOpTypeCategory = getEssentialTypeCategory(rightOpEssentialType) and ( not leftOpTypeCategory = rightOpTypeCategory and + not ( + // Exception 3: Operands where both are real or complex floating types are allowed. + leftOpTypeCategory = EssentiallyFloatingType(_) and + rightOpTypeCategory = EssentiallyFloatingType(_) + ) and message = "The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: " + leftOpTypeCategory + ", right operand: " + rightOpTypeCategory + ")." diff --git a/c/misra/src/rules/RULE-10-5/InappropriateEssentialTypeCast.ql b/c/misra/src/rules/RULE-10-5/InappropriateEssentialTypeCast.ql index f782a16597..7cadb104ad 100644 --- a/c/misra/src/rules/RULE-10-5/InappropriateEssentialTypeCast.ql +++ b/c/misra/src/rules/RULE-10-5/InappropriateEssentialTypeCast.ql @@ -23,14 +23,14 @@ predicate isIncompatibleEssentialTypeCast(EssentialTypeCategory fromCat, Essenti toCat = [ EssentiallyCharacterType(), EssentiallyEnumType(), EssentiallySignedType(), - EssentiallyUnsignedType(), EssentiallyFloatingType().(TEssentialTypeCategory) + EssentiallyUnsignedType(), EssentiallyFloatingType(_).(TEssentialTypeCategory) ] or fromCat = EssentiallyCharacterType() and toCat = [ EssentiallyBooleanType(), EssentiallyEnumType(), - EssentiallyFloatingType().(TEssentialTypeCategory) + EssentiallyFloatingType(_).(TEssentialTypeCategory) ] or fromCat = EssentiallyEnumType() and @@ -42,7 +42,7 @@ predicate isIncompatibleEssentialTypeCast(EssentialTypeCategory fromCat, Essenti fromCat = EssentiallyUnsignedType() and toCat = [EssentiallyBooleanType(), EssentiallyEnumType().(TEssentialTypeCategory)] or - fromCat = EssentiallyFloatingType() and + fromCat = EssentiallyFloatingType(_) and toCat = [ EssentiallyBooleanType(), EssentiallyCharacterType(), diff --git a/c/misra/src/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.ql b/c/misra/src/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.ql index 911aa5e00e..d674f78dc3 100644 --- a/c/misra/src/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.ql +++ b/c/misra/src/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.ql @@ -23,6 +23,10 @@ bindingset[essentialTypeLeft, essentialTypeRight] pragma[inline_late] predicate isSameEssentialTypeCategory(Type essentialTypeLeft, Type essentialTypeRight) { getEssentialTypeCategory(essentialTypeLeft) = getEssentialTypeCategory(essentialTypeRight) + or + // Complex and real floating types are considered interchangeable + getEssentialTypeCategory(essentialTypeLeft) = EssentiallyFloatingType(_) and + getEssentialTypeCategory(essentialTypeRight) = EssentiallyFloatingType(_) } from @@ -35,7 +39,7 @@ where not otherOp = compositeOp and compositeEssentialType = getEssentialType(compositeOp) and otherOpEssentialType = getEssentialType(otherOp) and - compositeEssentialType.getSize() < otherOpEssentialType.getSize() and + getEssentialSize(compositeEssentialType) < getEssentialSize(otherOpEssentialType) and // Operands of a different type category in an operation with the usual arithmetic conversions is // prohibited by Rule 10.4, so we only report cases here where the essential type categories are // the same diff --git a/c/misra/src/rules/RULE-10-8/InappropriateCastOfCompositeExpression.ql b/c/misra/src/rules/RULE-10-8/InappropriateCastOfCompositeExpression.ql index 162ba4439c..b4d54bf2e8 100644 --- a/c/misra/src/rules/RULE-10-8/InappropriateCastOfCompositeExpression.ql +++ b/c/misra/src/rules/RULE-10-8/InappropriateCastOfCompositeExpression.ql @@ -30,12 +30,19 @@ where castTypeCategory = getEssentialTypeCategory(castEssentialType) and compositeTypeCategory = getEssentialTypeCategory(compositeExprEssentialType) and ( - not castTypeCategory = compositeTypeCategory and - message = - "Cast from " + compositeTypeCategory + " to " + castTypeCategory + " changes type category." - or - castTypeCategory = compositeTypeCategory and - castEssentialType.getSize() > compositeExprEssentialType.getSize() and - message = "Cast from " + compositeTypeCategory + " to " + castTypeCategory + " widens type." + if + not castTypeCategory = compositeTypeCategory and + not ( + // Exception 2: Casts between real or complex floating types are allowed + castTypeCategory = EssentiallyFloatingType(_) and + compositeTypeCategory = EssentiallyFloatingType(_) + ) + then + message = + "Cast from " + compositeTypeCategory + " to " + castTypeCategory + " changes type category." + else ( + getEssentialSize(castEssentialType) > getEssentialSize(compositeExprEssentialType) and + message = "Cast from " + compositeTypeCategory + " to " + castTypeCategory + " widens type." + ) ) select ce, message diff --git a/c/misra/src/rules/RULE-14-1/LoopOverEssentiallyFloatType.ql b/c/misra/src/rules/RULE-14-1/LoopOverEssentiallyFloatType.ql index 83d91dac63..3d351c898e 100644 --- a/c/misra/src/rules/RULE-14-1/LoopOverEssentiallyFloatType.ql +++ b/c/misra/src/rules/RULE-14-1/LoopOverEssentiallyFloatType.ql @@ -21,6 +21,6 @@ from ForStmt forLoop, Variable loopIterationVariable where not isExcluded(loopIterationVariable, EssentialTypesPackage::loopOverEssentiallyFloatTypeQuery()) and getAnIterationVariable(forLoop) = loopIterationVariable and - getEssentialTypeCategory(loopIterationVariable.getType()) = EssentiallyFloatingType() + getEssentialTypeCategory(loopIterationVariable.getType()) = EssentiallyFloatingType(_) select loopIterationVariable, "Loop iteration variable " + loopIterationVariable.getName() + " is essentially Floating type." diff --git a/c/misra/test/rules/DIR-4-6/PlainNumericalTypeUsedOverExplicitTypedef.expected b/c/misra/test/rules/DIR-4-6/PlainNumericalTypeUsedOverExplicitTypedef.expected index c7f1cba77a..49e0b1c34c 100644 --- a/c/misra/test/rules/DIR-4-6/PlainNumericalTypeUsedOverExplicitTypedef.expected +++ b/c/misra/test/rules/DIR-4-6/PlainNumericalTypeUsedOverExplicitTypedef.expected @@ -1,20 +1,24 @@ | test.c:14:5:14:10 | int4_t | The typedef type int4_t does not have its indicated size. | | test.c:16:5:16:11 | uint4_t | The typedef type uint4_t does not have its indicated size. | -| test.c:27:5:27:26 | _astronomical_number_t | The type _astronomical_number_t is not an alias to a fixed-width numeric type. | -| test.c:34:15:34:16 | c2 | The type signed char is not a fixed-width numeric type. | -| test.c:35:17:35:18 | c3 | The type unsigned char is not a fixed-width numeric type. | -| test.c:38:9:38:10 | s1 | The type short is not a fixed-width numeric type. | -| test.c:39:16:39:17 | s2 | The type signed short is not a fixed-width numeric type. | -| test.c:40:18:40:19 | s3 | The type unsigned short is not a fixed-width numeric type. | -| test.c:43:7:43:8 | i1 | The type int is not a fixed-width numeric type. | -| test.c:44:14:44:15 | i2 | The type signed int is not a fixed-width numeric type. | -| test.c:45:16:45:17 | i3 | The type unsigned int is not a fixed-width numeric type. | -| test.c:48:8:48:9 | l1 | The type long is not a fixed-width numeric type. | -| test.c:49:15:49:16 | l2 | The type signed long is not a fixed-width numeric type. | -| test.c:50:17:50:18 | l3 | The type unsigned long is not a fixed-width numeric type. | -| test.c:53:13:53:15 | ll1 | The type long long is not a fixed-width numeric type. | -| test.c:54:20:54:22 | ll2 | The type signed long long is not a fixed-width numeric type. | -| test.c:55:22:55:24 | ll3 | The type unsigned long long is not a fixed-width numeric type. | -| test.c:58:9:58:10 | f1 | The type float is not a fixed-width numeric type. | -| test.c:61:10:61:11 | d1 | The type double is not a fixed-width numeric type. | -| test.c:64:15:64:17 | ld1 | The type long double is not a fixed-width numeric type. | +| test.c:19:25:19:33 | float64_t | The typedef name float64_t does not indicate a complex type. | +| test.c:22:15:22:24 | cfloat32_t | The typedef type cfloat32_t is not a complex type. | +| test.c:24:25:24:35 | cfloat128_t | The typedef type cfloat128_t does not have its indicated real size. | +| test.c:31:5:31:26 | _astronomical_number_t | The type _astronomical_number_t is not an alias to a fixed-width numeric type. | +| test.c:38:15:38:16 | c2 | The type signed char is not a fixed-width numeric type. | +| test.c:39:17:39:18 | c3 | The type unsigned char is not a fixed-width numeric type. | +| test.c:42:9:42:10 | s1 | The type short is not a fixed-width numeric type. | +| test.c:43:16:43:17 | s2 | The type signed short is not a fixed-width numeric type. | +| test.c:44:18:44:19 | s3 | The type unsigned short is not a fixed-width numeric type. | +| test.c:47:7:47:8 | i1 | The type int is not a fixed-width numeric type. | +| test.c:48:14:48:15 | i2 | The type signed int is not a fixed-width numeric type. | +| test.c:49:16:49:17 | i3 | The type unsigned int is not a fixed-width numeric type. | +| test.c:52:8:52:9 | l1 | The type long is not a fixed-width numeric type. | +| test.c:53:15:53:16 | l2 | The type signed long is not a fixed-width numeric type. | +| test.c:54:17:54:18 | l3 | The type unsigned long is not a fixed-width numeric type. | +| test.c:57:13:57:15 | ll1 | The type long long is not a fixed-width numeric type. | +| test.c:58:20:58:22 | ll2 | The type signed long long is not a fixed-width numeric type. | +| test.c:59:22:59:24 | ll3 | The type unsigned long long is not a fixed-width numeric type. | +| test.c:62:9:62:10 | f1 | The type float is not a fixed-width numeric type. | +| test.c:65:10:65:11 | d1 | The type double is not a fixed-width numeric type. | +| test.c:68:15:68:17 | ld1 | The type long double is not a fixed-width numeric type. | +| test.c:71:18:71:20 | cf1 | The type _Complex float is not a fixed-width numeric type. | diff --git a/c/misra/test/rules/DIR-4-6/test.c b/c/misra/test/rules/DIR-4-6/test.c index db0842c4f6..0fc79faa2e 100644 --- a/c/misra/test/rules/DIR-4-6/test.c +++ b/c/misra/test/rules/DIR-4-6/test.c @@ -15,10 +15,14 @@ typedef signed long long typedef unsigned long long uint4_t; // NON_COMPLIANT: typedef does not have its indicated size -typedef float float32_t; // COMPLIANT: exception, typedefs are permitted -typedef double float64_t; // COMPLIANT: exception, typedefs are permitted +typedef float float32_t; // COMPLIANT: exception, typedefs are permitted +typedef double _Complex float64_t; // NON-COMPLIANT: not complex floating type typedef long double float128_t; // COMPLIANT: exception, typedefs are permitted +typedef float cfloat32_t; // NON-COMPLIANT: not a complex floating type +typedef double _Complex cfloat64_t; // COMPLIANT: correct complex floating type +typedef double _Complex cfloat128_t; // NON-COMPLIANT: incorrect complex size + typedef int8_t astronomical_number_t; // COMPLIANT: aliasing a fixed-width numeric typedef typedef uint8_t u_astronomical_number_t; // COMPLIANT: aliasing a fixed-width @@ -63,4 +67,7 @@ main(int argc, // COMPLIANT: exception, argc's type can be plain int long double ld1 = 1; // NON_COMPLIANT: int is a basic numeric type float128_t ld2 = 1; // COMPLIANT: typedef used instead + + float _Complex cf1 = 1; // NON_COMPLIANT: complex basic numeric type + cfloat64_t cf2 = 1; // COMPLIANT: typedef used instead } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected b/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected index 2745223358..3f63a6c26c 100644 --- a/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected +++ b/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected @@ -1,15 +1 @@ -| test.c:1:1:1:21 | #include | Usage of emergent language feature. | -| test.c:2:1:2:22 | #include | Usage of emergent language feature. | -| test.c:3:1:3:24 | #include | Usage of emergent language feature. | -| test.c:4:1:4:20 | #include | Usage of emergent language feature. | -| test.c:6:1:6:49 | #define MACRO(x) _Generic((x), int : 0, long : 1) | Usage of emergent language feature. | | test.c:7:1:7:32 | #define __STDC_WANT_LIB_EXT1__ 1 | Usage of emergent language feature. | -| test.c:9:16:9:17 | f0 | Usage of emergent language feature. | -| test.c:12:26:12:40 | atomic_new_type | Usage of emergent language feature. | -| test.c:17:15:17:15 | i | Usage of emergent language feature. | -| test.c:19:3:19:10 | alignas(...) | Usage of emergent language feature. | -| test.c:20:3:20:9 | alignas(...) | Usage of emergent language feature. | -| test.c:21:11:21:23 | alignof(int) | Usage of emergent language feature. | -| test.c:22:12:22:23 | alignof(int) | Usage of emergent language feature. | -| test.c:24:27:24:28 | i3 | Usage of emergent language feature. | -| test.c:25:28:25:29 | i4 | Usage of emergent language feature. | diff --git a/c/misra/test/rules/RULE-1-4/test.c b/c/misra/test/rules/RULE-1-4/test.c index 153c722c94..8c1e44e6bd 100644 --- a/c/misra/test/rules/RULE-1-4/test.c +++ b/c/misra/test/rules/RULE-1-4/test.c @@ -1,26 +1,26 @@ -#include //NON_COMPLIANT -#include //NON_COMPLIANT -#include //NON_COMPLIANT -#include //NON_COMPLIANT +#include //COMPLIANT +#include //COMPLIANT +#include //COMPLIANT +#include //COMPLIANT -#define MACRO(x) _Generic((x), int : 0, long : 1) // NON_COMPLIANT -#define __STDC_WANT_LIB_EXT1__ 1 // NON_COMPLIANT +#define MACRO(x) _Generic((x), int : 0, long : 1) // COMPLIANT +#define __STDC_WANT_LIB_EXT1__ 1 // NON-COMPLIANT -_Noreturn void f0(); // NON_COMPLIANT +_Noreturn void f0(); // COMPLIANT typedef int new_type; // COMPLIANT -typedef _Atomic new_type atomic_new_type; // NON_COMPLIANT +typedef _Atomic new_type atomic_new_type; // COMPLIANT void f(int p) { - int i0 = _Generic(p, int : 0, long : 1); // NON_COMPLIANT[FALSE_NEGATIVE] + int i0 = _Generic(p, int : 0, long : 1); // COMPLIANT - _Atomic int i; // NON_COMPLIANT + _Atomic int i; // COMPLIANT - _Alignas(4) int i1; // NON_COMPLIANT - alignas(4) int i2; // NON_COMPLIANT - int a = _Alignof(int); // NON_COMPLIANT - int a1 = alignof(int); // NON_COMPLIANT + _Alignas(4) int i1; // COMPLIANT + alignas(4) int i2; // COMPLIANT + int a = _Alignof(int); // COMPLIANT + int a1 = alignof(int); // COMPLIANT - static thread_local int i3; // NON_COMPLIANT - static _Thread_local int i4; // NON_COMPLIANT + static thread_local int i3; // COMPLIANT + static _Thread_local int i4; // COMPLIANT } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.expected b/c/misra/test/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.expected index 8d1b1d8d1b..aad8dadf99 100644 --- a/c/misra/test/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.expected +++ b/c/misra/test/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.expected @@ -1,191 +1,209 @@ -| test.c:13:5:13:5 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:14:5:14:5 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:20:4:20:4 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:21:4:21:4 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:22:4:22:5 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:27:4:27:4 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:28:4:28:4 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:29:4:29:5 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:31:4:31:4 | u | Operand of essentially Unsigned type will be converted to a signed type with the signedness dependent on the implemented size of int. | -| test.c:34:7:34:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:36:7:36:8 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:41:7:41:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:43:7:43:8 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:48:3:48:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:50:3:50:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:15:5:15:5 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:16:5:16:5 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:23:4:23:4 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:24:4:24:4 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:25:4:25:5 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:31:4:31:4 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:32:4:32:4 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:33:4:33:5 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:35:4:35:4 | u | Operand of essentially Unsigned type will be converted to a signed type with the signedness dependent on the implemented size of int. | +| test.c:39:7:39:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:41:7:41:8 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:47:7:47:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:49:7:49:8 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | | test.c:55:3:55:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | | test.c:57:3:57:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:62:3:62:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:64:3:64:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:69:3:69:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:71:3:71:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:76:5:76:5 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:78:5:78:6 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:83:5:83:5 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:85:5:85:6 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:90:7:90:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:91:7:91:7 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:92:7:92:8 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:97:7:97:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:98:7:98:7 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:99:7:99:8 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:104:3:104:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:105:3:105:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:106:3:106:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:111:3:111:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:112:3:112:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:113:3:113:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:118:3:118:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:119:3:119:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:120:3:120:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:125:7:125:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:126:7:126:7 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:127:7:127:8 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:132:7:132:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:139:7:139:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:146:8:146:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:153:8:153:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:160:3:160:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:167:3:167:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:174:3:174:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:181:3:181:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:217:4:217:4 | c | Operand of essentially Character type type interpreted as a Boolean value. | -| test.c:218:4:218:5 | e1 | Operand of essentially Enum Type type interpreted as a Boolean value. | -| test.c:219:4:219:4 | s | Operand of essentially Signed type type interpreted as a Boolean value. | -| test.c:220:4:220:4 | u | Operand of essentially Unsigned type type interpreted as a Boolean value. | -| test.c:221:4:221:4 | f | Operand of essentially Floating type type interpreted as a Boolean value. | -| test.c:224:3:224:3 | c | Operand of essentially Character type type interpreted as a Boolean value. | -| test.c:225:3:225:4 | e1 | Operand of essentially Enum Type type interpreted as a Boolean value. | -| test.c:226:3:226:3 | s | Operand of essentially Signed type type interpreted as a Boolean value. | -| test.c:227:3:227:3 | u | Operand of essentially Unsigned type type interpreted as a Boolean value. | -| test.c:228:3:228:3 | f | Operand of essentially Floating type type interpreted as a Boolean value. | -| test.c:231:3:231:3 | c | Operand of essentially Character type type interpreted as a Boolean value. | -| test.c:232:3:232:4 | e1 | Operand of essentially Enum Type type interpreted as a Boolean value. | -| test.c:233:3:233:3 | s | Operand of essentially Signed type type interpreted as a Boolean value. | -| test.c:234:3:234:3 | u | Operand of essentially Unsigned type type interpreted as a Boolean value. | -| test.c:235:3:235:3 | f | Operand of essentially Floating type type interpreted as a Boolean value. | -| test.c:238:11:238:11 | c | Operand of essentially Character type type interpreted as a Boolean value. | -| test.c:239:11:239:12 | e1 | Operand of essentially Enum Type type interpreted as a Boolean value. | -| test.c:240:11:240:11 | s | Operand of essentially Signed type type interpreted as a Boolean value. | -| test.c:241:11:241:11 | u | Operand of essentially Unsigned type type interpreted as a Boolean value. | -| test.c:242:11:242:11 | f | Operand of essentially Floating type type interpreted as a Boolean value. | -| test.c:245:12:245:12 | c | Operand of essentially Character type type interpreted as a Boolean value. | -| test.c:246:12:246:13 | e1 | Operand of essentially Enum Type type interpreted as a Boolean value. | -| test.c:247:12:247:12 | s | Operand of essentially Signed type type interpreted as a Boolean value. | -| test.c:248:12:248:12 | u | Operand of essentially Unsigned type type interpreted as a Boolean value. | -| test.c:249:12:249:12 | f | Operand of essentially Floating type type interpreted as a Boolean value. | -| test.c:251:3:251:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:252:3:252:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:253:3:253:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:254:3:254:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:258:3:258:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:259:3:259:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:260:3:260:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:261:3:261:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:265:8:265:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:266:8:266:8 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:267:8:267:9 | e1 | Right hand operand of shift operator is essentially Enum Type and not not essentially unsigned. | -| test.c:268:8:268:8 | s | Right hand operand of shift operator is essentially Signed type and not not essentially unsigned. | -| test.c:272:8:272:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:273:8:273:8 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:274:8:274:9 | e1 | Right hand operand of shift operator is essentially Enum Type and not not essentially unsigned. | -| test.c:275:8:275:8 | s | Right hand operand of shift operator is essentially Signed type and not not essentially unsigned. | -| test.c:279:3:279:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:280:3:280:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:281:3:281:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:282:3:282:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:286:3:286:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:287:3:287:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:288:3:288:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:289:3:289:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:293:3:293:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:294:3:294:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:295:3:295:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:296:3:296:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:300:6:300:6 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:301:6:301:6 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:302:6:302:7 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:303:6:303:6 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:307:7:307:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:308:7:308:7 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:309:7:309:8 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:310:7:310:7 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:314:7:314:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:315:7:315:7 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:316:7:316:8 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:317:7:317:7 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:321:4:321:4 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:322:4:322:4 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:323:4:323:5 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:324:4:324:4 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:329:3:329:3 | c | Operand of essentially Character type type interpreted as a Boolean value. | -| test.c:330:3:330:4 | e1 | Operand of essentially Enum Type type interpreted as a Boolean value. | -| test.c:331:3:331:3 | s | Operand of essentially Signed type type interpreted as a Boolean value. | -| test.c:332:3:332:3 | u | Operand of essentially Unsigned type type interpreted as a Boolean value. | -| test.c:333:3:333:3 | f | Operand of essentially Floating type type interpreted as a Boolean value. | -| test.c:342:3:342:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:344:3:344:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:349:3:349:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:351:3:351:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:356:8:356:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:358:8:358:9 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:363:8:363:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:365:8:365:9 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:370:3:370:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:371:3:371:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:372:3:372:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:377:3:377:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:378:3:378:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:379:3:379:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:384:8:384:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:385:8:385:8 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:386:8:386:9 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:391:8:391:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:392:8:392:8 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:393:8:393:9 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:398:3:398:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:399:3:399:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:400:3:400:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:405:8:405:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:406:8:406:8 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:407:8:407:9 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | -| test.c:412:3:412:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:413:3:413:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:414:3:414:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:415:3:415:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:419:3:419:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:420:3:420:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:421:3:421:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:422:3:422:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:426:9:426:9 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:427:9:427:9 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:428:9:428:10 | e1 | Right hand operand of shift operator is essentially Enum Type and not not essentially unsigned. | -| test.c:429:9:429:9 | s | Right hand operand of shift operator is essentially Signed type and not not essentially unsigned. | -| test.c:433:9:433:9 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:434:9:434:9 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:435:9:435:10 | e1 | Right hand operand of shift operator is essentially Enum Type and not not essentially unsigned. | -| test.c:436:9:436:9 | s | Right hand operand of shift operator is essentially Signed type and not not essentially unsigned. | -| test.c:440:3:440:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:441:3:441:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:442:3:442:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:443:3:443:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:63:3:63:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:65:3:65:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:71:3:71:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:73:3:73:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:77:3:77:4 | cf | Use of essentially Complex type in this way is a constraint violation. | +| test.c:79:3:79:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:81:3:81:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:85:3:85:4 | cf | Use of essentially Complex type in this way is a constraint violation. | +| test.c:87:5:87:5 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:89:5:89:6 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:93:5:93:6 | cf | Use of essentially Complex type in this way is a constraint violation. | +| test.c:95:5:95:5 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:97:5:97:6 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:101:5:101:6 | cf | Use of essentially Complex type in this way is a constraint violation. | +| test.c:103:7:103:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:104:7:104:7 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:105:7:105:8 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:111:7:111:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:112:7:112:7 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:113:7:113:8 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:119:3:119:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:120:3:120:3 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:121:3:121:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:127:3:127:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:128:3:128:3 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:129:3:129:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:135:3:135:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:136:3:136:3 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:137:3:137:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:143:7:143:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:144:7:144:7 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:145:7:145:8 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:151:7:151:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:159:7:159:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:167:8:167:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:175:8:175:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:183:3:183:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:191:3:191:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:199:3:199:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:207:3:207:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:220:3:220:3 | f | Floating point numbers have inherent error such that comparisons should consider precision and not exact equality. | +| test.c:221:3:221:4 | cf | Floating point numbers have inherent error such that comparisons should consider precision and not exact equality. | +| test.c:234:3:234:3 | f | Floating point numbers have inherent error such that comparisons should consider precision and not exact equality. | +| test.c:235:3:235:4 | cf | Floating point numbers have inherent error such that comparisons should consider precision and not exact equality. | +| test.c:248:8:248:8 | f | Floating point numbers have inherent error such that comparisons should consider precision and not exact equality. | +| test.c:249:8:249:9 | cf | Floating point numbers have inherent error such that comparisons should consider precision and not exact equality. | +| test.c:262:8:262:8 | f | Floating point numbers have inherent error such that comparisons should consider precision and not exact equality. | +| test.c:263:8:263:9 | cf | Floating point numbers have inherent error such that comparisons should consider precision and not exact equality. | +| test.c:272:4:272:4 | c | Operand of essentially Character type type interpreted as a Boolean value. | +| test.c:273:4:273:5 | e1 | Operand of essentially Enum Type type interpreted as a Boolean value. | +| test.c:274:4:274:4 | s | Operand of essentially Signed type type interpreted as a Boolean value. | +| test.c:275:4:275:4 | u | Operand of essentially Unsigned type type interpreted as a Boolean value. | +| test.c:276:4:276:4 | f | Operand of essentially Floating type type interpreted as a Boolean value. | +| test.c:277:4:277:5 | cf | Operand of essentially Complex Floating type type interpreted as a Boolean value. | +| test.c:280:3:280:3 | c | Operand of essentially Character type type interpreted as a Boolean value. | +| test.c:281:3:281:4 | e1 | Operand of essentially Enum Type type interpreted as a Boolean value. | +| test.c:282:3:282:3 | s | Operand of essentially Signed type type interpreted as a Boolean value. | +| test.c:283:3:283:3 | u | Operand of essentially Unsigned type type interpreted as a Boolean value. | +| test.c:284:3:284:3 | f | Operand of essentially Floating type type interpreted as a Boolean value. | +| test.c:285:3:285:4 | cf | Operand of essentially Complex Floating type type interpreted as a Boolean value. | +| test.c:288:3:288:3 | c | Operand of essentially Character type type interpreted as a Boolean value. | +| test.c:289:3:289:4 | e1 | Operand of essentially Enum Type type interpreted as a Boolean value. | +| test.c:290:3:290:3 | s | Operand of essentially Signed type type interpreted as a Boolean value. | +| test.c:291:3:291:3 | u | Operand of essentially Unsigned type type interpreted as a Boolean value. | +| test.c:292:3:292:3 | f | Operand of essentially Floating type type interpreted as a Boolean value. | +| test.c:293:3:293:4 | cf | Operand of essentially Complex Floating type type interpreted as a Boolean value. | +| test.c:296:11:296:11 | c | Operand of essentially Character type type interpreted as a Boolean value. | +| test.c:297:11:297:12 | e1 | Operand of essentially Enum Type type interpreted as a Boolean value. | +| test.c:298:11:298:11 | s | Operand of essentially Signed type type interpreted as a Boolean value. | +| test.c:299:11:299:11 | u | Operand of essentially Unsigned type type interpreted as a Boolean value. | +| test.c:300:11:300:11 | f | Operand of essentially Floating type type interpreted as a Boolean value. | +| test.c:301:11:301:12 | cf | Operand of essentially Complex Floating type type interpreted as a Boolean value. | +| test.c:304:12:304:12 | c | Operand of essentially Character type type interpreted as a Boolean value. | +| test.c:305:12:305:13 | e1 | Operand of essentially Enum Type type interpreted as a Boolean value. | +| test.c:306:12:306:12 | s | Operand of essentially Signed type type interpreted as a Boolean value. | +| test.c:307:12:307:12 | u | Operand of essentially Unsigned type type interpreted as a Boolean value. | +| test.c:308:12:308:12 | f | Operand of essentially Floating type type interpreted as a Boolean value. | +| test.c:309:12:309:13 | cf | Operand of essentially Complex Floating type type interpreted as a Boolean value. | +| test.c:311:3:311:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:312:3:312:3 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:313:3:313:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:314:3:314:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:319:3:319:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:320:3:320:3 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:321:3:321:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:322:3:322:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:327:8:327:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:328:8:328:8 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:329:8:329:9 | e1 | Right hand operand of shift operator is essentially Enum Type and not not essentially unsigned. | +| test.c:330:8:330:8 | s | Right hand operand of shift operator is essentially Signed type and not not essentially unsigned. | +| test.c:335:8:335:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:336:8:336:8 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:337:8:337:9 | e1 | Right hand operand of shift operator is essentially Enum Type and not not essentially unsigned. | +| test.c:338:8:338:8 | s | Right hand operand of shift operator is essentially Signed type and not not essentially unsigned. | +| test.c:343:3:343:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:344:3:344:3 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:345:3:345:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:346:3:346:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:351:3:351:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:352:3:352:3 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:353:3:353:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:354:3:354:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:359:3:359:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:360:3:360:3 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:361:3:361:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:362:3:362:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:367:7:367:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:368:7:368:7 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:369:7:369:8 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:370:7:370:7 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:375:7:375:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:376:7:376:7 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:377:7:377:8 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:378:7:378:7 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:383:7:383:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:384:7:384:7 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:385:7:385:8 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:386:7:386:7 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:391:4:391:4 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:392:4:392:4 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:393:4:393:5 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:394:4:394:4 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:400:3:400:3 | c | Operand of essentially Character type type interpreted as a Boolean value. | +| test.c:401:3:401:4 | e1 | Operand of essentially Enum Type type interpreted as a Boolean value. | +| test.c:402:3:402:3 | s | Operand of essentially Signed type type interpreted as a Boolean value. | +| test.c:403:3:403:3 | u | Operand of essentially Unsigned type type interpreted as a Boolean value. | +| test.c:404:3:404:3 | f | Operand of essentially Floating type type interpreted as a Boolean value. | +| test.c:405:3:405:4 | cf | Operand of essentially Complex Floating type type interpreted as a Boolean value. | +| test.c:415:3:415:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:417:3:417:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:423:3:423:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:425:3:425:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:431:8:431:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:433:8:433:9 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:439:8:439:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:441:8:441:9 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | | test.c:447:3:447:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | | test.c:448:3:448:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:449:3:449:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:450:3:450:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:454:3:454:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:455:3:455:3 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:456:3:456:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:457:3:457:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:461:8:461:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:462:8:462:8 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:463:8:463:9 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:464:8:464:8 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:468:8:468:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:469:8:469:8 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:470:8:470:9 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:471:8:471:8 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:475:8:475:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:476:8:476:8 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:477:8:477:9 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:478:8:478:8 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:449:3:449:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:455:3:455:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:456:3:456:3 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:457:3:457:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:463:8:463:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:464:8:464:8 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:465:8:465:9 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:471:8:471:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:472:8:472:8 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:473:8:473:9 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:479:3:479:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:480:3:480:3 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:481:3:481:4 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:487:8:487:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:488:8:488:8 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:489:8:489:9 | e1 | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:495:3:495:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:496:3:496:3 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:497:3:497:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:498:3:498:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:503:3:503:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:504:3:504:3 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:505:3:505:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:506:3:506:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:511:9:511:9 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:512:9:512:9 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:513:9:513:10 | e1 | Right hand operand of shift operator is essentially Enum Type and not not essentially unsigned. | +| test.c:514:9:514:9 | s | Right hand operand of shift operator is essentially Signed type and not not essentially unsigned. | +| test.c:519:9:519:9 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:520:9:520:9 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:521:9:521:10 | e1 | Right hand operand of shift operator is essentially Enum Type and not not essentially unsigned. | +| test.c:522:9:522:9 | s | Right hand operand of shift operator is essentially Signed type and not not essentially unsigned. | +| test.c:527:3:527:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:528:3:528:3 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:529:3:529:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:530:3:530:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:535:3:535:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:536:3:536:3 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:537:3:537:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:538:3:538:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:543:3:543:3 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:544:3:544:3 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:545:3:545:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:546:3:546:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:551:8:551:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:552:8:552:8 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:553:8:553:9 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:554:8:554:8 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:559:8:559:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:560:8:560:8 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:561:8:561:9 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:562:8:562:8 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:567:8:567:8 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:568:8:568:8 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:569:8:569:9 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:570:8:570:8 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | diff --git a/c/misra/test/rules/RULE-10-1/PointerTypeOnLogicalOperator.expected b/c/misra/test/rules/RULE-10-1/PointerTypeOnLogicalOperator.expected index 35a55919fd..34d2993389 100644 --- a/c/misra/test/rules/RULE-10-1/PointerTypeOnLogicalOperator.expected +++ b/c/misra/test/rules/RULE-10-1/PointerTypeOnLogicalOperator.expected @@ -1,5 +1,5 @@ -| test.c:488:4:488:4 | p | Logical operators should not be used with pointer types. | -| test.c:490:3:490:3 | p | Logical operators should not be used with pointer types. | -| test.c:491:7:491:7 | p | Logical operators should not be used with pointer types. | -| test.c:493:3:493:3 | p | Logical operators should not be used with pointer types. | -| test.c:494:8:494:8 | p | Logical operators should not be used with pointer types. | +| test.c:581:4:581:4 | p | Logical operators should not be used with pointer types. | +| test.c:583:3:583:3 | p | Logical operators should not be used with pointer types. | +| test.c:584:7:584:7 | p | Logical operators should not be used with pointer types. | +| test.c:586:3:586:3 | p | Logical operators should not be used with pointer types. | +| test.c:587:8:587:8 | p | Logical operators should not be used with pointer types. | diff --git a/c/misra/test/rules/RULE-10-1/test.c b/c/misra/test/rules/RULE-10-1/test.c index 19b7d2e3e8..f8d1a4fca5 100644 --- a/c/misra/test/rules/RULE-10-1/test.c +++ b/c/misra/test/rules/RULE-10-1/test.c @@ -1,3 +1,4 @@ +#include "math.h" #include "stdbool.h" void testInappropriateOperands() { @@ -7,6 +8,7 @@ void testInappropriateOperands() { signed int s = 100; unsigned int u = 1; float f = 1.0; + float _Complex cf = 1.0 + 1.0i; int a[20]; @@ -16,6 +18,7 @@ void testInappropriateOperands() { a[s]; // COMPLIANT a[u]; // COMPLIANT // a[f]; // NON_COMPILABLE + // a[cf]; // NON_COMPILABLE +b; // NON_COMPLIANT +c; // NON_COMPLIANT @@ -23,6 +26,7 @@ void testInappropriateOperands() { +s; // COMPLIANT +u; // COMPLIANT +f; // COMPLIANT + +cf; // COMPLIANT -b; // NON_COMPLIANT -c; // NON_COMPLIANT @@ -30,6 +34,7 @@ void testInappropriateOperands() { -s; // COMPLIANT -u; // NON_COMPLIANT -f; // COMPLIANT + -cf; // COMPLIANT 1 + b; // NON_COMPLIANT 1 + c; // COMPLIANT @@ -37,6 +42,7 @@ void testInappropriateOperands() { 1 + s; // COMPLIANT 1 + u; // COMPLIANT 1 + f; // COMPLIANT + 1 + cf; // COMPLIANT 1 - b; // NON_COMPLIANT 1 - c; // COMPLIANT @@ -44,6 +50,7 @@ void testInappropriateOperands() { 1 - s; // COMPLIANT 1 - u; // COMPLIANT 1 - f; // COMPLIANT + 1 - cf; // COMPLIANT b + 1; // NON_COMPLIANT c + 1; // COMPLIANT @@ -51,6 +58,7 @@ void testInappropriateOperands() { s + 1; // COMPLIANT u + 1; // COMPLIANT f + 1; // COMPLIANT + cf + 1; // COMPLIANT b - 1; // NON_COMPLIANT c - 1; // COMPLIANT @@ -58,6 +66,7 @@ void testInappropriateOperands() { s - 1; // COMPLIANT u - 1; // COMPLIANT f - 1; // COMPLIANT + cf - 1; // COMPLIANT b++; // NON_COMPLIANT c++; // COMPLIANT @@ -65,6 +74,7 @@ void testInappropriateOperands() { s++; // COMPLIANT u++; // COMPLIANT f++; // COMPLIANT + cf++; // NON_COMPLIANT b--; // NON_COMPLIANT c--; // COMPLIANT @@ -72,6 +82,7 @@ void testInappropriateOperands() { s--; // COMPLIANT u--; // COMPLIANT f--; // COMPLIANT + cf--; // NON_COMPLIANT ++b; // NON_COMPLIANT ++c; // COMPLIANT @@ -79,6 +90,7 @@ void testInappropriateOperands() { ++s; // COMPLIANT ++u; // COMPLIANT ++f; // COMPLIANT + ++cf; // NON_COMPLIANT --b; // NON_COMPLIANT --c; // COMPLIANT @@ -86,6 +98,7 @@ void testInappropriateOperands() { --s; // COMPLIANT --u; // COMPLIANT --f; // COMPLIANT + --cf; // NON_COMPLIANT 1 * b; // NON_COMPLIANT 1 * c; // NON_COMPLIANT @@ -93,6 +106,7 @@ void testInappropriateOperands() { 1 * s; // COMPLIANT 1 * u; // COMPLIANT 1 * f; // COMPLIANT + 1 * cf; // COMPLIANT 1 / b; // NON_COMPLIANT 1 / c; // NON_COMPLIANT @@ -100,6 +114,7 @@ void testInappropriateOperands() { 1 / s; // COMPLIANT 1 / u; // COMPLIANT 1 / f; // COMPLIANT + 1 / cf; // COMPLIANT b * 1; // NON_COMPLIANT c * 1; // NON_COMPLIANT @@ -107,6 +122,7 @@ void testInappropriateOperands() { s * 1; // COMPLIANT u * 1; // COMPLIANT f * 1; // COMPLIANT + cf * 1; // COMPLIANT b / 1; // NON_COMPLIANT c / 1; // NON_COMPLIANT @@ -114,6 +130,7 @@ void testInappropriateOperands() { s / 1; // COMPLIANT u / 1; // COMPLIANT f / 1; // COMPLIANT + cf / 1; // COMPLIANT b % 1; // NON_COMPLIANT c % 1; // NON_COMPLIANT @@ -121,6 +138,7 @@ void testInappropriateOperands() { s % 1; // COMPLIANT u % 1; // COMPLIANT // f % 1; // NON_COMPILABLE + // cf % 1; // NON_COMPILABLE 1 % b; // NON_COMPLIANT 1 % c; // NON_COMPLIANT @@ -128,6 +146,7 @@ void testInappropriateOperands() { 1 % s; // COMPLIANT 1 % u; // COMPLIANT // 1 % f; // NON_COMPILABLE + // 1 % cf; // NON_COMPILABLE 1 < b; // NON_COMPLIANT 1 < c; // COMPLIANT @@ -135,6 +154,7 @@ void testInappropriateOperands() { 1 < s; // COMPLIANT 1 < u; // COMPLIANT 1 < f; // COMPLIANT + // 1 < cf; // NON_COMPILABLE 1 > b; // NON_COMPLIANT 1 > c; // COMPLIANT @@ -142,6 +162,7 @@ void testInappropriateOperands() { 1 > s; // COMPLIANT 1 > u; // COMPLIANT 1 > f; // COMPLIANT + // 1 > cf; // NON_COMPILABLE 1 <= b; // NON_COMPLIANT 1 <= c; // COMPLIANT @@ -149,6 +170,7 @@ void testInappropriateOperands() { 1 <= s; // COMPLIANT 1 <= u; // COMPLIANT 1 <= f; // COMPLIANT + // 1 <= cf; // NON_COMPILABLE 1 >= b; // NON_COMPLIANT 1 >= c; // COMPLIANT @@ -156,6 +178,7 @@ void testInappropriateOperands() { 1 >= s; // COMPLIANT 1 >= u; // COMPLIANT 1 >= f; // COMPLIANT + // 1 >= cf; // NON_COMPILABLE b < 1; // NON_COMPLIANT c < 1; // COMPLIANT @@ -163,6 +186,7 @@ void testInappropriateOperands() { s < 1; // COMPLIANT u < 1; // COMPLIANT f < 1; // COMPLIANT + // cf < 1; // NON_COMPILABLE b > 1; // NON_COMPLIANT c > 1; // COMPLIANT @@ -170,6 +194,7 @@ void testInappropriateOperands() { s > 1; // COMPLIANT u > 1; // COMPLIANT f > 1; // COMPLIANT + // cf > 1; // NON_COMPILABLE b <= 1; // NON_COMPLIANT c <= 1; // COMPLIANT @@ -177,6 +202,7 @@ void testInappropriateOperands() { s <= 1; // COMPLIANT u <= 1; // COMPLIANT f <= 1; // COMPLIANT + // cf <= 1; // NON_COMPILABLE b >= 1; // NON_COMPLIANT c >= 1; // COMPLIANT @@ -184,34 +210,63 @@ void testInappropriateOperands() { s >= 1; // COMPLIANT u >= 1; // COMPLIANT f >= 1; // COMPLIANT - - b == 1; // COMPLIANT - c == 1; // COMPLIANT - e1 == 1; // COMPLIANT - s == 1; // COMPLIANT - u == 1; // COMPLIANT - f == 1; // COMPLIANT - - b != 1; // COMPLIANT - c != 1; // COMPLIANT - e1 != 1; // COMPLIANT - s != 1; // COMPLIANT - u != 1; // COMPLIANT - f != 1; // COMPLIANT - - 1 == b; // COMPLIANT - 1 == c; // COMPLIANT - 1 == e1; // COMPLIANT - 1 == s; // COMPLIANT - 1 == u; // COMPLIANT - 1 == f; // COMPLIANT - - 1 != b; // COMPLIANT - 1 != c; // COMPLIANT - 1 != e1; // COMPLIANT - 1 != s; // COMPLIANT - 1 != u; // COMPLIANT - 1 != f; // COMPLIANT + // cf >= 1; // NON_COMPILABLE + + b == 1; // COMPLIANT + c == 1; // COMPLIANT + e1 == 1; // COMPLIANT + s == 1; // COMPLIANT + u == 1; // COMPLIANT + f == 1; // NON_COMPLIANT + cf == 1; // NON_COMPLIANT + f == 0; // COMPLIANT + f == INFINITY; // COMPLIANT + f == -INFINITY; // COMPLIANT + cf == 0; // COMPLIANT + cf == INFINITY; // COMPLIANT + cf == -INFINITY; // COMPLIANT + + b != 1; // COMPLIANT + c != 1; // COMPLIANT + e1 != 1; // COMPLIANT + s != 1; // COMPLIANT + u != 1; // COMPLIANT + f != 1; // NON_COMPLIANT + cf != 1; // NON_COMPLIANT + f != 0; // COMPLIANT + f != INFINITY; // COMPLIANT + f != -INFINITY; // COMPLIANT + cf != 0; // COMPLIANT + cf != INFINITY; // COMPLIANT + cf != -INFINITY; // COMPLIANT + + 1 == b; // COMPLIANT + 1 == c; // COMPLIANT + 1 == e1; // COMPLIANT + 1 == s; // COMPLIANT + 1 == u; // COMPLIANT + 1 == f; // NON_COMPLIANT + 1 == cf; // NON_COMPLIANT + 0 == f; // COMPLIANT + INFINITY == f; // COMPLIANT + -INFINITY == f; // COMPLIANT + 0 == cf; // COMPLIANT + INFINITY == cf; // COMPLIANT + -INFINITY == cf; // COMPLIANT + + 1 != b; // COMPLIANT + 1 != c; // COMPLIANT + 1 != e1; // COMPLIANT + 1 != s; // COMPLIANT + 1 != u; // COMPLIANT + 1 != f; // NON_COMPLIANT + 1 != cf; // NON_COMPLIANT + 0 != f; // COMPLIANT + INFINITY != f; // COMPLIANT + -INFINITY != f; // COMPLIANT + 0 != cf; // COMPLIANT + INFINITY != cf; // COMPLIANT + -INFINITY != cf; // COMPLIANT !b; // COMPLIANT !c; // NON_COMPLIANT @@ -219,6 +274,7 @@ void testInappropriateOperands() { !s; // NON_COMPLIANT !u; // NON_COMPLIANT !f; // NON_COMPLIANT + !cf; // NON_COMPLIANT b && true; // COMPLIANT c && true; // NON_COMPLIANT @@ -226,6 +282,7 @@ void testInappropriateOperands() { s && true; // NON_COMPLIANT u && true; // NON_COMPLIANT f && true; // NON_COMPLIANT + cf && true; // NON_COMPLIANT b || false; // COMPLIANT c || false; // NON_COMPLIANT @@ -233,6 +290,7 @@ void testInappropriateOperands() { s || false; // NON_COMPLIANT u || false; // NON_COMPLIANT f || false; // NON_COMPLIANT + cf || false; // NON_COMPLIANT true && b; // COMPLIANT true && c; // NON_COMPLIANT @@ -240,6 +298,7 @@ void testInappropriateOperands() { true && s; // NON_COMPLIANT true && u; // NON_COMPLIANT true && f; // NON_COMPLIANT + true && cf; // NON_COMPLIANT false || b; // COMPLIANT false || c; // NON_COMPLIANT @@ -247,6 +306,7 @@ void testInappropriateOperands() { false || s; // NON_COMPLIANT false || u; // NON_COMPLIANT false || f; // NON_COMPLIANT + false || cf; // NON_COMPLIANT b << u; // NON_COMPLIANT c << u; // NON_COMPLIANT @@ -254,6 +314,7 @@ void testInappropriateOperands() { s << u; // NON_COMPLIANT u << u; // COMPLIANT // f << u; // NON_COMPILABLE + // cf << u; // NON_COMPILABLE b >> u; // NON_COMPLIANT c >> u; // NON_COMPLIANT @@ -261,6 +322,7 @@ void testInappropriateOperands() { s >> u; // NON_COMPLIANT u >> u; // COMPLIANT // f >> u; // NON_COMPILABLE + // cf >> u; // NON_COMPILABLE u << b; // NON_COMPLIANT u << c; // NON_COMPLIANT @@ -268,6 +330,7 @@ void testInappropriateOperands() { u << s; // NON_COMPLIANT u << u; // COMPLIANT // u << f; // NON_COMPILABLE + // u << cf; // NON_COMPILABLE u >> b; // NON_COMPLIANT u >> c; // NON_COMPLIANT @@ -275,13 +338,15 @@ void testInappropriateOperands() { u >> s; // NON_COMPLIANT u >> u; // COMPLIANT // u >> f; // NON_COMPILABLE + // u >> cf; // NON_COMPILABLE - b &u; // NON_COMPLIANT - c &u; // NON_COMPLIANT - e1 &u; // NON_COMPLIANT - s &u; // NON_COMPLIANT - u &u; // COMPLIANT + b & u; // NON_COMPLIANT + c & u; // NON_COMPLIANT + e1 & u; // NON_COMPLIANT + s & u; // NON_COMPLIANT + u & u; // COMPLIANT // f &u; // NON_COMPILABLE + // cf &u; // NON_COMPILABLE b | u; // NON_COMPLIANT c | u; // NON_COMPLIANT @@ -289,6 +354,7 @@ void testInappropriateOperands() { s | u; // NON_COMPLIANT u | u; // COMPLIANT // f | u; // NON_COMPILABLE + // cf | u; // NON_COMPILABLE b ^ u; // NON_COMPLIANT c ^ u; // NON_COMPLIANT @@ -296,13 +362,15 @@ void testInappropriateOperands() { s ^ u; // NON_COMPLIANT u ^ u; // COMPLIANT // f ^ u; // NON_COMPILABLE + // cf ^ u; // NON_COMPILABLE - u &b; // NON_COMPLIANT - u &c; // NON_COMPLIANT - u &e1; // NON_COMPLIANT - u &s; // NON_COMPLIANT - u &u; // COMPLIANT + u & b; // NON_COMPLIANT + u & c; // NON_COMPLIANT + u & e1; // NON_COMPLIANT + u & s; // NON_COMPLIANT + u & u; // COMPLIANT // u &f; // NON_COMPILABLE + // u &cf; // NON_COMPILABLE u | b; // NON_COMPLIANT u | c; // NON_COMPLIANT @@ -310,6 +378,7 @@ void testInappropriateOperands() { u | s; // NON_COMPLIANT u | u; // COMPLIANT // u | f; // NON_COMPILABLE + // u | cf; // NON_COMPILABLE u ^ b; // NON_COMPLIANT u ^ c; // NON_COMPLIANT @@ -317,6 +386,7 @@ void testInappropriateOperands() { u ^ s; // NON_COMPLIANT u ^ u; // COMPLIANT // u ^ f; // NON_COMPILABLE + // u ^ cf; // NON_COMPILABLE ~b; // NON_COMPLIANT ~c; // NON_COMPLIANT @@ -324,6 +394,7 @@ void testInappropriateOperands() { ~s; // NON_COMPLIANT ~u; // COMPLIANT //~f; // NON_COMPILABLE + ~cf; // NON_COMPLIANT b ? 1 : 2; // COMPLIANT c ? 1 : 2; // NON_COMPLIANT @@ -331,6 +402,7 @@ void testInappropriateOperands() { s ? 1 : 2; // NON_COMPLIANT u ? 1 : 2; // NON_COMPLIANT f ? 1 : 2; // NON_COMPLIANT + cf ? 1 : 2; // NON_COMPLIANT b ? b : b; // COMPLIANT b ? c : c; // COMPLIANT @@ -338,6 +410,7 @@ void testInappropriateOperands() { b ? s : s; // COMPLIANT b ? u : u; // COMPLIANT b ? f : f; // COMPLIANT + b ? cf : cf; // COMPLIANT b += 1; // NON_COMPLIANT c += 1; // COMPLIANT @@ -345,6 +418,7 @@ void testInappropriateOperands() { s += 1; // COMPLIANT u += 1; // COMPLIANT f += 1; // COMPLIANT + cf += 1; // COMPLIANT b -= 1; // NON_COMPLIANT c -= 1; // COMPLIANT @@ -352,6 +426,7 @@ void testInappropriateOperands() { s -= 1; // COMPLIANT u -= 1; // COMPLIANT f -= 1; // COMPLIANT + cf -= 1; // COMPLIANT u += b; // NON_COMPLIANT u += c; // COMPLIANT @@ -359,6 +434,7 @@ void testInappropriateOperands() { u += s; // COMPLIANT u += u; // COMPLIANT u += f; // COMPLIANT + u += cf; // COMPLIANT u -= b; // NON_COMPLIANT u -= c; // COMPLIANT @@ -366,6 +442,7 @@ void testInappropriateOperands() { u -= s; // COMPLIANT u -= u; // COMPLIANT u -= f; // COMPLIANT + u -= cf; // COMPLIANT b *= 1; // NON_COMPLIANT c *= 1; // NON_COMPLIANT @@ -373,6 +450,7 @@ void testInappropriateOperands() { s *= 1; // COMPLIANT u *= 1; // COMPLIANT f *= 1; // COMPLIANT + cf *= 1; // COMPLIANT b /= 1; // NON_COMPLIANT c /= 1; // NON_COMPLIANT @@ -380,6 +458,7 @@ void testInappropriateOperands() { s /= 1; // COMPLIANT u /= 1; // COMPLIANT f /= 1; // COMPLIANT + cf /= 1; // COMPLIANT u *= b; // NON_COMPLIANT u *= c; // NON_COMPLIANT @@ -387,6 +466,7 @@ void testInappropriateOperands() { u *= s; // COMPLIANT u *= u; // COMPLIANT u *= f; // COMPLIANT + u *= cf; // COMPLIANT u /= b; // NON_COMPLIANT u /= c; // NON_COMPLIANT @@ -394,6 +474,7 @@ void testInappropriateOperands() { u /= s; // COMPLIANT u /= u; // COMPLIANT u /= f; // COMPLIANT + u /= cf; // COMPLIANT b %= 1; // NON_COMPLIANT c %= 1; // NON_COMPLIANT @@ -401,6 +482,7 @@ void testInappropriateOperands() { s %= 1; // COMPLIANT u %= 1; // COMPLIANT // f %= 1; // NON_COMPILABLE + // cf %= 1; // NON_COMPILABLE u %= b; // NON_COMPLIANT u %= c; // NON_COMPLIANT @@ -408,6 +490,7 @@ void testInappropriateOperands() { u %= s; // COMPLIANT u %= u; // COMPLIANT // u %= f; // NON_COMPILABLE + // u %= cf; // NON_COMPILABLE b <<= u; // NON_COMPLIANT c <<= u; // NON_COMPLIANT @@ -415,6 +498,7 @@ void testInappropriateOperands() { s <<= u; // NON_COMPLIANT u <<= u; // COMPLIANT // f <<= u; // NON_COMPILABLE + // cf <<= u; // NON_COMPILABLE b >>= u; // NON_COMPLIANT c >>= u; // NON_COMPLIANT @@ -422,6 +506,7 @@ void testInappropriateOperands() { s >>= u; // NON_COMPLIANT u >>= u; // COMPLIANT // f >>= u; // NON_COMPILABLE + // cf >>= u; // NON_COMPILABLE u <<= b; // NON_COMPLIANT u <<= c; // NON_COMPLIANT @@ -429,6 +514,7 @@ void testInappropriateOperands() { u <<= s; // NON_COMPLIANT u <<= u; // COMPLIANT // u <<= f; // NON_COMPILABLE + // u <<= cf; // NON_COMPILABLE u >>= b; // NON_COMPLIANT u >>= c; // NON_COMPLIANT @@ -436,6 +522,7 @@ void testInappropriateOperands() { u >>= s; // NON_COMPLIANT u >>= u; // COMPLIANT // u >>= f; // NON_COMPILABLE + // u >>= cf; // NON_COMPILABLE b &= u; // NON_COMPLIANT c &= u; // NON_COMPLIANT @@ -443,6 +530,7 @@ void testInappropriateOperands() { s &= u; // NON_COMPLIANT u &= u; // COMPLIANT // f &= u; // NON_COMPILABLE + // cf &= u; // NON_COMPILABLE b ^= u; // NON_COMPLIANT c ^= u; // NON_COMPLIANT @@ -450,6 +538,7 @@ void testInappropriateOperands() { s ^= u; // NON_COMPLIANT u ^= u; // COMPLIANT // f ^= u; // NON_COMPILABLE + // cf ^= u; // NON_COMPILABLE b |= u; // NON_COMPLIANT c |= u; // NON_COMPLIANT @@ -457,6 +546,7 @@ void testInappropriateOperands() { s |= u; // NON_COMPLIANT u |= u; // COMPLIANT // f |= u; // NON_COMPILABLE + // cf |= u; // NON_COMPILABLE u &= b; // NON_COMPLIANT u &= c; // NON_COMPLIANT @@ -464,6 +554,7 @@ void testInappropriateOperands() { u &= s; // NON_COMPLIANT u &= u; // COMPLIANT // u &= f; // NON_COMPILABLE + // u &= cf; // NON_COMPILABLE u ^= b; // NON_COMPLIANT u ^= c; // NON_COMPLIANT @@ -471,6 +562,7 @@ void testInappropriateOperands() { u ^= s; // NON_COMPLIANT u ^= u; // COMPLIANT // u ^= f; // NON_COMPILABLE + // u ^= cf; // NON_COMPILABLE u |= b; // NON_COMPLIANT u |= c; // NON_COMPLIANT @@ -478,6 +570,7 @@ void testInappropriateOperands() { u |= s; // NON_COMPLIANT u |= u; // COMPLIANT // u |= f; // NON_COMPILABLE + // u |= cf; // NON_COMPILABLE } void pointerType() { diff --git a/c/misra/test/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.expected b/c/misra/test/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.expected index 3867abd0ca..42af35cb47 100644 --- a/c/misra/test/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.expected +++ b/c/misra/test/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.expected @@ -1,133 +1,188 @@ -| test.c:11:7:11:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | -| test.c:12:7:12:7 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | -| test.c:13:7:13:7 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | -| test.c:14:7:14:7 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | -| test.c:16:8:16:8 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | -| test.c:18:8:18:8 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | -| test.c:19:8:19:8 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | -| test.c:20:8:20:8 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | -| test.c:22:7:22:7 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | -| test.c:23:7:23:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | -| test.c:25:7:25:7 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | -| test.c:26:7:26:7 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | -| test.c:28:7:28:7 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | -| test.c:29:7:29:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | -| test.c:30:7:30:7 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | -| test.c:32:7:32:7 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | -| test.c:34:7:34:7 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | -| test.c:35:7:35:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | -| test.c:36:7:36:7 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | -| test.c:37:7:37:7 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | -| test.c:49:14:49:15 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | -| test.c:50:14:50:14 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | -| test.c:51:14:51:14 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | -| test.c:52:14:52:14 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | -| test.c:54:17:54:17 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | -| test.c:56:17:56:17 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | -| test.c:57:17:57:17 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | -| test.c:58:17:58:17 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | -| test.c:60:19:60:19 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | -| test.c:61:19:61:20 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | -| test.c:63:19:63:19 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | -| test.c:64:19:64:19 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | -| test.c:66:21:66:21 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | -| test.c:67:21:67:22 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | -| test.c:68:21:68:21 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | -| test.c:70:21:70:21 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | -| test.c:72:14:72:14 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | -| test.c:73:14:73:15 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | -| test.c:74:14:74:14 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | -| test.c:75:14:75:14 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | -| test.c:80:7:80:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | -| test.c:81:7:81:7 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | -| test.c:82:7:82:7 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | -| test.c:83:7:83:7 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | -| test.c:86:7:86:7 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | -| test.c:88:7:88:7 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | -| test.c:89:7:89:7 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | -| test.c:90:7:90:7 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | -| test.c:93:7:93:7 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | -| test.c:94:7:94:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | -| test.c:96:7:96:7 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | -| test.c:97:7:97:7 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | -| test.c:100:7:100:7 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | -| test.c:101:7:101:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | -| test.c:102:7:102:7 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | -| test.c:104:7:104:7 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | -| test.c:107:7:107:7 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | -| test.c:108:7:108:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | -| test.c:109:7:109:7 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | -| test.c:110:7:110:7 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | -| test.c:118:7:118:8 | - ... | Assignment of essentially Signed type value to an object of essentially Unsigned type. | -| test.c:119:7:119:16 | 4294967296 | Assignment of essentially Signed type value to an object of essentially Unsigned type. | -| test.c:131:8:131:8 | A | Assignment of essentially Enum Type value to an object of essentially Boolean type. | -| test.c:132:8:132:10 | 100 | Assignment of essentially Signed type value to an object of essentially Boolean type. | -| test.c:133:23:133:25 | 200 | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | -| test.c:138:8:138:11 | 1 | Assignment of essentially Boolean type value to an object of essentially Enum Type. | -| test.c:140:8:140:10 | 100 | Assignment of essentially Signed type value to an object of essentially Enum Type. | -| test.c:141:23:141:25 | 200 | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | -| test.c:146:8:146:11 | 1 | Assignment of essentially Boolean type value to an object of essentially Signed type. | -| test.c:147:8:147:8 | A | Assignment of essentially Enum Type value to an object of essentially Signed type. | -| test.c:149:23:149:25 | 200 | Assignment of essentially Unsigned type value to an object of essentially Signed type. | -| test.c:154:8:154:11 | 1 | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | -| test.c:155:8:155:8 | A | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | -| test.c:174:8:174:8 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | -| test.c:175:8:175:8 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | -| test.c:176:8:176:8 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | -| test.c:177:8:177:8 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | -| test.c:180:8:180:9 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | -| test.c:182:8:182:9 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | -| test.c:183:8:183:9 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | -| test.c:184:8:184:9 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | -| test.c:187:8:187:8 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | -| test.c:188:8:188:8 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | -| test.c:190:8:190:8 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | -| test.c:191:8:191:8 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | -| test.c:194:8:194:8 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | -| test.c:195:8:195:8 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | -| test.c:196:8:196:8 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | -| test.c:198:8:198:8 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | -| test.c:201:8:201:8 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | -| test.c:202:8:202:8 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | -| test.c:203:8:203:8 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | -| test.c:204:8:204:8 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | -| test.c:220:12:220:13 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | -| test.c:222:12:222:12 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | -| test.c:224:12:224:12 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | -| test.c:226:12:226:12 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | -| test.c:239:12:239:12 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | -| test.c:243:12:243:12 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | -| test.c:245:12:245:12 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | -| test.c:247:12:247:12 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | -| test.c:260:12:260:12 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | -| test.c:262:12:262:13 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | -| test.c:266:12:266:12 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | -| test.c:268:12:268:12 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | -| test.c:281:12:281:12 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | -| test.c:283:12:283:13 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | -| test.c:285:12:285:12 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | -| test.c:289:12:289:12 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | -| test.c:302:12:302:12 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | -| test.c:304:12:304:13 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | -| test.c:306:12:306:12 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | -| test.c:308:12:308:12 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | -| test.c:332:10:332:11 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | -| test.c:333:10:333:10 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | -| test.c:334:10:334:10 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | -| test.c:335:10:335:10 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | -| test.c:337:11:337:11 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | -| test.c:339:11:339:11 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | -| test.c:340:11:340:11 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | -| test.c:341:11:341:11 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | -| test.c:343:10:343:10 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | -| test.c:344:10:344:11 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | -| test.c:346:10:346:10 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | -| test.c:347:10:347:10 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | -| test.c:349:10:349:10 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | -| test.c:350:10:350:11 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | -| test.c:351:10:351:10 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | -| test.c:353:10:353:10 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | -| test.c:355:10:355:10 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | -| test.c:356:10:356:11 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | -| test.c:357:10:357:10 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | -| test.c:358:10:358:10 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | +| test.c:13:7:13:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | +| test.c:14:7:14:7 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | +| test.c:15:7:15:7 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | +| test.c:16:7:16:7 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | +| test.c:17:7:17:8 | cf | Assignment of essentially Complex Floating type value to an object of essentially Boolean type. | +| test.c:19:8:19:8 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | +| test.c:21:8:21:8 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | +| test.c:22:8:22:8 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | +| test.c:23:8:23:8 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | +| test.c:24:8:24:9 | cf | Assignment of essentially Complex Floating type value to an object of essentially Enum Type. | +| test.c:26:7:26:7 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | +| test.c:27:7:27:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | +| test.c:29:7:29:7 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:30:7:30:7 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | +| test.c:31:7:31:8 | cf | Assignment of essentially Complex Floating type value to an object of essentially Signed type. | +| test.c:33:7:33:7 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | +| test.c:34:7:34:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | +| test.c:35:7:35:7 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:37:7:37:7 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | +| test.c:38:7:38:8 | cf | Assignment of essentially Complex Floating type value to an object of essentially Unsigned type. | +| test.c:40:7:40:7 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | +| test.c:41:7:41:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | +| test.c:42:7:42:7 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | +| test.c:43:7:43:7 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | +| test.c:45:7:45:8 | cf | Assignment of essentially Complex Floating type value to an object of essentially Floating type. | +| test.c:47:8:47:8 | b | Assignment of essentially Boolean type value to an object of essentially Complex Floating type. | +| test.c:48:8:48:9 | e1 | Assignment of essentially Enum Type value to an object of essentially Complex Floating type. | +| test.c:49:8:49:8 | s | Assignment of essentially Signed type value to an object of essentially Complex Floating type. | +| test.c:50:8:50:8 | u | Assignment of essentially Unsigned type value to an object of essentially Complex Floating type. | +| test.c:64:14:64:15 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | +| test.c:65:14:65:14 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | +| test.c:66:14:66:14 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | +| test.c:67:14:67:14 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | +| test.c:68:15:68:16 | cf | Assignment of essentially Complex Floating type value to an object of essentially Boolean type. | +| test.c:70:17:70:17 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | +| test.c:72:17:72:17 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | +| test.c:73:17:73:17 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | +| test.c:74:17:74:17 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | +| test.c:75:18:75:19 | cf | Assignment of essentially Complex Floating type value to an object of essentially Enum Type. | +| test.c:77:19:77:19 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | +| test.c:78:19:78:20 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | +| test.c:80:19:80:19 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:81:19:81:19 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | +| test.c:82:20:82:21 | cf | Assignment of essentially Complex Floating type value to an object of essentially Signed type. | +| test.c:84:21:84:21 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | +| test.c:85:21:85:22 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | +| test.c:86:21:86:21 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:88:21:88:21 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | +| test.c:89:22:89:23 | cf | Assignment of essentially Complex Floating type value to an object of essentially Unsigned type. | +| test.c:91:14:91:14 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | +| test.c:92:14:92:15 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | +| test.c:93:14:93:14 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | +| test.c:94:14:94:14 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | +| test.c:96:15:96:16 | cf | Assignment of essentially Complex Floating type value to an object of essentially Floating type. | +| test.c:98:24:98:24 | b | Assignment of essentially Boolean type value to an object of essentially Complex Floating type. | +| test.c:99:24:99:25 | e1 | Assignment of essentially Enum Type value to an object of essentially Complex Floating type. | +| test.c:100:24:100:24 | s | Assignment of essentially Signed type value to an object of essentially Complex Floating type. | +| test.c:101:24:101:24 | u | Assignment of essentially Unsigned type value to an object of essentially Complex Floating type. | +| test.c:107:7:107:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | +| test.c:108:7:108:7 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | +| test.c:109:7:109:7 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | +| test.c:110:7:110:7 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | +| test.c:111:7:111:8 | cf | Assignment of essentially Complex Floating type value to an object of essentially Boolean type. | +| test.c:114:7:114:7 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | +| test.c:116:7:116:7 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | +| test.c:117:7:117:7 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | +| test.c:118:7:118:7 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | +| test.c:119:7:119:8 | cf | Assignment of essentially Complex Floating type value to an object of essentially Enum Type. | +| test.c:122:7:122:7 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | +| test.c:123:7:123:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | +| test.c:125:7:125:7 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:126:7:126:7 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | +| test.c:127:7:127:8 | cf | Assignment of essentially Complex Floating type value to an object of essentially Signed type. | +| test.c:130:7:130:7 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | +| test.c:131:7:131:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | +| test.c:132:7:132:7 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:134:7:134:7 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | +| test.c:135:7:135:8 | cf | Assignment of essentially Complex Floating type value to an object of essentially Unsigned type. | +| test.c:138:7:138:7 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | +| test.c:139:7:139:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | +| test.c:140:7:140:7 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | +| test.c:141:7:141:7 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | +| test.c:143:7:143:8 | cf | Assignment of essentially Complex Floating type value to an object of essentially Floating type. | +| test.c:146:7:146:7 | b | Assignment of essentially Boolean type value to an object of essentially Complex Floating type. | +| test.c:147:7:147:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Complex Floating type. | +| test.c:148:7:148:7 | s | Assignment of essentially Signed type value to an object of essentially Complex Floating type. | +| test.c:149:7:149:7 | u | Assignment of essentially Unsigned type value to an object of essentially Complex Floating type. | +| test.c:158:7:158:8 | - ... | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:159:7:159:16 | 4294967296 | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:171:8:171:8 | A | Assignment of essentially Enum Type value to an object of essentially Boolean type. | +| test.c:172:8:172:10 | 100 | Assignment of essentially Signed type value to an object of essentially Boolean type. | +| test.c:173:23:173:25 | 200 | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | +| test.c:178:8:178:11 | 1 | Assignment of essentially Boolean type value to an object of essentially Enum Type. | +| test.c:180:8:180:10 | 100 | Assignment of essentially Signed type value to an object of essentially Enum Type. | +| test.c:181:23:181:25 | 200 | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | +| test.c:186:8:186:11 | 1 | Assignment of essentially Boolean type value to an object of essentially Signed type. | +| test.c:187:8:187:8 | A | Assignment of essentially Enum Type value to an object of essentially Signed type. | +| test.c:189:23:189:25 | 200 | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:194:8:194:11 | 1 | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | +| test.c:195:8:195:8 | A | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | +| test.c:216:8:216:8 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | +| test.c:217:8:217:8 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | +| test.c:218:8:218:8 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | +| test.c:219:8:219:8 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | +| test.c:220:8:220:8 | b | Assignment of essentially Boolean type value to an object of essentially Complex Floating type. | +| test.c:223:8:223:9 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | +| test.c:225:8:225:9 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | +| test.c:226:8:226:9 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | +| test.c:227:8:227:9 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | +| test.c:228:8:228:9 | e1 | Assignment of essentially Enum Type value to an object of essentially Complex Floating type. | +| test.c:231:8:231:8 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | +| test.c:232:8:232:8 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | +| test.c:234:8:234:8 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:235:8:235:8 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | +| test.c:236:8:236:8 | s | Assignment of essentially Signed type value to an object of essentially Complex Floating type. | +| test.c:239:8:239:8 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | +| test.c:240:8:240:8 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | +| test.c:241:8:241:8 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:243:8:243:8 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | +| test.c:244:8:244:8 | u | Assignment of essentially Unsigned type value to an object of essentially Complex Floating type. | +| test.c:247:8:247:8 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | +| test.c:248:8:248:8 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | +| test.c:249:8:249:8 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | +| test.c:250:8:250:8 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | +| test.c:255:8:255:9 | cf | Assignment of essentially Complex Floating type value to an object of essentially Boolean type. | +| test.c:256:8:256:9 | cf | Assignment of essentially Complex Floating type value to an object of essentially Enum Type. | +| test.c:257:8:257:9 | cf | Assignment of essentially Complex Floating type value to an object of essentially Signed type. | +| test.c:258:8:258:9 | cf | Assignment of essentially Complex Floating type value to an object of essentially Unsigned type. | +| test.c:259:8:259:9 | cf | Assignment of essentially Complex Floating type value to an object of essentially Floating type. | +| test.c:275:12:275:13 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | +| test.c:277:12:277:12 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | +| test.c:279:12:279:12 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | +| test.c:281:12:281:12 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | +| test.c:283:12:283:13 | cf | Assignment of essentially Complex Floating type value to an object of essentially Boolean type. | +| test.c:297:12:297:12 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | +| test.c:301:12:301:12 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | +| test.c:303:12:303:12 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | +| test.c:305:12:305:12 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | +| test.c:307:12:307:13 | cf | Assignment of essentially Complex Floating type value to an object of essentially Enum Type. | +| test.c:321:12:321:12 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | +| test.c:323:12:323:13 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | +| test.c:327:12:327:12 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:329:12:329:12 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | +| test.c:331:12:331:13 | cf | Assignment of essentially Complex Floating type value to an object of essentially Signed type. | +| test.c:345:12:345:12 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | +| test.c:347:12:347:13 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | +| test.c:349:12:349:12 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:353:12:353:12 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | +| test.c:355:12:355:13 | cf | Assignment of essentially Complex Floating type value to an object of essentially Unsigned type. | +| test.c:369:12:369:12 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | +| test.c:371:12:371:13 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | +| test.c:373:12:373:12 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | +| test.c:375:12:375:12 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | +| test.c:379:12:379:13 | cf | Assignment of essentially Complex Floating type value to an object of essentially Floating type. | +| test.c:393:12:393:12 | b | Assignment of essentially Boolean type value to an object of essentially Complex Floating type. | +| test.c:395:12:395:13 | e1 | Assignment of essentially Enum Type value to an object of essentially Complex Floating type. | +| test.c:397:12:397:12 | s | Assignment of essentially Signed type value to an object of essentially Complex Floating type. | +| test.c:399:12:399:12 | u | Assignment of essentially Unsigned type value to an object of essentially Complex Floating type. | +| test.c:427:10:427:11 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | +| test.c:428:10:428:10 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | +| test.c:429:10:429:10 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | +| test.c:430:10:430:10 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | +| test.c:431:10:431:11 | cf | Assignment of essentially Complex Floating type value to an object of essentially Boolean type. | +| test.c:433:11:433:11 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | +| test.c:435:11:435:11 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | +| test.c:436:11:436:11 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | +| test.c:437:11:437:11 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | +| test.c:438:11:438:12 | cf | Assignment of essentially Complex Floating type value to an object of essentially Enum Type. | +| test.c:440:10:440:10 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | +| test.c:441:10:441:11 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | +| test.c:443:10:443:10 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:444:10:444:10 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | +| test.c:445:10:445:11 | cf | Assignment of essentially Complex Floating type value to an object of essentially Signed type. | +| test.c:447:10:447:10 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | +| test.c:448:10:448:11 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | +| test.c:449:10:449:10 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:451:10:451:10 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | +| test.c:452:10:452:11 | cf | Assignment of essentially Complex Floating type value to an object of essentially Unsigned type. | +| test.c:454:10:454:10 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | +| test.c:455:10:455:11 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | +| test.c:456:10:456:10 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | +| test.c:457:10:457:10 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | +| test.c:459:10:459:11 | cf | Assignment of essentially Complex Floating type value to an object of essentially Floating type. | +| test.c:461:11:461:11 | b | Assignment of essentially Boolean type value to an object of essentially Complex Floating type. | +| test.c:462:11:462:12 | e1 | Assignment of essentially Enum Type value to an object of essentially Complex Floating type. | +| test.c:463:11:463:11 | s | Assignment of essentially Signed type value to an object of essentially Complex Floating type. | +| test.c:464:11:464:11 | u | Assignment of essentially Unsigned type value to an object of essentially Complex Floating type. | +| test.c:473:26:473:28 | f64 | Assignment of essentially Floating type value to an object of essentially Complex Floating type. | diff --git a/c/misra/test/rules/RULE-10-3/test.c b/c/misra/test/rules/RULE-10-3/test.c index 30ab2985ae..c208890490 100644 --- a/c/misra/test/rules/RULE-10-3/test.c +++ b/c/misra/test/rules/RULE-10-3/test.c @@ -1,3 +1,4 @@ +#include #include void testAssignment() { @@ -6,36 +7,49 @@ void testAssignment() { signed int s = 100; // COMPLIANT unsigned int u = 100; // COMPLIANT - by exception 1 float f = 10.0f; // COMPLIANT + float _Complex cf = 10.0f; // COMPLIANT b = false; // COMPLIANT b = e1; // NON_COMPLIANT b = s; // NON_COMPLIANT b = u; // NON_COMPLIANT b = f; // NON_COMPLIANT + b = cf; // NON_COMPLIANT e1 = b; // NON_COMPLIANT e1 = e1; // COMPLIANT e1 = s; // NON_COMPLIANT e1 = u; // NON_COMPLIANT e1 = f; // NON_COMPLIANT + e1 = cf; // NON_COMPLIANT s = b; // NON_COMPLIANT s = e1; // NON_COMPLIANT s = s; // COMPLIANT s = u; // NON_COMPLIANT s = f; // NON_COMPLIANT + s = cf; // NON_COMPLIANT u = b; // NON_COMPLIANT u = e1; // NON_COMPLIANT u = s; // NON_COMPLIANT u = u; // COMPLIANT u = f; // NON_COMPLIANT + u = cf; // NON_COMPLIANT f = b; // NON_COMPLIANT f = e1; // NON_COMPLIANT f = s; // NON_COMPLIANT f = u; // NON_COMPLIANT f = f; // COMPLIANT + f = cf; // NON-COMPLIANT + + cf = b; // NON_COMPLIANT + cf = e1; // NON_COMPLIANT + cf = s; // NON_COMPLIANT + cf = u; // NON_COMPLIANT + cf = f; // COMPLIANT + cf = cf; // COMPLIANT } void testInitializers() { @@ -44,71 +58,97 @@ void testInitializers() { signed int s = 100; // COMPLIANT unsigned int u = 100; // COMPLIANT - by exception 1 float f = 10.0f; // COMPLIANT - - _Bool bb = b; // COMPLIANT - _Bool be = e1; // NON_COMPLIANT - _Bool bs = s; // NON_COMPLIANT - _Bool bu = u; // NON_COMPLIANT - _Bool bf = f; // NON_COMPLIANT - - enum E1 e1b = b; // NON_COMPLIANT - enum E1 e1e = e1; // COMPLIANT - enum E1 e1s = s; // NON_COMPLIANT - enum E1 e1u = u; // NON_COMPLIANT - enum E1 e1f = f; // NON_COMPLIANT - - signed int sb = b; // NON_COMPLIANT - signed int se = e1; // NON_COMPLIANT - signed int ss = s; // COMPLIANT - signed int su = u; // NON_COMPLIANT - signed int sf = f; // NON_COMPLIANT - - unsigned int ub = b; // NON_COMPLIANT - unsigned int ue = e1; // NON_COMPLIANT - unsigned int us = s; // NON_COMPLIANT - unsigned int uu = u; // COMPLIANT - unsigned int uf = f; // NON_COMPLIANT - - float fb = b; // NON_COMPLIANT - float fe = e1; // NON_COMPLIANT - float fs = s; // NON_COMPLIANT - float fu = u; // NON_COMPLIANT - float ff = f; // COMPLIANT - - _Bool ba[5] = { + float _Complex cf = 10.0f; // COMPLIANT + + _Bool bb = b; // COMPLIANT + _Bool be = e1; // NON_COMPLIANT + _Bool bs = s; // NON_COMPLIANT + _Bool bu = u; // NON_COMPLIANT + _Bool bf = f; // NON_COMPLIANT + _Bool bcf = cf; // NON_COMPLIANT + + enum E1 e1b = b; // NON_COMPLIANT + enum E1 e1e = e1; // COMPLIANT + enum E1 e1s = s; // NON_COMPLIANT + enum E1 e1u = u; // NON_COMPLIANT + enum E1 e1f = f; // NON_COMPLIANT + enum E1 e1cf = cf; // NON_COMPLIANT + + signed int sb = b; // NON_COMPLIANT + signed int se = e1; // NON_COMPLIANT + signed int ss = s; // COMPLIANT + signed int su = u; // NON_COMPLIANT + signed int sf = f; // NON_COMPLIANT + signed int scf = cf; // NON_COMPLIANT + + unsigned int ub = b; // NON_COMPLIANT + unsigned int ue = e1; // NON_COMPLIANT + unsigned int us = s; // NON_COMPLIANT + unsigned int uu = u; // COMPLIANT + unsigned int uf = f; // NON_COMPLIANT + unsigned int ucf = cf; // NON_COMPLIANT + + float fb = b; // NON_COMPLIANT + float fe = e1; // NON_COMPLIANT + float fs = s; // NON_COMPLIANT + float fu = u; // NON_COMPLIANT + float ff = f; // COMPLIANT + float fcf = cf; // NON-COMPLIANT + + float _Complex cfb = b; // NON_COMPLIANT + float _Complex cfe = e1; // NON_COMPLIANT + float _Complex cfs = s; // NON_COMPLIANT + float _Complex cfu = u; // NON_COMPLIANT + float _Complex cff = f; // COMPLIANT + float _Complex cfcf = cf; // COMPLIANT + + _Bool ba[6] = { b, // COMPLIANT e1, // NON_COMPLIANT s, // NON_COMPLIANT u, // NON_COMPLIANT - f // NON_COMPLIANT + f, // NON_COMPLIANT + cf // NON_COMPLIANT }; - enum E1 ea[5] = { + enum E1 ea[6] = { b, // NON_COMPLIANT e1, // COMPLIANT s, // NON_COMPLIANT u, // NON_COMPLIANT - f // NON_COMPLIANT + f, // NON_COMPLIANT + cf // NON_COMPLIANT }; - signed int sa[5] = { + signed int sa[6] = { b, // NON_COMPLIANT e1, // NON_COMPLIANT s, // COMPLIANT u, // NON_COMPLIANT - f // NON_COMPLIANT + f, // NON_COMPLIANT + cf // NON_COMPLIANT }; - unsigned int ua[5] = { + unsigned int ua[6] = { b, // NON_COMPLIANT e1, // NON_COMPLIANT s, // NON_COMPLIANT u, // COMPLIANT - f // NON_COMPLIANT + f, // NON_COMPLIANT + cf // NON_COMPLIANT + }; + float fa[6] = { + b, // NON_COMPLIANT + e1, // NON_COMPLIANT + s, // NON_COMPLIANT + u, // NON_COMPLIANT + f, // COMPLIANT + cf // NON_COMPLIANT }; - float fa[5] = { + float _Complex cfa[6] = { b, // NON_COMPLIANT e1, // NON_COMPLIANT s, // NON_COMPLIANT u, // NON_COMPLIANT - f // COMPLIANT + f, // COMPLIANT + cf // COMPLIANT }; } @@ -161,19 +201,22 @@ void testSwitchCase() { enum EG { EGA, EGB, EGC }; -void func(_Bool b, enum EG eg, signed int i, unsigned int u, float f); +void func(_Bool b, enum EG eg, signed int i, unsigned int u, float f, + float _Complex cf); void testFunctionCall() { - _Bool b = true; // COMPLIANT - enum EG e1 = EGA; // COMPLIANT - signed int s = 100; // COMPLIANT - unsigned int u = 100; // COMPLIANT - by exception 1 - float f = 10.0f; // COMPLIANT + _Bool b = true; // COMPLIANT + enum EG e1 = EGA; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + float _Complex cf = 10.0f; // COMPLIANT func(b, // COMPLIANT b, // NON_COMPLIANT b, // NON_COMPLIANT b, // NON_COMPLIANT + b, // NON_COMPLIANT b // NON_COMPLIANT ); @@ -181,6 +224,7 @@ void testFunctionCall() { e1, // COMPLIANT e1, // NON_COMPLIANT e1, // NON_COMPLIANT + e1, // NON_COMPLIANT e1 // NON_COMPLIANT ); @@ -188,6 +232,7 @@ void testFunctionCall() { s, // NON_COMPLIANT s, // COMPLIANT s, // NON_COMPLIANT + s, // NON_COMPLIANT s // NON_COMPLIANT ); @@ -195,6 +240,7 @@ void testFunctionCall() { u, // NON_COMPLIANT u, // NON_COMPLIANT u, // COMPLIANT + u, // NON_COMPLIANT u // NON_COMPLIANT ); @@ -202,16 +248,25 @@ void testFunctionCall() { f, // NON_COMPLIANT f, // NON_COMPLIANT f, // NON_COMPLIANT + f, // COMPLIANT f // COMPLIANT ); + + func(cf, // NON_COMPLIANT + cf, // NON_COMPLIANT + cf, // NON_COMPLIANT + cf, // NON_COMPLIANT + cf, // NON_COMPLIANT + cf); } _Bool testBoolFunctionReturn(int x) { - _Bool b = true; // COMPLIANT - enum EG e1 = EGA; // COMPLIANT - signed int s = 100; // COMPLIANT - unsigned int u = 100; // COMPLIANT - by exception 1 - float f = 10.0f; // COMPLIANT + _Bool b = true; // COMPLIANT + enum EG e1 = EGA; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + float _Complex cf = 10.0f; // COMPLIANT switch (x) { case 0: @@ -222,17 +277,20 @@ _Bool testBoolFunctionReturn(int x) { return s; // NON_COMPLIANT case 3: return u; // NON_COMPLIANT - default: + case 4: return f; // NON_COMPLIANT + default: + return cf; // NON_COMPLIANT } } enum EG testEnumFunctionReturn(int x) { - _Bool b = true; // COMPLIANT - enum EG e1 = EGA; // COMPLIANT - signed int s = 100; // COMPLIANT - unsigned int u = 100; // COMPLIANT - by exception 1 - float f = 10.0f; // COMPLIANT + _Bool b = true; // COMPLIANT + enum EG e1 = EGA; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + float _Complex cf = 10.0f; // COMPLIANT switch (x) { case 0: @@ -243,17 +301,20 @@ enum EG testEnumFunctionReturn(int x) { return s; // NON_COMPLIANT case 3: return u; // NON_COMPLIANT - default: + case 4: return f; // NON_COMPLIANT + default: + return cf; // NON_COMPLIANT } } signed int testSignedIntFunctionReturn(int x) { - _Bool b = true; // COMPLIANT - enum EG e1 = EGA; // COMPLIANT - signed int s = 100; // COMPLIANT - unsigned int u = 100; // COMPLIANT - by exception 1 - float f = 10.0f; // COMPLIANT + _Bool b = true; // COMPLIANT + enum EG e1 = EGA; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + float _Complex cf = 10.0f; // COMPLIANT switch (x) { case 0: @@ -264,17 +325,20 @@ signed int testSignedIntFunctionReturn(int x) { return s; // COMPLIANT case 3: return u; // NON_COMPLIANT - default: + case 4: return f; // NON_COMPLIANT + default: + return cf; // NON_COMPLIANT } } unsigned int testUnsignedIntFunctionReturn(int x) { - _Bool b = true; // COMPLIANT - enum EG e1 = EGA; // COMPLIANT - signed int s = 100; // COMPLIANT - unsigned int u = 100; // COMPLIANT - by exception 1 - float f = 10.0f; // COMPLIANT + _Bool b = true; // COMPLIANT + enum EG e1 = EGA; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + float _Complex cf = 10.0f; // COMPLIANT switch (x) { case 0: @@ -285,17 +349,20 @@ unsigned int testUnsignedIntFunctionReturn(int x) { return s; // NON_COMPLIANT case 3: return u; // COMPLIANT - default: + case 4: return f; // NON_COMPLIANT + default: + return cf; // NON_COMPLIANT } } float testFloatFunctionReturn(int x) { - _Bool b = true; // COMPLIANT - enum EG e1 = EGA; // COMPLIANT - signed int s = 100; // COMPLIANT - unsigned int u = 100; // COMPLIANT - by exception 1 - float f = 10.0f; // COMPLIANT + _Bool b = true; // COMPLIANT + enum EG e1 = EGA; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + float _Complex cf = 10.0f; // COMPLIANT switch (x) { case 0: @@ -306,8 +373,34 @@ float testFloatFunctionReturn(int x) { return s; // NON_COMPLIANT case 3: return u; // NON_COMPLIANT + case 4: + return f; // COMPLIANT default: + return cf; // NON_COMPLIANT + } +} + +float _Complex testComplexFunctionReturn(int x) { + _Bool b = true; // COMPLIANT + enum EG e1 = EGA; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + float _Complex cf = 10.0f; // COMPLIANT + + switch (x) { + case 0: + return b; // NON_COMPLIANT + case 1: + return e1; // NON_COMPLIANT + case 2: + return s; // NON_COMPLIANT + case 3: + return u; // NON_COMPLIANT + case 4: return f; // COMPLIANT + default: + return cf; // COMPLIANT } } @@ -317,14 +410,16 @@ struct S1 { signed int s; unsigned int u; float f; + float _Complex cf; }; void testStructAssignment() { - _Bool b = true; // COMPLIANT - enum EG e1 = EGA; // COMPLIANT - signed int s = 100; // COMPLIANT - unsigned int u = 100; // COMPLIANT - by exception 1 - float f = 10.0f; // COMPLIANT + _Bool b = true; // COMPLIANT + enum EG e1 = EGA; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + float _Complex cf = 10.0f; // COMPLIANT struct S1 s1; @@ -333,28 +428,54 @@ void testStructAssignment() { s1.b = s; // NON_COMPLIANT s1.b = u; // NON_COMPLIANT s1.b = f; // NON_COMPLIANT + s1.b = cf; // NON_COMPLIANT s1.e1 = b; // NON_COMPLIANT s1.e1 = e1; // COMPLIANT s1.e1 = s; // NON_COMPLIANT s1.e1 = u; // NON_COMPLIANT s1.e1 = f; // NON_COMPLIANT + s1.e1 = cf; // NON_COMPLIANT s1.s = b; // NON_COMPLIANT s1.s = e1; // NON_COMPLIANT s1.s = s; // COMPLIANT s1.s = u; // NON_COMPLIANT s1.s = f; // NON_COMPLIANT + s1.s = cf; // NON_COMPLIANT s1.u = b; // NON_COMPLIANT s1.u = e1; // NON_COMPLIANT s1.u = s; // NON_COMPLIANT s1.u = u; // COMPLIANT s1.u = f; // NON_COMPLIANT + s1.u = cf; // NON_COMPLIANT s1.f = b; // NON_COMPLIANT s1.f = e1; // NON_COMPLIANT s1.f = s; // NON_COMPLIANT s1.f = u; // NON_COMPLIANT s1.f = f; // COMPLIANT + s1.f = cf; // NON_COMPLIANT + + s1.cf = b; // NON_COMPLIANT + s1.cf = e1; // NON_COMPLIANT + s1.cf = s; // NON_COMPLIANT + s1.cf = u; // NON_COMPLIANT + s1.cf = f; // COMPLIANT + s1.cf = cf; // COMPLIANT +} + +void testException4() { + float f32 = 10.0f; // COMPLIANT + double f64 = 10.0f; // COMPLIANT + float _Complex cf32a = f32; // COMPLIANT + float _Complex cf32b = f64; // NON_COMPLIANT + double _Complex cf64a = f32; // COMPLIANT + double _Complex cf64b = f64; // COMPLIANT + + double _Complex f64byparts_a = 10.0i; // COMPLIANT + double _Complex f64byparts_b = 10.0 * I; // COMPLIANT + double _Complex f64byparts_c = 10.0f + 10.0i; // COMPLIANT + double _Complex f64byparts_d = 10.0f + 10.0f * I; // COMPLIANT } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.expected b/c/misra/test/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.expected index 333c3ad581..c85f2a447e 100644 --- a/c/misra/test/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.expected +++ b/c/misra/test/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.expected @@ -1,10 +1,13 @@ -| test.c:14:3:14:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Unsigned type, right operand: essentially Signed type). | -| test.c:15:3:15:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Unsigned type). | -| test.c:16:3:16:10 | ... += ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Unsigned type). | -| test.c:17:3:17:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Floating type, right operand: essentially Signed type). | -| test.c:18:3:18:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Floating type). | -| test.c:19:3:19:10 | ... += ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Floating type). | -| test.c:27:3:27:9 | ... - ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Character type). | -| test.c:28:3:28:10 | ... -= ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Character type). | -| test.c:34:3:34:11 | ... < ... | The operands of this operator with usual arithmetic conversions have mismatched essentially Enum types (left operand: E1, right operand: E2). | -| test.c:35:3:35:7 | ... < ... | The operands of this operator with usual arithmetic conversions have mismatched essentially Enum types (left operand: E1, right operand: E2). | +| test.c:15:3:15:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Unsigned type, right operand: essentially Signed type). | +| test.c:16:3:16:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Unsigned type). | +| test.c:17:3:17:10 | ... += ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Unsigned type). | +| test.c:18:3:18:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Floating type, right operand: essentially Signed type). | +| test.c:19:3:19:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Floating type). | +| test.c:20:3:20:10 | ... += ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Floating type). | +| test.c:21:3:21:10 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Complex Floating type, right operand: essentially Signed type). | +| test.c:22:3:22:10 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Complex Floating type). | +| test.c:23:3:23:11 | ... += ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Complex Floating type). | +| test.c:31:3:31:9 | ... - ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Character type). | +| test.c:32:3:32:10 | ... -= ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Character type). | +| test.c:43:3:43:11 | ... < ... | The operands of this operator with usual arithmetic conversions have mismatched essentially Enum types (left operand: E1, right operand: E2). | +| test.c:44:3:44:7 | ... < ... | The operands of this operator with usual arithmetic conversions have mismatched essentially Enum types (left operand: E1, right operand: E2). | diff --git a/c/misra/test/rules/RULE-10-4/test.c b/c/misra/test/rules/RULE-10-4/test.c index cbcb7191f6..223aacbdad 100644 --- a/c/misra/test/rules/RULE-10-4/test.c +++ b/c/misra/test/rules/RULE-10-4/test.c @@ -3,6 +3,7 @@ void testOps() { signed long long s64 = 100; unsigned int u = 100; float f = 10.0f; + float _Complex cf = 10.0f; char c = 'A'; s32 + s32; // COMPLIANT @@ -17,6 +18,9 @@ void testOps() { f + s32; // NON_COMPLIANT s32 + f; // NON_COMPLIANT s32 += f; // NON_COMPLIANT + cf + s32; // NON_COMPLIANT + s32 + cf; // NON_COMPLIANT + s32 += cf; // NON_COMPLIANT c + s32; // COMPLIANT - by exception c += s32; // COMPLIANT - by exception @@ -27,6 +31,11 @@ void testOps() { s32 - c; // NON_COMPLIANT s32 -= c; // NON_COMPLIANT + cf + f; // COMPLIANT - by exception + f + cf; // COMPLIANT - by exception + cf *f; // COMPLIANT - by exception + f *cf; // COMPLIANT - by exception + enum E1 { A, B, C } e1a; enum E2 { D, E, F } e2a; e1a < e1a; // COMPLIANT diff --git a/c/misra/test/rules/RULE-10-5/InappropriateEssentialTypeCast.expected b/c/misra/test/rules/RULE-10-5/InappropriateEssentialTypeCast.expected index 731ad9f312..2f4c38eb95 100644 --- a/c/misra/test/rules/RULE-10-5/InappropriateEssentialTypeCast.expected +++ b/c/misra/test/rules/RULE-10-5/InappropriateEssentialTypeCast.expected @@ -1,20 +1,25 @@ -| test.c:9:3:9:9 | (char)... | Incompatible cast from essentially Boolean type to essentially Character type. | -| test.c:10:3:10:13 | (E1)... | Incompatible cast from essentially Boolean type to essentially Enum Type. | -| test.c:11:3:11:15 | (signed int)... | Incompatible cast from essentially Boolean type to essentially Signed type. | -| test.c:12:3:12:17 | (unsigned int)... | Incompatible cast from essentially Boolean type to essentially Unsigned type. | -| test.c:13:3:13:10 | (float)... | Incompatible cast from essentially Boolean type to essentially Floating type. | -| test.c:16:3:16:11 | (bool)... | Incompatible cast from essentially Character type to essentially Boolean type. | -| test.c:18:3:18:13 | (E1)... | Incompatible cast from essentially Character type to essentially Enum Type. | -| test.c:21:3:21:10 | (float)... | Incompatible cast from essentially Character type to essentially Floating type. | -| test.c:24:3:24:11 | (bool)... | Incompatible cast from essentially Enum Type to essentially Boolean type. | -| test.c:26:3:26:13 | (E1)... | Incompatible cast from E2 to E1. | -| test.c:33:3:33:11 | (bool)... | Incompatible cast from essentially Signed type to essentially Boolean type. | -| test.c:35:3:35:13 | (E1)... | Incompatible cast from essentially Signed type to essentially Enum Type. | -| test.c:41:3:41:11 | (bool)... | Incompatible cast from essentially Unsigned type to essentially Boolean type. | -| test.c:43:3:43:13 | (E1)... | Incompatible cast from essentially Unsigned type to essentially Enum Type. | -| test.c:49:3:49:11 | (bool)... | Incompatible cast from essentially Floating type to essentially Boolean type. | -| test.c:50:3:50:9 | (char)... | Incompatible cast from essentially Floating type to essentially Character type. | -| test.c:51:3:51:13 | (E1)... | Incompatible cast from essentially Floating type to essentially Enum Type. | -| test.c:68:3:68:10 | (bool)... | Incompatible cast from essentially Signed type to essentially Boolean type. | -| test.c:72:3:72:16 | (MyBool)... | Incompatible cast from essentially Signed type to essentially Boolean type. | -| test.c:76:3:76:12 | (boolean)... | Incompatible cast from essentially Signed type to essentially Boolean type. | +| test.c:10:3:10:9 | (char)... | Incompatible cast from essentially Boolean type to essentially Character type. | +| test.c:11:3:11:13 | (E1)... | Incompatible cast from essentially Boolean type to essentially Enum Type. | +| test.c:12:3:12:15 | (signed int)... | Incompatible cast from essentially Boolean type to essentially Signed type. | +| test.c:13:3:13:17 | (unsigned int)... | Incompatible cast from essentially Boolean type to essentially Unsigned type. | +| test.c:14:3:14:10 | (float)... | Incompatible cast from essentially Boolean type to essentially Floating type. | +| test.c:15:3:15:20 | (_Complex float)... | Incompatible cast from essentially Boolean type to essentially Complex Floating type. | +| test.c:18:3:18:11 | (bool)... | Incompatible cast from essentially Character type to essentially Boolean type. | +| test.c:20:3:20:13 | (E1)... | Incompatible cast from essentially Character type to essentially Enum Type. | +| test.c:23:3:23:10 | (float)... | Incompatible cast from essentially Character type to essentially Floating type. | +| test.c:24:3:24:20 | (_Complex float)... | Incompatible cast from essentially Character type to essentially Complex Floating type. | +| test.c:27:3:27:11 | (bool)... | Incompatible cast from essentially Enum Type to essentially Boolean type. | +| test.c:29:3:29:13 | (E1)... | Incompatible cast from E2 to E1. | +| test.c:37:3:37:11 | (bool)... | Incompatible cast from essentially Signed type to essentially Boolean type. | +| test.c:39:3:39:13 | (E1)... | Incompatible cast from essentially Signed type to essentially Enum Type. | +| test.c:46:3:46:11 | (bool)... | Incompatible cast from essentially Unsigned type to essentially Boolean type. | +| test.c:48:3:48:13 | (E1)... | Incompatible cast from essentially Unsigned type to essentially Enum Type. | +| test.c:55:3:55:11 | (bool)... | Incompatible cast from essentially Floating type to essentially Boolean type. | +| test.c:56:3:56:9 | (char)... | Incompatible cast from essentially Floating type to essentially Character type. | +| test.c:57:3:57:13 | (E1)... | Incompatible cast from essentially Floating type to essentially Enum Type. | +| test.c:64:3:64:12 | (bool)... | Incompatible cast from essentially Complex Floating type to essentially Boolean type. | +| test.c:65:3:65:10 | (char)... | Incompatible cast from essentially Complex Floating type to essentially Character type. | +| test.c:66:3:66:14 | (E1)... | Incompatible cast from essentially Complex Floating type to essentially Enum Type. | +| test.c:84:3:84:10 | (bool)... | Incompatible cast from essentially Signed type to essentially Boolean type. | +| test.c:88:3:88:16 | (MyBool)... | Incompatible cast from essentially Signed type to essentially Boolean type. | +| test.c:92:3:92:12 | (boolean)... | Incompatible cast from essentially Signed type to essentially Boolean type. | diff --git a/c/misra/test/rules/RULE-10-5/test.c b/c/misra/test/rules/RULE-10-5/test.c index dbc5939f0f..d7a6d878f1 100644 --- a/c/misra/test/rules/RULE-10-5/test.c +++ b/c/misra/test/rules/RULE-10-5/test.c @@ -1,3 +1,4 @@ +#include #include void testIncompatibleCasts() { @@ -5,53 +6,68 @@ void testIncompatibleCasts() { _Bool b = true; - (_Bool) b; // COMPLIANT - (char)b; // NON_COMPLIANT - (enum E1) b; // NON_COMPLIANT - (signed int)b; // NON_COMPLIANT - (unsigned int)b; // NON_COMPLIANT - (float)b; // NON_COMPLIANT + (_Bool) b; // COMPLIANT + (char)b; // NON_COMPLIANT + (enum E1) b; // NON_COMPLIANT + (signed int)b; // NON_COMPLIANT + (unsigned int)b; // NON_COMPLIANT + (float)b; // NON_COMPLIANT + (float _Complex) b; // NON_COMPLIANT char c = 100; - (_Bool) c; // NON_COMPLIANT - (char)c; // COMPLIANT - (enum E1) c; // NON_COMPLIANT - (signed int)c; // COMPLIANT - (unsigned int)c; // COMPLIANT - (float)c; // NON_COMPLIANT + (_Bool) c; // NON_COMPLIANT + (char)c; // COMPLIANT + (enum E1) c; // NON_COMPLIANT + (signed int)c; // COMPLIANT + (unsigned int)c; // COMPLIANT + (float)c; // NON_COMPLIANT + (float _Complex) c; // NON_COMPLIANT enum E2 { C, D } e = C; - (_Bool) e; // NON_COMPLIANT - (char)e; // COMPLIANT - (enum E1) e; // NON_COMPLIANT - (enum E2) e; // COMPLIANT - (signed int)e; // COMPLIANT - (unsigned int)e; // COMPLIANT - (float)e; // COMPLIANT + (_Bool) e; // NON_COMPLIANT + (char)e; // COMPLIANT + (enum E1) e; // NON_COMPLIANT + (enum E2) e; // COMPLIANT + (signed int)e; // COMPLIANT + (unsigned int)e; // COMPLIANT + (float)e; // COMPLIANT + (float _Complex) e; // COMPLIANT signed int i = 100; - (_Bool) i; // NON_COMPLIANT - (char)i; // COMPLIANT - (enum E1) i; // NON_COMPLIANT - (signed int)i; // COMPLIANT - (unsigned int)i; // COMPLIANT - (float)i; // COMPLIANT + (_Bool) i; // NON_COMPLIANT + (char)i; // COMPLIANT + (enum E1) i; // NON_COMPLIANT + (signed int)i; // COMPLIANT + (unsigned int)i; // COMPLIANT + (float)i; // COMPLIANT + (float _Complex) i; // COMPLIANT unsigned int u = 100; - (_Bool) u; // NON_COMPLIANT - (char)u; // COMPLIANT - (enum E1) u; // NON_COMPLIANT - (signed int)u; // COMPLIANT - (unsigned int)u; // COMPLIANT - (float)u; // COMPLIANT + (_Bool) u; // NON_COMPLIANT + (char)u; // COMPLIANT + (enum E1) u; // NON_COMPLIANT + (signed int)u; // COMPLIANT + (unsigned int)u; // COMPLIANT + (float)u; // COMPLIANT + (float _Complex) u; // COMPLIANT float f = 100.0; - (_Bool) f; // NON_COMPLIANT - (char)f; // NON_COMPLIANT - (enum E1) f; // NON_COMPLIANT - (signed int)f; // COMPLIANT - (unsigned int)f; // COMPLIANT - (float)f; // COMPLIANT + (_Bool) f; // NON_COMPLIANT + (char)f; // NON_COMPLIANT + (enum E1) f; // NON_COMPLIANT + (signed int)f; // COMPLIANT + (unsigned int)f; // COMPLIANT + (float)f; // COMPLIANT + (float _Complex) f; // COMPLIANT + + float _Complex cf = 100.0; + (_Bool) cf; // NON_COMPLIANT + (char)cf; // NON_COMPLIANT + (enum E1) cf; // NON_COMPLIANT + (signed int)cf; // COMPLIANT + (unsigned int)cf; // COMPLIANT + (float)cf; // COMPLIANT + (float _Complex) cf; // COMPLIANT } void testImplicit() { diff --git a/c/misra/test/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.expected b/c/misra/test/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.expected index 30b5e1efb7..ea8fc433b1 100644 --- a/c/misra/test/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.expected +++ b/c/misra/test/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.expected @@ -1,3 +1,7 @@ | test.c:5:3:5:16 | ... + ... | Implicit conversion of $@ from unsigned short to unsigned int | test.c:5:9:5:16 | ... * ... | composite op | | test.c:6:3:6:18 | ... * ... | Implicit conversion of $@ from unsigned short to unsigned int | test.c:6:9:6:17 | ... + ... | composite op | | test.c:9:3:9:20 | ... += ... | Implicit conversion of $@ from unsigned short to unsigned int | test.c:9:11:9:19 | ... + ... | composite op | +| test.c:24:3:24:19 | ... + ... | Implicit conversion of $@ from float to double | test.c:24:10:24:18 | ... + ... | composite op | +| test.c:25:3:25:21 | ... + ... | Implicit conversion of $@ from _Complex float to double | test.c:25:10:25:20 | ... + ... | composite op | +| test.c:26:3:26:20 | ... + ... | Implicit conversion of $@ from float to _Complex double | test.c:26:11:26:19 | ... + ... | composite op | +| test.c:27:3:27:22 | ... + ... | Implicit conversion of $@ from _Complex float to _Complex double | test.c:27:11:27:21 | ... + ... | composite op | diff --git a/c/misra/test/rules/RULE-10-7/test.c b/c/misra/test/rules/RULE-10-7/test.c index 59d0ed1437..7aaa1847e4 100644 --- a/c/misra/test/rules/RULE-10-7/test.c +++ b/c/misra/test/rules/RULE-10-7/test.c @@ -11,4 +11,18 @@ void testComposite() { signed int s32 = 100; s32 += (u16 + u16); // // ignored - prohibited by Rule 10.4 + + float f32 = 10.0f; + double f64 = 10.0f; + float _Complex cf32 = 10.0f; + double _Complex cf64 = 10.0f; + + f32 + (f32 + f32); // COMPLIANT + cf32 + (cf32 + cf32); // COMPLIANT + f32 + (cf32 + cf32); // COMPLIANT + cf32 + (f32 + f32); // COMPLIANT + f64 + (f32 + f32); // NON_COMPLIANT + f64 + (cf32 + cf32); // NON_COMPLIANT + cf64 + (f32 + f32); // NON_COMPLIANT + cf64 + (cf32 + cf32); // NON_COMPLIANT } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-8/InappropriateCastOfCompositeExpression.expected b/c/misra/test/rules/RULE-10-8/InappropriateCastOfCompositeExpression.expected index 85e2471a41..659b41199d 100644 --- a/c/misra/test/rules/RULE-10-8/InappropriateCastOfCompositeExpression.expected +++ b/c/misra/test/rules/RULE-10-8/InappropriateCastOfCompositeExpression.expected @@ -1,4 +1,10 @@ | test.c:4:16:4:20 | ... + ... | Cast from essentially Unsigned type to essentially Signed type changes type category. | | test.c:5:18:5:22 | ... + ... | Cast from essentially Signed type to essentially Unsigned type changes type category. | -| test.c:14:18:14:24 | ... + ... | Cast from essentially Unsigned type to essentially Unsigned type widens type. | -| test.c:20:16:20:22 | ... + ... | Cast from essentially Signed type to essentially Signed type widens type. | +| test.c:11:11:11:15 | ... + ... | Cast from essentially Unsigned type to essentially Floating type changes type category. | +| test.c:12:20:12:24 | ... + ... | Cast from essentially Unsigned type to essentially Complex Floating type changes type category. | +| test.c:13:18:13:22 | ... + ... | Cast from essentially Floating type to essentially Unsigned type changes type category. | +| test.c:14:18:14:24 | ... + ... | Cast from essentially Complex Floating type to essentially Unsigned type changes type category. | +| test.c:25:18:25:24 | ... + ... | Cast from essentially Unsigned type to essentially Unsigned type widens type. | +| test.c:31:16:31:22 | ... + ... | Cast from essentially Signed type to essentially Signed type widens type. | +| test.c:43:12:43:20 | ... + ... | Cast from essentially Floating type to essentially Floating type widens type. | +| test.c:44:12:44:22 | ... + ... | Cast from essentially Complex Floating type to essentially Floating type widens type. | diff --git a/c/misra/test/rules/RULE-10-8/test.c b/c/misra/test/rules/RULE-10-8/test.c index 41efb6b8d8..31294ed550 100644 --- a/c/misra/test/rules/RULE-10-8/test.c +++ b/c/misra/test/rules/RULE-10-8/test.c @@ -5,6 +5,17 @@ void testDifferentEssentialType() { (unsigned int)(s + s); // NON_COMPLIANT (signed int)(s + s); // COMPLIANT (unsigned int)(u + u); // COMPLIANT + + float f = 1.0; + float _Complex cf = 1.0; + (float)(u + u); // NON_COMPLIANT + (float _Complex)(u + u); // NON_COMPLIANT + (unsigned int)(f + f); // NON_COMPLIANT + (unsigned int)(cf + cf); // NON_COMPLIANT + (float)(f + f); // COMPLIANT + (float)(cf + cf); // COMPLIANT + (float _Complex)(f + f); // COMPLIANT + (float _Complex)(cf + cf); // COMPLIANT } void testWiderType() { @@ -19,4 +30,18 @@ void testWiderType() { (signed int)(ss + ss); // NON_COMPLIANT (signed short)(s + s); // COMPLIANT + + float f32 = 1.0; + double f64 = 1.0; + float _Complex cf32 = 1.0; + double _Complex cf64 = 1.0; + + (float)(f32 + f32); // COMPLIANT + (float)(cf32 + cf32); // COMPLIANT + (float _Complex)(f32 + f32); // COMPLIANT + (float _Complex)(cf32 + cf32); // COMPLIANT + (double)(f32 + f32); // NON_COMPLIANT + (double)(cf32 + cf32); // NON_COMPLIANT + (double _Complex)(f64 + f64); // COMPLIANT + (double _Complex)(cf64 + cf64); // COMPLIANT } \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/Emergent.qll b/cpp/common/src/codingstandards/cpp/Emergent.qll index 9036c12bd7..30f1df58e4 100644 --- a/cpp/common/src/codingstandards/cpp/Emergent.qll +++ b/cpp/common/src/codingstandards/cpp/Emergent.qll @@ -6,44 +6,10 @@ import cpp module C11 { abstract class EmergentLanguageFeature extends Element { } - class AlignAsAttribute extends EmergentLanguageFeature, Attribute { - AlignAsAttribute() { getName() = "_Alignas" } - } - - class AtomicVariableSpecifier extends EmergentLanguageFeature, Variable { - AtomicVariableSpecifier() { - getType().(DerivedType).getBaseType*().getASpecifier().getName() = "atomic" - } - } - - class AtomicDeclaration extends EmergentLanguageFeature, Declaration { - AtomicDeclaration() { getASpecifier().getName() = "atomic" } - } - - class ThreadLocalDeclaration extends EmergentLanguageFeature, Declaration { - ThreadLocalDeclaration() { getASpecifier().getName() = "is_thread_local" } - } - - class EmergentHeader extends EmergentLanguageFeature, Include { - EmergentHeader() { - getIncludedFile().getBaseName() = ["stdalign.h", "stdatomic.h", "stdnoreturn.h", "threads.h"] - } - } - class LibExt1Macro extends EmergentLanguageFeature, Macro { LibExt1Macro() { getName() = "__STDC_WANT_LIB_EXT1__" and getBody() = "1" } } - - class GenericMacro extends EmergentLanguageFeature, Macro { - GenericMacro() { getBody().indexOf("_Generic") = 0 } - } - - class NoReturnSpecificer extends EmergentLanguageFeature, Function { - NoReturnSpecificer() { getASpecifier().getName() = "noreturn" } - } - - class AlignOf extends EmergentLanguageFeature, AlignofTypeOperator { } } From 72250d74fb596b8403e0da0d1b315bc783b3c1fd Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 12 Dec 2024 17:26:47 -0800 Subject: [PATCH 105/370] Add changelog --- .../2024-12-12-complex-floating-essential-types.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 change_notes/2024-12-12-complex-floating-essential-types.md diff --git a/change_notes/2024-12-12-complex-floating-essential-types.md b/change_notes/2024-12-12-complex-floating-essential-types.md new file mode 100644 index 0000000000..5f5b6b519f --- /dev/null +++ b/change_notes/2024-12-12-complex-floating-essential-types.md @@ -0,0 +1,8 @@ + - `EssentialType` - for all queries related to essential types: + - Complex floating types are now considered a different essential type than real floating types. + - `RULE-10-1` `RULE-10-3`, `RULE-10-4`, `RULE-10-5`, `RULE-10-7`, `RULE-10-8` - `OperandsOfAnInappropriateEssentialType.ql`, `AssignmentOfIncompatibleEssentialType.ql`, `OperandsWithMismatchedEssentialTypeCategory.ql`, `InappropriateEssentialTypeCast.ql`, `ImplicitConversionOfCompositeExpression.ql`, `InappropriateCastOfCompositeExpression.ql`: + - Updates to rules handling complex floating types in MISRA-C 2012 Amendment 3 have been implemented. +- `RULE-14-1`, `LoopOverEssentiallyFloatType.ql`: + - Query updated to account for the existence of complex essentially floating point types. No change in query results or performance expected. + - `DIR-4-6` - `PlainNumericalTypeUsedOverExplicitTypedef.ql`: + - Updates from MISRA-C 2012 Amendment 3 specifying complex fixed width typedef support has been implemented. \ No newline at end of file From 6625d1ba9ff6dfaa5d4efe71c96c288b1dd0bb81 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 12 Dec 2024 17:36:09 -0800 Subject: [PATCH 106/370] format test case --- c/misra/test/rules/RULE-10-1/test.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/c/misra/test/rules/RULE-10-1/test.c b/c/misra/test/rules/RULE-10-1/test.c index f8d1a4fca5..3b96c7151d 100644 --- a/c/misra/test/rules/RULE-10-1/test.c +++ b/c/misra/test/rules/RULE-10-1/test.c @@ -340,11 +340,11 @@ void testInappropriateOperands() { // u >> f; // NON_COMPILABLE // u >> cf; // NON_COMPILABLE - b & u; // NON_COMPLIANT - c & u; // NON_COMPLIANT - e1 & u; // NON_COMPLIANT - s & u; // NON_COMPLIANT - u & u; // COMPLIANT + b &u; // NON_COMPLIANT + c &u; // NON_COMPLIANT + e1 &u; // NON_COMPLIANT + s &u; // NON_COMPLIANT + u &u; // COMPLIANT // f &u; // NON_COMPILABLE // cf &u; // NON_COMPILABLE @@ -364,11 +364,11 @@ void testInappropriateOperands() { // f ^ u; // NON_COMPILABLE // cf ^ u; // NON_COMPILABLE - u & b; // NON_COMPLIANT - u & c; // NON_COMPLIANT - u & e1; // NON_COMPLIANT - u & s; // NON_COMPLIANT - u & u; // COMPLIANT + u &b; // NON_COMPLIANT + u &c; // NON_COMPLIANT + u &e1; // NON_COMPLIANT + u &s; // NON_COMPLIANT + u &u; // COMPLIANT // u &f; // NON_COMPILABLE // u &cf; // NON_COMPILABLE From a7d2c136f6a7734788005190ca359faee5624789 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 13 Dec 2024 11:07:04 -0800 Subject: [PATCH 107/370] Attempt fix tests --- .../ListGuidelineRecategorizations.expected | 2 +- .../guideline_recategorizations/invalid/coding-standards.xml | 2 +- .../guideline_recategorizations/invalid/coding-standards.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/common/test/guideline_recategorizations/ListGuidelineRecategorizations.expected b/cpp/common/test/guideline_recategorizations/ListGuidelineRecategorizations.expected index 0a8aeb9ba1..8e6a397620 100644 --- a/cpp/common/test/guideline_recategorizations/ListGuidelineRecategorizations.expected +++ b/cpp/common/test/guideline_recategorizations/ListGuidelineRecategorizations.expected @@ -5,4 +5,4 @@ | A10-4-1 | advisory | required | | A11-0-1 | advisory | mandatory | | CON50-CPP | rule | required | -| RULE-13-6 | mandatory | required | +| RULE-9-1 | mandatory | required | diff --git a/cpp/common/test/guideline_recategorizations/invalid/coding-standards.xml b/cpp/common/test/guideline_recategorizations/invalid/coding-standards.xml index d89f27050b..dfb7b6f13c 100644 --- a/cpp/common/test/guideline_recategorizations/invalid/coding-standards.xml +++ b/cpp/common/test/guideline_recategorizations/invalid/coding-standards.xml @@ -15,7 +15,7 @@ mandatory - RULE-13-6 + RULE-9-1 required diff --git a/cpp/common/test/guideline_recategorizations/invalid/coding-standards.yml b/cpp/common/test/guideline_recategorizations/invalid/coding-standards.yml index 89e562c05c..cd6abbf120 100644 --- a/cpp/common/test/guideline_recategorizations/invalid/coding-standards.yml +++ b/cpp/common/test/guideline_recategorizations/invalid/coding-standards.yml @@ -5,7 +5,7 @@ guideline-recategorizations: category: "disapplied" - rule-id: "A1-4-3" category: "mandatory" - - rule-id: "RULE-13-6" + - rule-id: "RULE-9-1" category: "required" - rule-id: "CON50-CPP" category: "required" From 9f60b60991ea74450c65b1d0ae6975c4dab2c4aa Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 13 Dec 2024 11:11:30 -0800 Subject: [PATCH 108/370] Fix test expectations post format --- .../OperandsOfAnInappropriateEssentialType.expected | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/c/misra/test/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.expected b/c/misra/test/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.expected index aad8dadf99..7a8fd1e07c 100644 --- a/c/misra/test/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.expected +++ b/c/misra/test/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.expected @@ -119,10 +119,10 @@ | test.c:360:3:360:3 | c | Operand of essentially Charater type interpreted as a numeric value. | | test.c:361:3:361:4 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | | test.c:362:3:362:3 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | -| test.c:367:7:367:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | -| test.c:368:7:368:7 | c | Operand of essentially Charater type interpreted as a numeric value. | -| test.c:369:7:369:8 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | -| test.c:370:7:370:7 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:367:6:367:6 | b | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:368:6:368:6 | c | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:369:6:369:7 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:370:6:370:6 | s | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | | test.c:375:7:375:7 | b | Operand of essentially Boolean type interpreted as a numeric value. | | test.c:376:7:376:7 | c | Operand of essentially Charater type interpreted as a numeric value. | | test.c:377:7:377:8 | e1 | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | From b5e55952c362062eab6efb1f1424682c8d20aa0e Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 13 Dec 2024 11:42:50 -0800 Subject: [PATCH 109/370] Fix deviations report tests --- .../reports/test-data/deviations/invalid/coding-standards.yml | 4 ++-- .../guideline_recategorizations_report.md.expected | 4 ++-- .../guideline-recategorizations/invalid/coding-standards.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/reports/test-data/deviations/invalid/coding-standards.yml b/scripts/reports/test-data/deviations/invalid/coding-standards.yml index 7b12c7a8c2..1ce8cc718a 100644 --- a/scripts/reports/test-data/deviations/invalid/coding-standards.yml +++ b/scripts/reports/test-data/deviations/invalid/coding-standards.yml @@ -44,8 +44,8 @@ deviations: permit-id: non-existing-permit - permit-id: DP1 - permit-id: DP2 - - rule-id: RULE-13-6 - query-id: c/misra/sizeof-operand-with-side-effect + - rule-id: RULE-9-1 + query-id: c/misra/object-with-auto-storage-duration-read-before-init deviation-permits: - permit-id: DP1 justification: foo bar baz diff --git a/scripts/reports/test-data/guideline-recategorizations/guideline_recategorizations_report.md.expected b/scripts/reports/test-data/guideline-recategorizations/guideline_recategorizations_report.md.expected index 54fb25ae83..425eba1bc3 100644 --- a/scripts/reports/test-data/guideline-recategorizations/guideline_recategorizations_report.md.expected +++ b/scripts/reports/test-data/guideline-recategorizations/guideline_recategorizations_report.md.expected @@ -13,7 +13,7 @@ | A0-1-1 | required | advisory | | A0-1-1 | required | mandatory | | A0-1-2 | required | disapplied | -| RULE-13-6 | mandatory | required | +| RULE-9-1 | mandatory | required | | CON50-CPP | rule | required | | A0-1-6 | advisory | disapplied | | A10-4-1 | advisory | required | @@ -25,5 +25,5 @@ | invalid/coding-standards.xml:5:7:8:43 | 'Invalid recategorization from 'required' to 'advisory'.' for rule A0-1-1. | | invalid/coding-standards.xml:9:7:12:43 | 'Invalid recategorization from 'required' to 'disapplied'.' for rule A0-1-2. | | invalid/coding-standards.xml:13:7:16:43 | 'Unknown rule id 'A1-4-3'.' for rule A1-4-3. | -| invalid/coding-standards.xml:17:7:20:43 | 'Invalid recategorization from 'mandatory' to 'required'.' for rule RULE-13-6. | +| invalid/coding-standards.xml:17:7:20:43 | 'Invalid recategorization from 'mandatory' to 'required'.' for rule RULE-9-1. | | invalid/coding-standards.xml:21:7:24:43 | 'Invalid recategorization from 'rule' to 'required'.' for rule CON50-CPP. | diff --git a/scripts/reports/test-data/guideline-recategorizations/invalid/coding-standards.yml b/scripts/reports/test-data/guideline-recategorizations/invalid/coding-standards.yml index 89e562c05c..cd6abbf120 100644 --- a/scripts/reports/test-data/guideline-recategorizations/invalid/coding-standards.yml +++ b/scripts/reports/test-data/guideline-recategorizations/invalid/coding-standards.yml @@ -5,7 +5,7 @@ guideline-recategorizations: category: "disapplied" - rule-id: "A1-4-3" category: "mandatory" - - rule-id: "RULE-13-6" + - rule-id: "RULE-9-1" category: "required" - rule-id: "CON50-CPP" category: "required" From fde9973bff0ca359f1df9b175c9b78e4783a4f41 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 13 Dec 2024 13:13:47 -0800 Subject: [PATCH 110/370] Add draft 0.1 of document ID detection-infinities-nans --- ...ection_of_genenated_infinities_and_nans.md | 294 ++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 docs/design/detection_of_genenated_infinities_and_nans.md diff --git a/docs/design/detection_of_genenated_infinities_and_nans.md b/docs/design/detection_of_genenated_infinities_and_nans.md new file mode 100644 index 0000000000..62396eea99 --- /dev/null +++ b/docs/design/detection_of_genenated_infinities_and_nans.md @@ -0,0 +1,294 @@ +# Coding Standards: Detection of generated Infinities and NaNs + +- [Coding Standards: Detection of generated Infinities and NaNs](#coding-standards-detection-of-generated-infinities-and-nans) + - [Document management](#document-management) + - [Background](#background) + - [Critical problems](#critical-problems) + - [TL;DR](#tldr) + - [Range / Source Analysis, In Detail](#range-source-analysis-in-detail) + - [Mathematical Operations](#mathematical-operations) + - [Range / Source Proposal #1 (Recommended)](#range-source-proposal-1-recommended) + - [Range / Source Proposal #2 (Not Recommended)](#range-source-proposal-2-not-recommended) + - [Range / Source Proposal #3 (Not Recommended)](#range-source-proposal-3-not-recommended) + - [Range / Source Proposal #4 (Not Recommended)](#range-source-proposal-4-not-recommended) + - [Detection / Sink Analysis, In Detail](#detection-sink-analysis-in-detail) + - [Detection / Sink Proposal #1 (Recommended)](#range-source-proposal-1-recommended) + - [Detection / Sink Proposal #2 (Not Recommended)](#range-source-proposal-2-not-recommended) + - [Case study examples](#case-study-examples) + +## Document management + +**ID**: codeql-coding-standards/design/detection-infinities-nans
    +**Status**: Draft + +| Version | Date | Author(s) | Reviewer (s) | +| ------- | ---------- | -------------- | ---------------------------------------------------------------------------------------------- | +| 0.1 | 12/13/2024 | Mike Fairhurst | Robert C. Seacord, J.F. Bastien, Luke Cartey, Vincent Mailhol, Fernando Jose, Rakesh Pothengil | + +## Background + +Directive 4-15 of MISRA-C 2023 states that a program shall not have undetected generation of Infinities and NaNs. It also states that infinities and NaNs may propagate across various FLOPs, but may not propagate into sections of code not designed to handle infinities and NaNs. + +This directive is intentionally open to a large degree of interpretation. This document is intended to help guide the decision making for how to implement this directive in the most useful way. + +## Critical problems + +There are two fundamental problems to decide on before implementing this directive: +- **Range / source analysis**, even a simple expression like `a + b` can be a source of infinity or NaN if there is no estimated value for `a` and/or `b`, which violates developer expectations and produces false positives. +- **Detection / sink analysis**, how we decide which sources need to be reported to users. This can be flow analysis with sinks, or it can be modeled as a resource leak analysis where certain actions (`isnan(x), x < 10`) are handled as freeing the NaN/infinite value. + +## TL;DR + +This document proposes to create a float-specialized copy of standard range analysis which assumes most values are in the range of +/-1e15, which covers most valid program use cases, and allows `a * b` without generating `Infinity`. Then standard flow analysis will be used to detect when these values flow into underflowing operations (`x / infinity` and `x % infinity`, etc.), and when NaNs flow into comparison operations (`>`, `>=`, `<`, `<=`). If the query is noisy, we may ignore NaNs and/or infinities that come from the mostly safe basic operations (`+`, `-`, `*`). + +## Range / Source Analysis, In Detail: + +Default CodeQL range analysis is limited for performance reasons (etc): + +- Range analysis is local, not interprocedural +- Global variables are assumed to be in the range of [-Infinity, Infinity] +- Struct members, array values are assumed to be in the range of [-Infinity, Infinity] +- Guards (e.g. `x != 0 ? y / x : ...`) are not always tracked + +This creates a scenario where even `a + b` can be `Infinity` or `NaN`; if either `a` or `b` is `Inf` then the expression is `Inf`, and if `a` is `+Inf` while `b` is `-Inf` then the result is `NaN`. + +Perhaps the flaw is in assuming `a` or `b` may be an infinite value. However, if the analysis considered `a` and `b` to be between the largest positive and negative finite floating values, then still `a + b` can produce an infinity, and only offers a single step of protection from false positives and negatives. + +There are a few proposals to handle this. + +#### Mathematical Operations + +IEEE 754-1985 specifies floating point semantics for “add, subtract, multiply, divide, square root, remainder, and compare operations,” including invalid use of these operators that produce NaN, propagating NaNs, and overflows that produce +/- Infinity. These semantics shall be used in the analysis. + +The C17 standard states that implementations compiling with IEEE 754-1985 shall define `__STDC_IEC_559__`. Under this proposal we will detect compilations where this macro is not defined and report a warning. + +Beyond the standard binary operators defined by IEEE 754-1985, programs may generate Infinity and/or NaN in the standard library mathematical functions. Note that technically, the c spec is vague in certain ways about when range errors, pole errors, and invalid operation errors in the standard math functions produce infinities or NaNs. We propose to assume IEEE 754-2019 behavior in this regard as a practical matter, though there is no guarantee that is the case. An alternative approach which we do not plan to take would be to broadly assume that all range errors, pole errors, invalid operation errors produce both Infinities and NaNs. This alternative would increase false positives. + +### Range / Source Proposal #1 (Recommended): + +We will create a new float-specific version of range analysis. The actual values stored in floating point variables in real programs are very unlikely to be close to the limits of finite floating point numbers (+/- 3.4e38 for floats, 1.8e308 for doubles). This proposal is that we, for the purposes of this rule, create a new range analysis for floats where otherwise undeterminable values are assumed to be a very large range that is small compared to the range of floating point values, such as +/-1e15. + +Creating a new version of float analysis rather than extending previous analysis is likely to have better performance than extending standard range analysis. When floats and integers interact, the integer from standard range analysis can be used. + +Implications of this approach (assuming values `a` and `b` have no estimated range): +- `a + b` will be finite +- `a * b` will be finite +- `a * b * c` will be possibly infinite +- `a / b` will be possibly infinite, as the range includes small values such as 1e-30, as well as zero +- `acos(a)` will be considered out of domain + +**Additional option**: If this query is still noisy, we may simply exclude reporting NaN’s and Infinities that come from a basic float operation such as `+`, `-`, or `*`. We would most likely still choose to report `/`, as divide-by-zero errors are the most common and most important to catch. + +### Range / Source Proposal #2 (Not Recommended): + +This proposal mirrors Proposal #1 except that otherwise undeterminable values will be treated as the max finite value +/-3.4e38 (floats) or 1.7e308 (doubles). + +The implications are as above except: +- `a + b` will be possibly infinite +- `a * b` will be possibly infinite + +### Range / Source Proposal #3 (Not Recommended): + +Under this proposal, standard CodeQL range analysis is used to detect generation of NaN/Infinity. All uses of a global or otherwise undeterminable value will be considered possibly infinite. + +### Range / Source Proposal #4 (Recommended): + +Under this proposal, standard CodeQL range analysis is extended to provide the support of proposal #1. While this should mostly have the same results, it will likely create performance problems, as it would rerun all range analysis code on every expression in order to have different findings in a subset of them. + +## Detection / Sink Analysis, In Detail: + +The directive states that: + +- Generated Infinities and NaNs may not be unchecked +- Infinities and NaNs may propagate to delay NaN/Infinity checking for performance reasons +- Infinities and NaNs may not reach sections of code not designed to handle them + +This leaves open some questions. For instance, is `printf("%f", a * b)` possibly sending an infinity to code prepared to handle it? + +### Detection / Sink Proposal #1 (recommended): + +This proposal is to identify sinks that should not accept Infinity or NaN, and then rely on standard flow analysis as the backbone of supporting this directive. + +If a valid propagation of a NaN or an Infinity can be distinguished from cases where a program was not prepared to receive a NaN or Infinity, then flow analysis is the only thing that is needed, and a resource-leak approach is not necessary. This proposes that the following cases are detected as sinks, such that if NaN or Infinity flows into them they are reported. + +**Case 1**: _NaNs shall not be compared, except to themselves_ +```c +void f(float x, float y) { + float z = x / y; // Could be 0.0 / 0.0 which produces NaN + + if (x < 10) { ... } // Not allowed + if (x != x) { ... } // OK +} +``` + +**Case 2**: _NaNs and infinities shall not be cast to integers_ +```c +void f(float x, float y) { + int z = x / y; // 0.0 / 0.0 may produce Infinity or NaN +} +``` + +**Case 3**: _Infinite values shall not underflow or otherwise produce finite values_ +```c +float f(void) { + float x = ...; // Could be a positive number / 0.0, which produces Infinity + 1 / x; // If x is Infinity, this underflows to 0.0 + 1 % x; // If x is Infinity, this is defined to produce 1. +} +``` + +**Case 4**: _Functions shall not return NaNs and infinities_ +```c +void f(float* p) { + float local1 = ...; // Could be infinity + + return local1; +} +``` + +**Case 5**: _NaNs and infinities shall only be stored in local stack variables_ +```c +float global; +void f(float* p) { + float local1 = ...; // Could be infinity + + // The following assignments could store an infinity in the heap: + global = local1; + extern_function(local1); + *p = local1; + + // The following cases should be possible to analyze correctly as well + // with modest effort: + float arr[10] = ...; + struct my_struct = ...; + arr[0] = local2; + my_struct.member = local1; +} +``` + +**Case 6 (not planned, compiler specific)**: _Functions can use assume() to declare they are not prepared for Infinity or NaN_ +```c +void f(float x, float[] y, struct foo z) { + assume(!isnan(x)); // May be supportable, not planned + assert(!isnan(y[0])); // Not supportable + assert(!isnan(z.member)); // Not supportable +} +``` + +With these cases specified, we can detect invalid usage of Infinity and NaN with simple flow analysis. + +## Detection / Sink Proposal #2 (not recommended): + +This proposed solution takes inspiration from resource leak detection. In this metaphor, a generated infinity or NaN is treated like a resource that must be disposed. [There is a draft WIP of this approach here.](https://github.com/github/codeql-coding-standards/compare/main...michaelrfairhurst/implement-floatingtype-package) + +The advantage of this solution is that we do not need to define every way in which a NaN or an Infinity could be misused. Rather, we only need to define a few ways that a NaN or Infinity can be checked, and then find possible Infinities and NaNs that are not checked (or propagated to a value that is checked). + +Under this proposal, the following are echecks for infinity and NaN: + +- The macros `isnan(x)`, `isinf(x)`, `isfinite(x)` should be considered checks for infinity. +- Reflexive equality checks (`x == x` or `x != x`) should be considered checks for NaN. +- Any comparison operation (`>`, `>=`, `<`, and `<=`) should be considered a check on both positive and negative and positive infinities for an operand if the other is finite. + - If `a` may only be positive infinity, `a < b` and `a > b` both create a branch of the code where `a` is not positive infinity. + - If `a` may only be negative infinity, the same as above is the case for negative infinity cases. + - If `a` may be both positive or negative infinity, then a single check is not sufficient, however detecting an appropriate pair of checks would be a much more difficult implementation + +Only local leak detection analysis is feasible at this time. Therefore, this proposal suggests that an infinite or NaN value should be flagged if it goes out of scope before it is checked. _(In other leak detection problems, this would typically be considered a free event to avoid false positives, and that is an option here as well)_. + +```c +float g; +void f(void) { + float l = 1 / 0; // Must be checked + g = l; // May send Infinity to code not prepared to handle it + isinf(l); // check occurs too late +} +``` + +Overall, this option is not recommended for the following reasons: + +- Slower performance than Proposal #1 +- Limited benefits over Proposal #1 +- Detecting out-of-scope cases heavily resembles Proposal #1 +- Unused values will be flagged, which is not useful to developers +- Intraprocedural analysis will be difficult to support +- High false positive rate if too few checks are detected, as opposed to the alternative where missing sinks do not create false positives + +In this analysis, a method or function call which can generate an infinity, such as `x / y` is treated somewhat like opening a file descriptor, and calls to `isinf(x)` or `isnan(x)` are treated as closing that file descriptor. _There are some differences between how we would approach this and how an actual resource leak detection would be modeled. For instance, we are not searching for use-after-free or double-free bugs, in this metaphor._ + +Note that resource leak detection is not the same as standard CodeQL flow analysis. For instance, if the below example is analyzed with flow analysis, CodeQL will detect that the result of `fopen` flows into a call to `fclose`. However, this only means it is possible that the program will close the file, it does not mean the file descriptor cannot leak. + +```c +void f(bool p) { + FILE* fd = fopen(...); + if (p) { + fclose(fd); + } +} +``` + +The drafted leak detection algorithm follows [this paper](https://arxiv.org/html/2312.01912v2/#S2.SS2). In this approach, the program flow from the exit of `f()` is walked backwards. The walk stops upon reaching a call to `fclose()`, and if a call to `fopen()` is reached by this iterative process then that resource could leak. + +_Note that this approach still uses flow analysis to determine that fclose(fd) is referring to an initial fopen() call. In the paper, flow analysis is used to find aliases of resources, so that disposing an alias of a resource is handled correctly._ + +This approach is still neither 100% accurate nor precise. It can generate both false positives and false negatives, though it is hopefully accurate and precise enough for our purposes: + +```c +// FALSE POSITIVE: See fprintf call marked (1). Not all successors from (1) + // call fclose(), and not all predecessors of (1) call fclose() either. + // All paths dispose fd, but this algorithm does not see that. + fd = fopen(...); + if (!cond) { + fclose(fd); + } + fprintf(...); // (1) + if (cond) { + fclose(fd); + } + + // FALSE NEGATIVE: The file descriptor opened at (2) flows into the dispose + // call at (3) if the values of x and y are not known. However, the resource + // is only closed when x == y, which is not necessarily the case. + fds[x] = fopen(...); // (2) + fclose(fds[y]); // (3) +``` + +Nevertheless, their approach is sensible and likely good enough. + +Lastly, this approach has the unfortunate downside that unused float values which could be NaN or Infinity will be reported, when they do not have any negative effect on a program (as opposed to the negative effects of leaking unused file descriptors, or unused memory, etc). + +## Case study examples + +The following is an interesting set of examples and code snippets that come from the open source project [pandas](https://github.com/commaai/panda), which aims to be MISRA compliant and is used for self-driving cars. + +These examples are hand picked results from a query that selected expressions with a floating point type along with their upper and lower bounds. + +**Example 1**: +```c +float filtered_pcm_speed = + ((to_push->data[6] << 8) | to_push->data[7]) + * 0.01 / 3.6; +// Disable controls if speeds from ABS and PCM ECUs are too far apart. +bool is_invalid_speed = ABS(filtered_pcm_speed + - ((float)vehicle_speed.values[0] / VEHICLE_SPEED_FACTOR)) + > FORD_MAX_SPEED_DELTA; +``` + +While `filter_pcm_speed` cannot be infinity or NaN, it is interesting to see how this value is sanity checked. If this code were refactored such that it could produce NaN, the greater-than check would return false, resulting in a bug. If the condition were flipped (check inside valid range, rather than outside), it would handle NaN correctly. This cannot be captured via static analysis. + +**Example 2**: +```c + float x0 = xy.x[i]; + float y0 = xy.y[i]; + float dx = xy.x[i+1] - x0; + float dy = xy.y[i+1] - y0; + // dx should not be zero as xy.x is supposed to be monotonic + dx = MAX(dx, 0.0001); + ret = (dy * (x - x0) / dx) + y0; +``` + +This is an [interpolation function](https://github.com/commaai/panda/blob/dec9223f9726e400e4a4eb91ca19fffcd745f97a/board/safety.h#L538), where `xy` is a struct parameter, with array members `x` and `y` that represent points in the domain and range to interpolate across. + +Range analysis is performed with local information only, and therefore, the expression `xy.x[i]` is given the range [-Infinity, Infinity]. This is not a generated infinity. However, the computations of `dx` and `dy` could generate a positive or negative infinity (if both numbers are finite and the result exceeds the maximum float value), they could propagate a positive or negative infinity, and/or they could generate a NaN (if an infinite value is subtracted from itself). + +The call to `MAX()` will not check if `dx` = positive infinity, and is unsafe to use with NaN. It prevents a divide-by-zero error, but `ret` could still propagate or generate a NaN or one of the infinities since we know so little about `dy`, `x0`, and `y0`. + +It’s worth noting that if `dx` is positive Infinity, then `(x - x0) / dx` will produce zero, rather than propagating the infinity. This may be worth flagging. \ No newline at end of file From ad066bb4d4550e15a194f66f1559bc414df84744 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 13 Dec 2024 13:24:35 -0800 Subject: [PATCH 111/370] Continued attempts to resolve deviations tests --- .../test/deviations/invalid_deviations/coding-standards.xml | 4 ++-- .../test/deviations/invalid_deviations/coding-standards.yml | 4 ++-- .../InvalidGuidelineRecategorizations.expected | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/common/test/deviations/invalid_deviations/coding-standards.xml b/cpp/common/test/deviations/invalid_deviations/coding-standards.xml index 179227a13d..36dedead00 100644 --- a/cpp/common/test/deviations/invalid_deviations/coding-standards.xml +++ b/cpp/common/test/deviations/invalid_deviations/coding-standards.xml @@ -83,8 +83,8 @@ DP2 - RULE-13-6 - c/misra/sizeof-operand-with-side-effect + RULE-9-1 + c/misra/object-with-auto-storage-duration-read-before-init diff --git a/cpp/common/test/deviations/invalid_deviations/coding-standards.yml b/cpp/common/test/deviations/invalid_deviations/coding-standards.yml index 7b12c7a8c2..1ce8cc718a 100644 --- a/cpp/common/test/deviations/invalid_deviations/coding-standards.yml +++ b/cpp/common/test/deviations/invalid_deviations/coding-standards.yml @@ -44,8 +44,8 @@ deviations: permit-id: non-existing-permit - permit-id: DP1 - permit-id: DP2 - - rule-id: RULE-13-6 - query-id: c/misra/sizeof-operand-with-side-effect + - rule-id: RULE-9-1 + query-id: c/misra/object-with-auto-storage-duration-read-before-init deviation-permits: - permit-id: DP1 justification: foo bar baz diff --git a/cpp/common/test/guideline_recategorizations/InvalidGuidelineRecategorizations.expected b/cpp/common/test/guideline_recategorizations/InvalidGuidelineRecategorizations.expected index 971c70a9b6..d41c27f23a 100644 --- a/cpp/common/test/guideline_recategorizations/InvalidGuidelineRecategorizations.expected +++ b/cpp/common/test/guideline_recategorizations/InvalidGuidelineRecategorizations.expected @@ -1,5 +1,5 @@ | invalid/coding-standards.xml:5:7:8:43 | guideline-recategorizations-entry | guideline_recategorizations/invalid/coding-standards.xml: 'Invalid recategorization from 'required' to 'advisory'.' for rule A0-1-1. | | invalid/coding-standards.xml:9:7:12:43 | guideline-recategorizations-entry | guideline_recategorizations/invalid/coding-standards.xml: 'Invalid recategorization from 'required' to 'disapplied'.' for rule A0-1-2. | | invalid/coding-standards.xml:13:7:16:43 | guideline-recategorizations-entry | guideline_recategorizations/invalid/coding-standards.xml: 'Unknown rule id 'A1-4-3'.' for rule A1-4-3. | -| invalid/coding-standards.xml:17:7:20:43 | guideline-recategorizations-entry | guideline_recategorizations/invalid/coding-standards.xml: 'Invalid recategorization from 'mandatory' to 'required'.' for rule RULE-13-6. | +| invalid/coding-standards.xml:17:7:20:43 | guideline-recategorizations-entry | guideline_recategorizations/invalid/coding-standards.xml: 'Invalid recategorization from 'mandatory' to 'required'.' for rule RULE-9-1. | | invalid/coding-standards.xml:21:7:24:43 | guideline-recategorizations-entry | guideline_recategorizations/invalid/coding-standards.xml: 'Invalid recategorization from 'rule' to 'required'.' for rule CON50-CPP. | From 3342bb525e410e4c8d2b4232e73a5c3f06b00659 Mon Sep 17 00:00:00 2001 From: "rakesh.pothengil" Date: Tue, 17 Dec 2024 16:07:55 +0900 Subject: [PATCH 112/370] Fixes #824 --- change_notes/2024-12-17-fix-fp-824-a15-4-4 | 2 ++ cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql | 3 +++ 2 files changed, 5 insertions(+) create mode 100644 change_notes/2024-12-17-fix-fp-824-a15-4-4 diff --git a/change_notes/2024-12-17-fix-fp-824-a15-4-4 b/change_notes/2024-12-17-fix-fp-824-a15-4-4 new file mode 100644 index 0000000000..0908c14ffa --- /dev/null +++ b/change_notes/2024-12-17-fix-fp-824-a15-4-4 @@ -0,0 +1,2 @@ + - `A15-4-4` - `MissingNoExcept.ql`: + - Reduce false positives by not reporting on functions that have a noexcept specification with a complex expression. diff --git a/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql b/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql index 7701a8a1ea..2721b42af3 100644 --- a/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql +++ b/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql @@ -28,6 +28,9 @@ where not isNoExceptTrue(f) and // Not explicitly marked noexcept(false) not isNoExceptExplicitlyFalse(f) and + // Not having a noexcept specification that + // could not be computed as true or false above. + not exists(f.getADeclarationEntry().getNoExceptExpr()) and // Not compiler generated not f.isCompilerGenerated() and // The function is defined in this database From 40d7800f77d588e67b394a1604682cb7320e1236 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 17 Dec 2024 19:23:18 +0100 Subject: [PATCH 113/370] Update expected test results --- .../RULE-5-4/MacroIdentifiersNotDistinct.expected | 6 +++--- .../identifierhidden/IdentifierHidden.expected | 13 +------------ 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/c/misra/test/rules/RULE-5-4/MacroIdentifiersNotDistinct.expected b/c/misra/test/rules/RULE-5-4/MacroIdentifiersNotDistinct.expected index d44164d116..b079b7e94d 100644 --- a/c/misra/test/rules/RULE-5-4/MacroIdentifiersNotDistinct.expected +++ b/c/misra/test/rules/RULE-5-4/MacroIdentifiersNotDistinct.expected @@ -1,4 +1,4 @@ -| header3.h:7:1:7:24 | #define MULTIPLE_INCLUDE | Definition of macro MULTIPLE_INCLUDE is not distinct from alternative definition of $@ in rules/RULE-5-4/header4.h. | header4.h:1:1:1:24 | #define MULTIPLE_INCLUDE | MULTIPLE_INCLUDE | -| header3.h:14:1:14:21 | #define NOT_PROTECTED | Definition of macro NOT_PROTECTED is not distinct from alternative definition of $@ in rules/RULE-5-4/header4.h. | header4.h:12:1:12:23 | #define NOT_PROTECTED 1 | NOT_PROTECTED | +| header3.h:7:1:7:24 | #define MULTIPLE_INCLUDE | Definition of macro MULTIPLE_INCLUDE is not distinct from alternative definition of $@ in header4.h. | header4.h:1:1:1:24 | #define MULTIPLE_INCLUDE | MULTIPLE_INCLUDE | +| header3.h:14:1:14:21 | #define NOT_PROTECTED | Definition of macro NOT_PROTECTED is not distinct from alternative definition of $@ in header4.h. | header4.h:12:1:12:23 | #define NOT_PROTECTED 1 | NOT_PROTECTED | | test.c:2:1:2:72 | #define iltiqzxgfqsgigwfuyntzghvzltueatcxqnqofnnvjyszmcsylyohvqaosjbqyyB | Macro identifer iltiqzxgfqsgigwfuyntzghvzltueatcxqnqofnnvjyszmcsylyohvqaosjbqyyB is nondistinct in first 63 characters, compared to $@. | test.c:1:1:1:72 | #define iltiqzxgfqsgigwfuyntzghvzltueatcxqnqofnnvjyszmcsylyohvqaosjbqyyA | iltiqzxgfqsgigwfuyntzghvzltueatcxqnqofnnvjyszmcsylyohvqaosjbqyyA | -| test.c:8:1:8:31 | #define FUNCTION_MACRO(X) X + 1 | Definition of macro FUNCTION_MACRO is not distinct from alternative definition of $@ in rules/RULE-5-4/test.c. | test.c:7:1:7:57 | #define FUNCTION_MACRO(FUNCTION_MACRO) FUNCTION_MACRO + 1 | FUNCTION_MACRO | +| test.c:8:1:8:31 | #define FUNCTION_MACRO(X) X + 1 | Definition of macro FUNCTION_MACRO is not distinct from alternative definition of $@ in test.c. | test.c:7:1:7:57 | #define FUNCTION_MACRO(FUNCTION_MACRO) FUNCTION_MACRO + 1 | FUNCTION_MACRO | diff --git a/cpp/common/test/rules/identifierhidden/IdentifierHidden.expected b/cpp/common/test/rules/identifierhidden/IdentifierHidden.expected index 47d191d758..fd657590ef 100644 --- a/cpp/common/test/rules/identifierhidden/IdentifierHidden.expected +++ b/cpp/common/test/rules/identifierhidden/IdentifierHidden.expected @@ -4,21 +4,10 @@ | test.cpp:23:13:23:15 | id1 | Variable is hiding variable $@. | test.cpp:1:5:1:7 | id1 | id1 | | test.cpp:26:12:26:14 | id1 | Variable is hiding variable $@. | test.cpp:1:5:1:7 | id1 | id1 | | test.cpp:27:14:27:16 | id1 | Variable is hiding variable $@. | test.cpp:26:12:26:14 | id1 | id1 | -| test.cpp:48:11:48:11 | i | Variable is hiding variable $@. | test.cpp:58:16:58:16 | i | i | -| test.cpp:48:11:48:11 | i | Variable is hiding variable $@. | test.cpp:75:16:75:16 | i | i | -| test.cpp:50:9:50:9 | i | Variable is hiding variable $@. | test.cpp:58:16:58:16 | i | i | -| test.cpp:50:9:50:9 | i | Variable is hiding variable $@. | test.cpp:75:16:75:16 | i | i | -| test.cpp:53:12:53:12 | i | Variable is hiding variable $@. | test.cpp:58:16:58:16 | i | i | -| test.cpp:53:12:53:12 | i | Variable is hiding variable $@. | test.cpp:75:16:75:16 | i | i | -| test.cpp:65:11:65:11 | i | Variable is hiding variable $@. | test.cpp:58:16:58:16 | i | i | | test.cpp:65:11:65:11 | i | Variable is hiding variable $@. | test.cpp:61:7:61:7 | i | i | -| test.cpp:65:11:65:11 | i | Variable is hiding variable $@. | test.cpp:75:16:75:16 | i | i | -| test.cpp:67:9:67:9 | i | Variable is hiding variable $@. | test.cpp:58:16:58:16 | i | i | | test.cpp:67:9:67:9 | i | Variable is hiding variable $@. | test.cpp:61:7:61:7 | i | i | -| test.cpp:67:9:67:9 | i | Variable is hiding variable $@. | test.cpp:75:16:75:16 | i | i | -| test.cpp:70:12:70:12 | i | Variable is hiding variable $@. | test.cpp:58:16:58:16 | i | i | | test.cpp:70:12:70:12 | i | Variable is hiding variable $@. | test.cpp:61:7:61:7 | i | i | -| test.cpp:70:12:70:12 | i | Variable is hiding variable $@. | test.cpp:75:16:75:16 | i | i | +| test.cpp:75:16:75:16 | i | Variable is hiding variable $@. | test.cpp:61:7:61:7 | i | i | | test.cpp:86:9:86:9 | b | Variable is hiding variable $@. | test.cpp:80:11:80:11 | b | b | | test.cpp:94:9:94:17 | globalvar | Variable is hiding variable $@. | test.cpp:91:5:91:13 | globalvar | globalvar | | test.cpp:113:11:113:11 | b | Variable is hiding variable $@. | test.cpp:107:13:107:13 | b | b | From 065dc013edd676c420fa86f9fe6cebb9a7ae9394 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 17 Dec 2024 20:18:18 +0100 Subject: [PATCH 114/370] Update queries after `TemplateParameter` deprecation --- .../rules/RULE-2-4/UnusedTagDeclaration.ql | 2 +- ...wardingReferenceAsItsArgumentOverloaded.ql | 3 +- .../NonTemplateMemberDefinedInTemplate.ql | 28 +++++++++---------- .../NonMemberGenericOperatorCondition.ql | 2 +- ...tionAndInitializationNotOnSeparateLines.ql | 2 +- .../CopyAssignmentOperatorNotDeclared.ql | 4 +-- .../DisappliedQuery.ql | 2 +- 7 files changed, 22 insertions(+), 21 deletions(-) diff --git a/c/misra/src/rules/RULE-2-4/UnusedTagDeclaration.ql b/c/misra/src/rules/RULE-2-4/UnusedTagDeclaration.ql index 08fe2568e9..e277139c1a 100644 --- a/c/misra/src/rules/RULE-2-4/UnusedTagDeclaration.ql +++ b/c/misra/src/rules/RULE-2-4/UnusedTagDeclaration.ql @@ -32,5 +32,5 @@ where // `isInMacroExpansion` is broken for `UserType`s. not s.isInMacroExpansion() and // Exclude template parameters, in case this is run on C++ code. - not s instanceof TemplateParameter + not s instanceof TypeTemplateParameter select s, "struct " + s.getName() + " has an unused tag." diff --git a/cpp/autosar/src/rules/A13-3-1/FunctionThatContainsForwardingReferenceAsItsArgumentOverloaded.ql b/cpp/autosar/src/rules/A13-3-1/FunctionThatContainsForwardingReferenceAsItsArgumentOverloaded.ql index 1ae2bc87ab..7b31ae5d9e 100644 --- a/cpp/autosar/src/rules/A13-3-1/FunctionThatContainsForwardingReferenceAsItsArgumentOverloaded.ql +++ b/cpp/autosar/src/rules/A13-3-1/FunctionThatContainsForwardingReferenceAsItsArgumentOverloaded.ql @@ -18,7 +18,8 @@ import codingstandards.cpp.FunctionEquivalence class Candidate extends TemplateFunction { Candidate() { - this.getAParameter().getType().(RValueReferenceType).getBaseType() instanceof TemplateParameter + this.getAParameter().getType().(RValueReferenceType).getBaseType() instanceof + TypeTemplateParameter } } diff --git a/cpp/autosar/src/rules/A14-5-2/NonTemplateMemberDefinedInTemplate.ql b/cpp/autosar/src/rules/A14-5-2/NonTemplateMemberDefinedInTemplate.ql index 7f9ced9909..95465bbb6a 100644 --- a/cpp/autosar/src/rules/A14-5-2/NonTemplateMemberDefinedInTemplate.ql +++ b/cpp/autosar/src/rules/A14-5-2/NonTemplateMemberDefinedInTemplate.ql @@ -18,7 +18,7 @@ import codingstandards.cpp.autosar import codingstandards.cpp.TypeUses import codingstandards.cpp.Operator -predicate templateDefinitionMentionsTypeParameter(Declaration d, TemplateParameter tp) { +predicate templateDefinitionMentionsTypeParameter(Declaration d, TypeTemplateParameter tp) { exists(Type t | ( // direct reference, e.g., fields. @@ -50,36 +50,36 @@ predicate templateDefinitionMentionsTypeParameter(Declaration d, TemplateParamet } /** - * The set of `TemplateParameter` references within an `Enum`. + * The set of `TypeTemplateParameter` references within an `Enum`. */ -TemplateParameter enumTemplateReferences(Enum e) { +TypeTemplateParameter enumTemplateReferences(Enum e) { templateDefinitionMentionsTypeParameter(e.getADeclaration(), result) or result = e.getExplicitUnderlyingType() } /** - * The set of `TemplateParameter` references within an `Class`. + * The set of `TypeTemplateParameter` references within an `Class`. */ -TemplateParameter classTemplateReferences(Class c) { +TypeTemplateParameter classTemplateReferences(Class c) { templateDefinitionMentionsTypeParameter(c.getAMember(), result) or c.getADerivation().getBaseType() = result } /** - * The set of all of the `TemplateParameter`s referenced by a `EnumConstant`. + * The set of all of the `TypeTemplateParameter`s referenced by a `EnumConstant`. */ -TemplateParameter enumConstantTemplateReferences(EnumConstant ec) { +TypeTemplateParameter enumConstantTemplateReferences(EnumConstant ec) { templateDefinitionMentionsTypeParameter(ec.getDeclaringType(), result) } /** - * The set of all `TemplateParameter`s referenced by a `Function`. + * The set of all `TypeTemplateParameter`s referenced by a `Function`. */ -TemplateParameter functionTemplateReferences(Function mf) { +TypeTemplateParameter functionTemplateReferences(Function mf) { // the type of the function - exists(TemplateParameter tp | + exists(TypeTemplateParameter tp | result = tp and ( mf.getType().refersTo(result) @@ -115,10 +115,10 @@ TemplateParameter functionTemplateReferences(Function mf) { } /** - * The set of all `TemplateParameters` available as arguments to the declaring + * The set of all `TypeTemplateParameters` available as arguments to the declaring * element of some `Declarations`. */ -TemplateParameter templateParametersOfDeclaringTemplateClass(Declaration d) { +TypeTemplateParameter templateParametersOfDeclaringTemplateClass(Declaration d) { result = d.getDeclaringType().getATemplateArgument() } @@ -149,7 +149,7 @@ where not d instanceof UserNegationOperator and // for each declaration within a template class get the // template parameters of the declaring class - not exists(TemplateParameter t | + not exists(TypeTemplateParameter t | t = templateParametersOfDeclaringTemplateClass(d) and // and require that the declaration depends on at least // one of those template parameters. @@ -170,7 +170,7 @@ where ) and // Omit using alias (cf. https://github.com/github/codeql-coding-standards/issues/739) // Exclude Using alias which refer directly to a TypeParameter - not d.(UsingAliasTypedefType).getBaseType() instanceof TemplateParameter + not d.(UsingAliasTypedefType).getBaseType() instanceof TypeTemplateParameter select d, "Member " + d.getName() + " template class does not use any of template arguments of its $@.", d.getDeclaringType(), "declaring type" diff --git a/cpp/autosar/src/rules/A14-5-3/NonMemberGenericOperatorCondition.ql b/cpp/autosar/src/rules/A14-5-3/NonMemberGenericOperatorCondition.ql index a2211368ed..c2d28d3ef9 100644 --- a/cpp/autosar/src/rules/A14-5-3/NonMemberGenericOperatorCondition.ql +++ b/cpp/autosar/src/rules/A14-5-3/NonMemberGenericOperatorCondition.ql @@ -18,7 +18,7 @@ import codingstandards.cpp.autosar class NonMemberGenericOperator extends TemplateFunction { NonMemberGenericOperator() { this instanceof Operator and - exists(TemplateParameter tp, Type pType | + exists(TypeTemplateParameter tp, Type pType | pType = getAParameter().getType().getUnspecifiedType() //Parameter Type | pType = tp or diff --git a/cpp/autosar/src/rules/A7-1-7/IdentifierDeclarationAndInitializationNotOnSeparateLines.ql b/cpp/autosar/src/rules/A7-1-7/IdentifierDeclarationAndInitializationNotOnSeparateLines.ql index 89aca8048e..ac98fe699d 100644 --- a/cpp/autosar/src/rules/A7-1-7/IdentifierDeclarationAndInitializationNotOnSeparateLines.ql +++ b/cpp/autosar/src/rules/A7-1-7/IdentifierDeclarationAndInitializationNotOnSeparateLines.ql @@ -23,7 +23,7 @@ class UniqueLineStmt extends Locatable { exists(Declaration d | this = d.getADeclarationEntry() and not d instanceof Parameter and - not d instanceof TemplateParameter and + not d instanceof TypeTemplateParameter and // TODO - Needs to be enhanced to solve issues with // templated inner classes. not d instanceof Function and diff --git a/cpp/autosar/src/rules/M14-5-3/CopyAssignmentOperatorNotDeclared.ql b/cpp/autosar/src/rules/M14-5-3/CopyAssignmentOperatorNotDeclared.ql index 05e99d6e66..1b41fe81bc 100644 --- a/cpp/autosar/src/rules/M14-5-3/CopyAssignmentOperatorNotDeclared.ql +++ b/cpp/autosar/src/rules/M14-5-3/CopyAssignmentOperatorNotDeclared.ql @@ -34,10 +34,10 @@ class TemplateAssignmentOperatorMember extends MemberFunction { } /** - * is a copy assigment operator candidate if it has only one param and form in [T, T&, const T&, volatile T&, const volatile T&] + * is a copy assignment operator candidate if it has only one param and form in [T, T&, const T&, volatile T&, const volatile T&] */ predicate hasGenericCopyCompatibleParameter() { - exists(TemplateParameter tp, Type pType | + exists(TypeTemplateParameter tp, Type pType | pType = this.getAParameter().getType().getUnspecifiedType() and //Parameter Type ( tp = pType //T diff --git a/cpp/common/test/guideline_recategorizations/DisappliedQuery.ql b/cpp/common/test/guideline_recategorizations/DisappliedQuery.ql index 0254eca9bd..9c6f732aa9 100644 --- a/cpp/common/test/guideline_recategorizations/DisappliedQuery.ql +++ b/cpp/common/test/guideline_recategorizations/DisappliedQuery.ql @@ -17,7 +17,7 @@ from UserType ut, string reason where isExcluded(ut, DeadCodePackage::unusedTypeDeclarationsQuery(), reason) and exists(ut.getFile()) and - not ut instanceof TemplateParameter and + not ut instanceof TypeTemplateParameter and not ut instanceof ProxyClass and not exists(getATypeUse(ut)) and not ut.isFromUninstantiatedTemplate(_) From 23ddafa76ec60d06ef5f339062647f41cfb436ef Mon Sep 17 00:00:00 2001 From: "rakesh.pothengil" Date: Wed, 18 Dec 2024 11:13:46 +0900 Subject: [PATCH 115/370] Fix #540 --- change_notes/2024-12-18-fix-fp-540-a3-9-1.md | 2 ++ .../rules/A3-9-1/VariableWidthIntegerTypesUsed.ql | 4 ++++ cpp/autosar/test/rules/A3-9-1/test.cpp | 13 ++++++++++++- 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 change_notes/2024-12-18-fix-fp-540-a3-9-1.md diff --git a/change_notes/2024-12-18-fix-fp-540-a3-9-1.md b/change_notes/2024-12-18-fix-fp-540-a3-9-1.md new file mode 100644 index 0000000000..fbd09ca840 --- /dev/null +++ b/change_notes/2024-12-18-fix-fp-540-a3-9-1.md @@ -0,0 +1,2 @@ + - `A3-9-1` - `VariableWidthIntegerTypesUsed.ql`: + - Reduce false positives by not considering variables from template instantiations. diff --git a/cpp/autosar/src/rules/A3-9-1/VariableWidthIntegerTypesUsed.ql b/cpp/autosar/src/rules/A3-9-1/VariableWidthIntegerTypesUsed.ql index 84a38b0f6a..fa19ad998f 100644 --- a/cpp/autosar/src/rules/A3-9-1/VariableWidthIntegerTypesUsed.ql +++ b/cpp/autosar/src/rules/A3-9-1/VariableWidthIntegerTypesUsed.ql @@ -32,6 +32,10 @@ where typeStrippedOfSpecifiers instanceof SignedCharType ) and not v instanceof ExcludedVariable and + // Dont consider template instantiations because instantiations with + // Fixed Width Types are recorded after stripping their typedef'd type, + // thereby, causing false positives (#540). + not v.isFromTemplateInstantiation(_) and //post-increment/post-decrement operators are required by the standard to have a dummy int parameter not v.(Parameter).getFunction() instanceof PostIncrementOperator and not v.(Parameter).getFunction() instanceof PostDecrementOperator diff --git a/cpp/autosar/test/rules/A3-9-1/test.cpp b/cpp/autosar/test/rules/A3-9-1/test.cpp index 882738eea1..7ffb87ca39 100644 --- a/cpp/autosar/test/rules/A3-9-1/test.cpp +++ b/cpp/autosar/test/rules/A3-9-1/test.cpp @@ -75,4 +75,15 @@ void test_variable_width_type_qualified_variables() { struct test_fix_fp_614 { test_fix_fp_614 operator++(int); // COMPLIANT test_fix_fp_614 operator--(int); // COMPLIANT -}; \ No newline at end of file +}; + +// COMPLIANT - instantiated with Fixed Width Types. +template constexpr void test_fix_fp_540(MyType value) { + value++; +} + +int call_test_fix_fp_540() { + test_fix_fp_540(19); + test_fix_fp_540(20); + return 0; +} From f5394d0b1ef8bad2b32ef07298eebb7803a902b6 Mon Sep 17 00:00:00 2001 From: "rakesh.pothengil" Date: Thu, 19 Dec 2024 11:17:11 +0900 Subject: [PATCH 116/370] Check called functions with noexcept(unknown) --- change_notes/2024-12-17-fix-fp-824-a15-4-4 | 2 +- .../src/rules/A15-4-4/MissingNoExcept.ql | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/change_notes/2024-12-17-fix-fp-824-a15-4-4 b/change_notes/2024-12-17-fix-fp-824-a15-4-4 index 0908c14ffa..89ccf49815 100644 --- a/change_notes/2024-12-17-fix-fp-824-a15-4-4 +++ b/change_notes/2024-12-17-fix-fp-824-a15-4-4 @@ -1,2 +1,2 @@ - `A15-4-4` - `MissingNoExcept.ql`: - - Reduce false positives by not reporting on functions that have a noexcept specification with a complex expression. + - Reduce false positives by not reporting on functions that have a noexcept specification with a complex expression or call other such functions. diff --git a/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql b/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql index 2721b42af3..33369e00a4 100644 --- a/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql +++ b/cpp/autosar/src/rules/A15-4-4/MissingNoExcept.ql @@ -19,6 +19,36 @@ import codingstandards.cpp.autosar import codingstandards.cpp.exceptions.ExceptionSpecifications import codingstandards.cpp.exceptions.ExceptionFlow +// These functions have a noexcept specification that could not be resolved +// to noexcept(true). So either, they are noexcept(false) functions which +// means, they can throw an exception OR they have an expression which +// could not be resolved to "true" or "false". Even in this case, lets +// be more conservative and assume they may thrown an exception. +class FunctionWithUnknownNoExcept extends Function { + FunctionWithUnknownNoExcept() { + // Exists a noexcept specification but not noexcept(true) + exists(this.getADeclarationEntry().getNoExceptExpr()) and + not isNoExceptTrue(this) + } +} + +// This predicate checks if a function can call to other functions +// that may have a noexcept specification which cannot be resolved to +// noexcept(true). +predicate mayCallThrowingFunctions(Function f) { + // Exists a call in this function + exists(Call fc | + fc.getEnclosingFunction() = f and + ( + // Either this call is to a function with an unknown noexcept OR + fc.getTarget() instanceof FunctionWithUnknownNoExcept + or + // That function can further have calls to unknown noexcept functions. + mayCallThrowingFunctions(fc.getTarget()) + ) + ) +} + from Function f where not isExcluded(f, Exceptions1Package::missingNoExceptQuery()) and @@ -31,6 +61,9 @@ where // Not having a noexcept specification that // could not be computed as true or false above. not exists(f.getADeclarationEntry().getNoExceptExpr()) and + // Not calling function(s) which have a noexcept specification that + // could not be computed as true. + not mayCallThrowingFunctions(f) and // Not compiler generated not f.isCompilerGenerated() and // The function is defined in this database From ae63dcbd93178c83693ec7c06b0105be3088c445 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 18 Dec 2024 18:28:45 -0800 Subject: [PATCH 117/370] Implement most MISRA-C amendment4 rule amendments --- amendments.csv | 10 +- .../includes/standard-library/stdatomic.h | 74 +++++++++++++-- .../rules/readofuninitializedmemory/test.c | 2 + ...weenObjectPointerAndDifferentObjectType.ql | 6 +- ...CastRemovesConstOrVolatileQualification.ql | 4 + .../rules/RULE-13-2/UnsequencedAtomicReads.ql | 94 +++++++++++++++++++ ...CharacterSequencesAndUsedWithinAComment.ql | 33 ++++--- ...jectPointerAndDifferentObjectType.expected | 4 + c/misra/test/rules/RULE-11-3/test.c | 6 ++ ...movesConstOrVolatileQualification.expected | 4 + c/misra/test/rules/RULE-11-8/test.c | 7 ++ .../RULE-13-2/UnsequencedAtomicReads.expected | 5 + .../RULE-13-2/UnsequencedAtomicReads.qlref | 1 + .../RULE-13-2/UnsequencedSideEffects.expected | 12 +-- c/misra/test/rules/RULE-13-2/test.c | 13 +++ ...terSequencesAndUsedWithinAComment.expected | 2 + c/misra/test/rules/RULE-3-1/test.c | 15 +++ ...ment-misra-c-amendment4-rule-amendments.md | 10 ++ .../cpp/exclusions/c/SideEffects3.qll | 20 +++- .../ReadOfUninitializedMemory.qll | 2 + .../rules/readofuninitializedmemory/test.cpp | 2 + rule_packages/c/SideEffects3.json | 12 +++ 22 files changed, 307 insertions(+), 31 deletions(-) create mode 100644 c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql create mode 100644 c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected create mode 100644 c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.qlref create mode 100644 change_notes/2024-12-13-implement-misra-c-amendment4-rule-amendments.md diff --git a/amendments.csv b/amendments.csv index ce285a29ba..bb2ceac27a 100644 --- a/amendments.csv +++ b/amendments.csv @@ -11,21 +11,21 @@ c,MISRA-C-2012,Amendment3,RULE-10-7,Yes,Refine,No,Import c,MISRA-C-2012,Amendment3,RULE-10-8,Yes,Refine,No,Import c,MISRA-C-2012,Amendment3,RULE-21-11,Yes,Clarification,No,Import c,MISRA-C-2012,Amendment3,RULE-21-12,Yes,Replace,No,Easy -c,MISRA-C-2012,Amendment4,RULE-11-3,Yes,Expand,No,Easy -c,MISRA-C-2012,Amendment4,RULE-11-8,Yes,Expand,No,Easy -c,MISRA-C-2012,Amendment4,RULE-13-2,Yes,Expand,No,Very Hard +c,MISRA-C-2012,Amendment4,RULE-11-3,Yes,Expand,Yes,Easy +c,MISRA-C-2012,Amendment4,RULE-11-8,Yes,Expand,Yes,Easy +c,MISRA-C-2012,Amendment4,RULE-13-2,Yes,Expand,Yes,Very Hard c,MISRA-C-2012,Amendment4,RULE-18-6,Yes,Expand,No,Medium c,MISRA-C-2012,Amendment4,RULE-18-8,Yes,Split,Yes,Easy c,MISRA-C-2012,Corrigendum2,RULE-2-2,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-2-7,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-3-1,Yes,Refine,No,Easy +c,MISRA-C-2012,Corrigendum2,RULE-3-1,Yes,Refine,Yes,Easy c,MISRA-C-2012,Corrigendum2,RULE-8-6,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-8-9,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-9-4,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-10-1,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-18-3,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-1-4,Yes,Replace,No,Easy -c,MISRA-C-2012,Corrigendum2,RULE-9-1,Yes,Refine,No,Easy +c,MISRA-C-2012,Corrigendum2,RULE-9-1,Yes,Refine,Yes,Easy c,MISRA-C-2012,Corrigendum2,RULE-9-2,Yes,Refine,No,Import c,MISRA-C-2012,Corrigendum2,DIR-4-10,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-7-4,Yes,Refine,No,Easy diff --git a/c/common/test/includes/standard-library/stdatomic.h b/c/common/test/includes/standard-library/stdatomic.h index 66b74ae61a..49a5b3cfcd 100644 --- a/c/common/test/includes/standard-library/stdatomic.h +++ b/c/common/test/includes/standard-library/stdatomic.h @@ -1,9 +1,69 @@ -#define atomic_compare_exchange_weak(a, b, c) 0 -#define atomic_compare_exchange_weak_explicit(a, b, c, d, e) 0 -#define atomic_load(a) 0 -#define atomic_load_explicit(a, b) -#define atomic_store(a, b) 0 -#define atomic_store_explicit(a, b, c) 0 #define ATOMIC_VAR_INIT(value) (value) #define atomic_is_lock_free(obj) __c11_atomic_is_lock_free(sizeof(*(obj))) -typedef _Atomic(int) atomic_int; \ No newline at end of file +typedef _Atomic(int) atomic_int; + +#define __ATOMIC_RELAXED 0 +#define __ATOMIC_CONSUME 1 +#define __ATOMIC_ACQUIRE 2 +#define __ATOMIC_RELEASE 3 +#define __ATOMIC_ACQ_REL 4 +#define __ATOMIC_SEQ_CST 5 + +typedef enum memory_order { + memory_order_relaxed = __ATOMIC_RELAXED, + memory_order_consume = __ATOMIC_CONSUME, + memory_order_acquire = __ATOMIC_ACQUIRE, + memory_order_release = __ATOMIC_RELEASE, + memory_order_acq_rel = __ATOMIC_ACQ_REL, + memory_order_seq_cst = __ATOMIC_SEQ_CST +} memory_order; + +void atomic_thread_fence(memory_order); +void atomic_signal_fence(memory_order); + +#define atomic_thread_fence(order) __c11_atomic_thread_fence(order) +#define atomic_signal_fence(order) __c11_atomic_signal_fence(order) + +#define atomic_store(object, desired) __c11_atomic_store(object, desired, __ATOMIC_SEQ_CST) +#define atomic_store_explicit __c11_atomic_store + +#define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST) +#define atomic_load_explicit __c11_atomic_load + +#define atomic_exchange(object, desired) __c11_atomic_exchange(object, desired, __ATOMIC_SEQ_CST) +#define atomic_exchange_explicit __c11_atomic_exchange + +#define atomic_compare_exchange_strong(object, expected, desired) __c11_atomic_compare_exchange_strong(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) +#define atomic_compare_exchange_strong_explicit __c11_atomic_compare_exchange_strong + +#define atomic_compare_exchange_weak(object, expected, desired) __c11_atomic_compare_exchange_weak(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) +#define atomic_compare_exchange_weak_explicit __c11_atomic_compare_exchange_weak + +#define atomic_fetch_add(object, operand) __c11_atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST) +#define atomic_fetch_add_explicit __c11_atomic_fetch_add + +#define atomic_fetch_sub(object, operand) __c11_atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST) +#define atomic_fetch_sub_explicit __c11_atomic_fetch_sub + +#define atomic_fetch_or(object, operand) __c11_atomic_fetch_or(object, operand, __ATOMIC_SEQ_CST) +#define atomic_fetch_or_explicit __c11_atomic_fetch_or + +#define atomic_fetch_xor(object, operand) __c11_atomic_fetch_xor(object, operand, __ATOMIC_SEQ_CST) +#define atomic_fetch_xor_explicit __c11_atomic_fetch_xor + +#define atomic_fetch_and(object, operand) __c11_atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST) +#define atomic_fetch_and_explicit __c11_atomic_fetch_and + +typedef struct atomic_flag { _Atomic(_Bool) _Value; } atomic_flag; + +_Bool atomic_flag_test_and_set(volatile atomic_flag *); +_Bool atomic_flag_test_and_set_explicit(volatile atomic_flag *, memory_order); + +void atomic_flag_clear(volatile atomic_flag *); +void atomic_flag_clear_explicit(volatile atomic_flag *, memory_order); + +#define atomic_flag_test_and_set(object) __c11_atomic_exchange(&(object)->_Value, 1, __ATOMIC_SEQ_CST) +#define atomic_flag_test_and_set_explicit(object, order) __c11_atomic_exchange(&(object)->_Value, 1, order) + +#define atomic_flag_clear(object) __c11_atomic_store(&(object)->_Value, 0, __ATOMIC_SEQ_CST) +#define atomic_flag_clear_explicit(object, order) __c11_atomic_store(&(object)->_Value, 0, order) \ No newline at end of file diff --git a/c/common/test/rules/readofuninitializedmemory/test.c b/c/common/test/rules/readofuninitializedmemory/test.c index ce2c60484e..e76c5a22b3 100644 --- a/c/common/test/rules/readofuninitializedmemory/test.c +++ b/c/common/test/rules/readofuninitializedmemory/test.c @@ -94,4 +94,6 @@ void test_non_default_init() { static struct A ss; use_struct_A( ss); // COMPLIANT - static struct type variables are zero initialized + _Atomic int x; + use_int(x); // COMPLIANT - atomics are special, covered by other rules } \ No newline at end of file diff --git a/c/misra/src/rules/RULE-11-3/CastBetweenObjectPointerAndDifferentObjectType.ql b/c/misra/src/rules/RULE-11-3/CastBetweenObjectPointerAndDifferentObjectType.ql index 8292bd3b6f..c51ecbc81d 100644 --- a/c/misra/src/rules/RULE-11-3/CastBetweenObjectPointerAndDifferentObjectType.ql +++ b/c/misra/src/rules/RULE-11-3/CastBetweenObjectPointerAndDifferentObjectType.ql @@ -23,7 +23,11 @@ where baseTypeFrom = cast.getExpr().getType().(PointerToObjectType).getBaseType() and baseTypeTo = cast.getType().(PointerToObjectType).getBaseType() and // exception: cast to a char, signed char, or unsigned char is permitted - not baseTypeTo.stripType() instanceof CharType and + not ( + baseTypeTo.stripType() instanceof CharType and + // Exception does not apply to _Atomic types + not baseTypeFrom.hasSpecifier("atomic") + ) and ( ( baseTypeFrom.isVolatile() and not baseTypeTo.isVolatile() diff --git a/c/misra/src/rules/RULE-11-8/CastRemovesConstOrVolatileQualification.ql b/c/misra/src/rules/RULE-11-8/CastRemovesConstOrVolatileQualification.ql index 17b12aaf99..c0f447d5b5 100644 --- a/c/misra/src/rules/RULE-11-8/CastRemovesConstOrVolatileQualification.ql +++ b/c/misra/src/rules/RULE-11-8/CastRemovesConstOrVolatileQualification.ql @@ -24,5 +24,9 @@ where baseTypeFrom.isVolatile() and not baseTypeTo.isVolatile() and qualificationName = "volatile" or baseTypeFrom.isConst() and not baseTypeTo.isConst() and qualificationName = "const" + or + baseTypeFrom.hasSpecifier("atomic") and + not baseTypeTo.hasSpecifier("atomic") and + qualificationName = "atomic" ) select cast, "Cast of pointer removes " + qualificationName + " qualification from its base type." diff --git a/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql b/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql new file mode 100644 index 0000000000..d7638229d6 --- /dev/null +++ b/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql @@ -0,0 +1,94 @@ +/** + * @id c/misra/unsequenced-atomic-reads + * @name RULE-13-2: The value of an atomic variable depend on its evaluation order and interleave of threads + * @description The value of an atomic variable shall not depend on evaluation order and + * interleaving of threads. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-13-2 + * correctness + * external/misra/c/2012/amendment3 + * external/misra/obligation/required + */ + +import cpp +import semmle.code.cpp.dataflow.TaintTracking +import codingstandards.c.misra +import codingstandards.c.Ordering +import codingstandards.c.orderofevaluation.VariableAccessOrdering + +class AtomicAccessInFullExpressionOrdering extends Ordering::Configuration { + AtomicAccessInFullExpressionOrdering() { this = "AtomicAccessInFullExpressionOrdering" } + + override predicate isCandidate(Expr e1, Expr e2) { + exists(AtomicVariableAccess a, AtomicVariableAccess b, FullExpr e | a = e1 and b = e2 | + a.getTarget() = b.getTarget() and + a.(ConstituentExpr).getFullExpr() = e and + b.(ConstituentExpr).getFullExpr() = e and + not a = b + ) + } +} + +/** + * A read of a variable specified as `_Atomic`. + * + * Note, it may be accessed directly, or by passing its address into the std atomic functions. + */ +class AtomicVariableAccess extends VariableAccess { + pragma[noinline] + AtomicVariableAccess() { + getTarget().getType().hasSpecifier("atomic") + } + + /* Get the `atomic_()` call this VarAccess occurs in. */ + FunctionCall getAtomicFunctionCall() { + exists(AddressOfExpr addrParent, FunctionCall fc | + fc.getTarget().getName().matches("__c11_atomic%") and + addrParent = fc.getArgument(0) and + addrParent.getAnOperand() = this + and result = fc + ) + } + + /** + * Gets an assigned expr, either in the form `x = ` or `atomic_store(&x, )`. + */ + Expr getAnAssignedExpr() { + result = getAtomicFunctionCall().getArgument(1) + or + exists(AssignExpr assign | + assign.getLValue() = this + and result = assign.getRValue() + ) + } + + /** + * Gets the expression holding this variable access, either in the form `x` or `atomic_read(&x)`. + */ + Expr getARead() { + result = getAtomicFunctionCall() + or + result = this + } +} + +from + AtomicAccessInFullExpressionOrdering config, FullExpr e, Variable v, + AtomicVariableAccess va1, AtomicVariableAccess va2 +where + not isExcluded(e, SideEffects3Package::unsequencedAtomicReadsQuery()) and + e = va1.(ConstituentExpr).getFullExpr() and + config.isUnsequenced(va1, va2) and + v = va1.getTarget() and + v = va2.getTarget() and + // Exclude cases where the variable is assigned a value tainted by the other variable access. + not exists(Expr write | + write = va1.getAnAssignedExpr() and + TaintTracking::localTaint(DataFlow::exprNode(va2.getARead()), DataFlow::exprNode(write)) + ) and + // Impose an ordering, show the first access. + va1.getLocation().isBefore(va2.getLocation(), _) +select e, "Atomic variable $@ has a $@ that is unsequenced with $@.", + v, v.getName(), va1, "previous read", va2, "another read" diff --git a/c/misra/src/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.ql b/c/misra/src/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.ql index 6eb605dbd9..58d449a59b 100644 --- a/c/misra/src/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.ql +++ b/c/misra/src/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.ql @@ -16,27 +16,38 @@ import cpp import codingstandards.c.misra -class IllegalCCommentCharacter extends string { - IllegalCCommentCharacter() { - this = "/*" or - this = "//" - } +/* Character sequence is banned from all comment types */ +class IllegalCommentSequence extends string { + IllegalCommentSequence() { this = "/*" } } -class IllegalCPPCommentCharacter extends string { - IllegalCPPCommentCharacter() { this = "/*" } +/* A regexp to check for illegal C-style comments */ +class IllegalCCommentRegexp extends string { + IllegalCCommentRegexp() { + // Regexp to match "//" in C-style comments, which do not appear to be URLs. General format + // uses negative lookahead/lookbehind to match like `.*(? 0 + exists(IllegalCommentSequence c | illegalSequence = c | + comment.getContents().indexOf(illegalSequence) > 0 ) or - exists(IllegalCPPCommentCharacter c | illegalSequence = c | - comment.(CppStyleComment).getContents().indexOf(illegalSequence) > 0 + exists(IllegalCCommentRegexp c | illegalSequence = c.getDescription() | + comment.(CStyleComment).getContents().regexpMatch(c) ) ) select comment, "Comment contains an illegal sequence '" + illegalSequence + "'" diff --git a/c/misra/test/rules/RULE-11-3/CastBetweenObjectPointerAndDifferentObjectType.expected b/c/misra/test/rules/RULE-11-3/CastBetweenObjectPointerAndDifferentObjectType.expected index 94cf6ee635..24e6c4d5af 100644 --- a/c/misra/test/rules/RULE-11-3/CastBetweenObjectPointerAndDifferentObjectType.expected +++ b/c/misra/test/rules/RULE-11-3/CastBetweenObjectPointerAndDifferentObjectType.expected @@ -6,3 +6,7 @@ | test.c:21:3:21:16 | (int *)... | Cast performed between a pointer to object type (char) and a pointer to a different object type (int). | | test.c:22:20:22:21 | (int *)... | Cast performed between a pointer to object type (char) and a pointer to a different object type (int). | | test.c:23:3:23:18 | (long long *)... | Cast performed between a pointer to object type (int) and a pointer to a different object type (long long). | +| test.c:26:3:26:13 | (char *)... | Cast performed between a pointer to object type (_Atomic(int)) and a pointer to a different object type (char). | +| test.c:27:8:27:10 | (char *)... | Cast performed between a pointer to object type (_Atomic(int)) and a pointer to a different object type (char). | +| test.c:28:3:28:21 | (_Atomic(char) *)... | Cast performed between a pointer to object type (_Atomic(int)) and a pointer to a different object type (_Atomic(char)). | +| test.c:29:23:29:25 | (_Atomic(char) *)... | Cast performed between a pointer to object type (_Atomic(int)) and a pointer to a different object type (_Atomic(char)). | diff --git a/c/misra/test/rules/RULE-11-3/test.c b/c/misra/test/rules/RULE-11-3/test.c index 4730aeac03..0d91740438 100644 --- a/c/misra/test/rules/RULE-11-3/test.c +++ b/c/misra/test/rules/RULE-11-3/test.c @@ -21,4 +21,10 @@ void f1(void) { (int *const)v2; // NON_COMPLIANT int *const v10 = v2; // NON_COMPLIANT (long long *)v10; // NON_COMPLIANT + + _Atomic int *v11 = 0; + (char *)v11; // NON_COMPLIANT + v2 = v11; // NON_COMPLIANT + (_Atomic char *)v11; // NON_COMPLIANT + _Atomic char *v12 = v11; // NON_COMPLIANT } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-11-8/CastRemovesConstOrVolatileQualification.expected b/c/misra/test/rules/RULE-11-8/CastRemovesConstOrVolatileQualification.expected index 48658e2176..aa7752d28a 100644 --- a/c/misra/test/rules/RULE-11-8/CastRemovesConstOrVolatileQualification.expected +++ b/c/misra/test/rules/RULE-11-8/CastRemovesConstOrVolatileQualification.expected @@ -1,2 +1,6 @@ | test.c:4:19:4:33 | (const char *)... | Cast of pointer removes volatile qualification from its base type. | | test.c:6:13:6:21 | (char *)... | Cast of pointer removes const qualification from its base type. | +| test.c:9:3:9:11 | (char *)... | Cast of pointer removes atomic qualification from its base type. | +| test.c:10:7:10:7 | (char *)... | Cast of pointer removes atomic qualification from its base type. | +| test.c:11:3:11:17 | (const char *)... | Cast of pointer removes atomic qualification from its base type. | +| test.c:12:7:12:7 | (const char *)... | Cast of pointer removes atomic qualification from its base type. | diff --git a/c/misra/test/rules/RULE-11-8/test.c b/c/misra/test/rules/RULE-11-8/test.c index 75c7fc189a..e0e3b3a2fb 100644 --- a/c/misra/test/rules/RULE-11-8/test.c +++ b/c/misra/test/rules/RULE-11-8/test.c @@ -5,5 +5,12 @@ int f1(void) { const char *c2 = (const char *)c; // COMPLIANT char *d = (char *)c; // NON_COMPLIANT const char *e = (const char *)d; // COMPLIANT + _Atomic char *f = 0; + (char *)f; // NON_COMPLIANT + d = f; // NON_COMPLIANT + (const char *)f; // NON_COMPLIANT + e = f; // NON_COMPLIANT + (const _Atomic char *)f; // COMPLIANT + (const _Atomic char *)f; // COMPLIANT return 0; } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected b/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected new file mode 100644 index 0000000000..e84aef7128 --- /dev/null +++ b/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected @@ -0,0 +1,5 @@ +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:89,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:89,67-75) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:89,5-18) +| test.c:44:12:44:18 | ... + ... | Atomic variable $@ has a $@ that is unsequenced with $@. | test.c:42:15:42:16 | a1 | a1 | test.c:44:12:44:13 | a1 | previous read | test.c:44:17:44:18 | a1 | another read | +| test.c:46:3:46:37 | ... + ... | Atomic variable $@ has a $@ that is unsequenced with $@. | test.c:42:15:42:16 | a1 | a1 | test.c:46:16:46:17 | a1 | previous read | test.c:46:35:46:36 | a1 | another read | diff --git a/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.qlref b/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.qlref new file mode 100644 index 0000000000..46242df1b0 --- /dev/null +++ b/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.qlref @@ -0,0 +1 @@ +rules/RULE-13-2/UnsequencedAtomicReads.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-13-2/UnsequencedSideEffects.expected b/c/misra/test/rules/RULE-13-2/UnsequencedSideEffects.expected index 75bd8169ba..b6c704322c 100644 --- a/c/misra/test/rules/RULE-13-2/UnsequencedSideEffects.expected +++ b/c/misra/test/rules/RULE-13-2/UnsequencedSideEffects.expected @@ -1,6 +1,6 @@ -| test.c:6:12:6:18 | ... + ... | The expression contains unsequenced $@ to $@ and $@ to $@. | test.c:6:12:6:13 | l1 | side effect | test.c:6:12:6:13 | l1 | l1 | test.c:6:17:6:18 | l1 | side effect | test.c:6:17:6:18 | l1 | l1 | -| test.c:7:12:7:18 | ... + ... | The expression contains unsequenced $@ to $@ and $@ to $@. | test.c:7:12:7:13 | l1 | side effect | test.c:7:12:7:13 | l1 | l1 | test.c:7:17:7:18 | l2 | side effect | test.c:7:17:7:18 | l2 | l2 | -| test.c:17:3:17:21 | ... = ... | The expression contains unsequenced $@ to $@ and $@ to $@. | test.c:17:8:17:9 | l1 | side effect | test.c:17:8:17:9 | l1 | l1 | test.c:17:13:17:14 | l1 | side effect | test.c:17:13:17:14 | l1 | l1 | -| test.c:19:3:19:5 | call to foo | The expression contains unsequenced $@ to $@ and $@ to $@. | test.c:19:7:19:8 | l1 | side effect | test.c:19:7:19:8 | l1 | l1 | test.c:19:11:19:12 | l2 | side effect | test.c:19:11:19:12 | l2 | l2 | -| test.c:25:3:25:5 | call to foo | The expression contains unsequenced $@ to $@ and $@ to $@. | test.c:25:7:25:10 | ... ++ | side effect | test.c:25:7:25:8 | l8 | l8 | test.c:25:13:25:14 | l8 | read | test.c:25:13:25:14 | l8 | l8 | -| test.c:35:5:35:13 | ... = ... | The expression contains unsequenced $@ to $@ and $@ to $@. | test.c:35:10:35:12 | ... ++ | side effect | test.c:35:10:35:10 | i | i | test.c:35:10:35:12 | ... ++ | side effect | test.c:35:10:35:10 | i | i | \ No newline at end of file +| test.c:8:12:8:18 | ... + ... | The expression contains unsequenced $@ to $@ and $@ to $@. | test.c:8:12:8:13 | l1 | side effect | test.c:8:12:8:13 | l1 | l1 | test.c:8:17:8:18 | l1 | side effect | test.c:8:17:8:18 | l1 | l1 | +| test.c:9:12:9:18 | ... + ... | The expression contains unsequenced $@ to $@ and $@ to $@. | test.c:9:12:9:13 | l1 | side effect | test.c:9:12:9:13 | l1 | l1 | test.c:9:17:9:18 | l2 | side effect | test.c:9:17:9:18 | l2 | l2 | +| test.c:19:3:19:21 | ... = ... | The expression contains unsequenced $@ to $@ and $@ to $@. | test.c:19:8:19:9 | l1 | side effect | test.c:19:8:19:9 | l1 | l1 | test.c:19:13:19:14 | l1 | side effect | test.c:19:13:19:14 | l1 | l1 | +| test.c:21:3:21:5 | call to foo | The expression contains unsequenced $@ to $@ and $@ to $@. | test.c:21:7:21:8 | l1 | side effect | test.c:21:7:21:8 | l1 | l1 | test.c:21:11:21:12 | l2 | side effect | test.c:21:11:21:12 | l2 | l2 | +| test.c:27:3:27:5 | call to foo | The expression contains unsequenced $@ to $@ and $@ to $@. | test.c:27:7:27:10 | ... ++ | side effect | test.c:27:7:27:8 | l8 | l8 | test.c:27:13:27:14 | l8 | read | test.c:27:13:27:14 | l8 | l8 | +| test.c:37:5:37:13 | ... = ... | The expression contains unsequenced $@ to $@ and $@ to $@. | test.c:37:10:37:12 | ... ++ | side effect | test.c:37:10:37:10 | i | i | test.c:37:10:37:12 | ... ++ | side effect | test.c:37:10:37:10 | i | i | diff --git a/c/misra/test/rules/RULE-13-2/test.c b/c/misra/test/rules/RULE-13-2/test.c index 1bebec3775..6821a37296 100644 --- a/c/misra/test/rules/RULE-13-2/test.c +++ b/c/misra/test/rules/RULE-13-2/test.c @@ -1,3 +1,5 @@ +#include + void foo(int, int); void unsequenced_sideeffects1() { @@ -34,4 +36,15 @@ void unsequenced_sideeffects2() { for (i = 0; i < 10; i++) { test(i++); // NON_COMPLIANT } +} + +void atomics() { + _Atomic int a1, a2; + int l3 = a1 + a2; // COMPLIANT + int l4 = a1 + a1; // NON_COMPLIANT + a1 = a1 + 1; // COMPLIANT + atomic_load(&a1) + atomic_load(&a1); // NON_COMPLIANT + atomic_load(&a1) + atomic_load(&a2); // COMPLIANT + atomic_store(&a1, atomic_load(&a1)); // COMPLIANT + atomic_store(&a1, a1); // COMPLIANT } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.expected b/c/misra/test/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.expected index 5e876cecc3..5008fb100d 100644 --- a/c/misra/test/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.expected +++ b/c/misra/test/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.expected @@ -1,3 +1,5 @@ | test.c:9:1:9:8 | /* /* */ | Comment contains an illegal sequence '/*' | | test.c:12:1:12:8 | /* // */ | Comment contains an illegal sequence '//' | | test.c:21:1:21:7 | // /* | Comment contains an illegal sequence '/*' | +| test.c:30:1:30:27 | /* https://github.com // */ | Comment contains an illegal sequence '//' | +| test.c:33:1:33:60 | /* a://b, a://b., ://a.b, a://b., a://.b, ://, a://, ://b */ | Comment contains an illegal sequence '//' | diff --git a/c/misra/test/rules/RULE-3-1/test.c b/c/misra/test/rules/RULE-3-1/test.c index c1a135f972..ad61fd0f91 100644 --- a/c/misra/test/rules/RULE-3-1/test.c +++ b/c/misra/test/rules/RULE-3-1/test.c @@ -20,4 +20,19 @@ // NON_COMPLIANT // /* +// COMPLIANT +/* https://github.com */ + +// COMPLIANT +/* https://name-with-hyphen-and-num-12345.com */ + +// NON_COMPLIANT +/* https://github.com // */ + +// NON_COMPLIANT +/* a://b, a://b., ://a.b, a://b., a://.b, ://, a://, ://b */ + +// COMPLIANT +// https://github.com + void f(){} \ No newline at end of file diff --git a/change_notes/2024-12-13-implement-misra-c-amendment4-rule-amendments.md b/change_notes/2024-12-13-implement-misra-c-amendment4-rule-amendments.md new file mode 100644 index 0000000000..a8fbd282d8 --- /dev/null +++ b/change_notes/2024-12-13-implement-misra-c-amendment4-rule-amendments.md @@ -0,0 +1,10 @@ + - `RULE-11-3` - `CastBetweenObjectPointerAndDifferentObjectType.ql` + - Constrain exception that pointer types to may be cast to char types, so that it does not apply to atomic pointer types, in compliance with MISRA-C 2012 Amendment 4. + - `RULE-11-8` - `CastRemovesConstOrVolatileQualification.ql` + - Query expanded to detect cases of removing `_Atomic` qualification, in compliance with MISRA-C 2012 Amendment 4. + - `EXP33-C`, `RULE-9-1`, `A8-5-0`, `EXP53-CPP` - `DoNotReadUninitializedMemory.ql`, `ObjectWithAutoStorageDurationReadBeforeInit.ql`, `MemoryNotInitializedBeforeItIsRead.ql`, `DoNotReadUninitializedMemory.ql` + - Atomic local variables excluded from query results, in compliance with MISRA-C 2012 Amendment 4, and to reduce false positives in the other standards. + - `RULE-13-2` - `UnsequencedAtomicReads.ql` + - New query to find expressions which read an atomic variable more than once between sequence points, to address new case from MISRA-C 2012 Amendment 4. + - `RULE-3-1` - `CharacterSequencesAndUsedWithinAComment.ql` + - Add exception allowing URLs inside of cpp-style `/* ... */` comments, in compliance with MISRA-C 2012 Amendment 4 \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/SideEffects3.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/SideEffects3.qll index eff4f2caf9..7b01c18099 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/SideEffects3.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/SideEffects3.qll @@ -3,7 +3,9 @@ import cpp import RuleMetadata import codingstandards.cpp.exclusions.RuleMetadata -newtype SideEffects3Query = TUnsequencedSideEffectsQuery() +newtype SideEffects3Query = + TUnsequencedSideEffectsQuery() or + TUnsequencedAtomicReadsQuery() predicate isSideEffects3QueryMetadata(Query query, string queryId, string ruleId, string category) { query = @@ -14,6 +16,15 @@ predicate isSideEffects3QueryMetadata(Query query, string queryId, string ruleId "c/misra/unsequenced-side-effects" and ruleId = "RULE-13-2" and category = "required" + or + query = + // `Query` instance for the `unsequencedAtomicReads` query + SideEffects3Package::unsequencedAtomicReadsQuery() and + queryId = + // `@id` for the `unsequencedAtomicReads` query + "c/misra/unsequenced-atomic-reads" and + ruleId = "RULE-13-2" and + category = "required" } module SideEffects3Package { @@ -23,4 +34,11 @@ module SideEffects3Package { // `Query` type for `unsequencedSideEffects` query TQueryC(TSideEffects3PackageQuery(TUnsequencedSideEffectsQuery())) } + + Query unsequencedAtomicReadsQuery() { + //autogenerate `Query` type + result = + // `Query` type for `unsequencedAtomicReads` query + TQueryC(TSideEffects3PackageQuery(TUnsequencedAtomicReadsQuery())) + } } diff --git a/cpp/common/src/codingstandards/cpp/rules/readofuninitializedmemory/ReadOfUninitializedMemory.qll b/cpp/common/src/codingstandards/cpp/rules/readofuninitializedmemory/ReadOfUninitializedMemory.qll index 9de640db9c..8d701cb26c 100644 --- a/cpp/common/src/codingstandards/cpp/rules/readofuninitializedmemory/ReadOfUninitializedMemory.qll +++ b/cpp/common/src/codingstandards/cpp/rules/readofuninitializedmemory/ReadOfUninitializedMemory.qll @@ -131,6 +131,8 @@ class UninitializedVariable extends LocalVariable { // Not static or thread local, because they are not initialized with indeterminate values not isStatic() and not isThreadLocal() and + // Not atomic, which have special initialization rules + not getType().hasSpecifier("atomic") and // Not a class type, because default initialization of a class calls the default constructor // The default constructor may leave certain fields uninitialized, but that would be a separate // field-wise analysis diff --git a/cpp/common/test/rules/readofuninitializedmemory/test.cpp b/cpp/common/test/rules/readofuninitializedmemory/test.cpp index bdd3fdc203..6ed07d795f 100644 --- a/cpp/common/test/rules/readofuninitializedmemory/test.cpp +++ b/cpp/common/test/rules/readofuninitializedmemory/test.cpp @@ -121,4 +121,6 @@ void test_non_default_init() { use(slp); // COMPLIANT - static variables are zero initialized thread_local int *tlp; use(tlp); // COMPLIANT - thread local variables are zero initialized + _Atomic int ai; + use(ai); // COMPLIANT - atomics are special and not covered by this rule } \ No newline at end of file diff --git a/rule_packages/c/SideEffects3.json b/rule_packages/c/SideEffects3.json index 2bf91d77b9..369f5db9ee 100644 --- a/rule_packages/c/SideEffects3.json +++ b/rule_packages/c/SideEffects3.json @@ -16,6 +16,18 @@ "correctness", "external/misra/c/2012/third-edition-first-revision" ] + }, + { + "description": "The value of an atomic variable shall not depend on evaluation order and interleaving of threads.", + "kind": "problem", + "name": "The value of an atomic variable depend on its evaluation order and interleave of threads", + "precision": "very-high", + "severity": "error", + "short_name": "UnsequencedAtomicReads", + "tags": [ + "correctness", + "external/misra/c/2012/amendment3" + ] } ], "title": "The value of an expression and its persistent side effects shall be the same under all permitted evaluation orders" From 8403a4bcd6d5f52afd8ab29441b33b52c002e3bd Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 18 Dec 2024 18:39:46 -0800 Subject: [PATCH 118/370] Fix format --- .../rules/RULE-13-2/UnsequencedAtomicReads.ql | 24 +++++++++---------- c/misra/test/rules/RULE-13-2/test.c | 8 +++---- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql b/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql index d7638229d6..68f00be15f 100644 --- a/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql +++ b/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql @@ -33,22 +33,20 @@ class AtomicAccessInFullExpressionOrdering extends Ordering::Configuration { /** * A read of a variable specified as `_Atomic`. - * + * * Note, it may be accessed directly, or by passing its address into the std atomic functions. */ class AtomicVariableAccess extends VariableAccess { pragma[noinline] - AtomicVariableAccess() { - getTarget().getType().hasSpecifier("atomic") - } + AtomicVariableAccess() { getTarget().getType().hasSpecifier("atomic") } /* Get the `atomic_()` call this VarAccess occurs in. */ FunctionCall getAtomicFunctionCall() { exists(AddressOfExpr addrParent, FunctionCall fc | fc.getTarget().getName().matches("__c11_atomic%") and addrParent = fc.getArgument(0) and - addrParent.getAnOperand() = this - and result = fc + addrParent.getAnOperand() = this and + result = fc ) } @@ -59,8 +57,8 @@ class AtomicVariableAccess extends VariableAccess { result = getAtomicFunctionCall().getArgument(1) or exists(AssignExpr assign | - assign.getLValue() = this - and result = assign.getRValue() + assign.getLValue() = this and + result = assign.getRValue() ) } @@ -75,8 +73,8 @@ class AtomicVariableAccess extends VariableAccess { } from - AtomicAccessInFullExpressionOrdering config, FullExpr e, Variable v, - AtomicVariableAccess va1, AtomicVariableAccess va2 + AtomicAccessInFullExpressionOrdering config, FullExpr e, Variable v, AtomicVariableAccess va1, + AtomicVariableAccess va2 where not isExcluded(e, SideEffects3Package::unsequencedAtomicReadsQuery()) and e = va1.(ConstituentExpr).getFullExpr() and @@ -89,6 +87,6 @@ where TaintTracking::localTaint(DataFlow::exprNode(va2.getARead()), DataFlow::exprNode(write)) ) and // Impose an ordering, show the first access. - va1.getLocation().isBefore(va2.getLocation(), _) -select e, "Atomic variable $@ has a $@ that is unsequenced with $@.", - v, v.getName(), va1, "previous read", va2, "another read" + va1.getLocation().isBefore(va2.getLocation(), _) +select e, "Atomic variable $@ has a $@ that is unsequenced with $@.", v, v.getName(), va1, + "previous read", va2, "another read" diff --git a/c/misra/test/rules/RULE-13-2/test.c b/c/misra/test/rules/RULE-13-2/test.c index 6821a37296..e1be53a037 100644 --- a/c/misra/test/rules/RULE-13-2/test.c +++ b/c/misra/test/rules/RULE-13-2/test.c @@ -40,11 +40,11 @@ void unsequenced_sideeffects2() { void atomics() { _Atomic int a1, a2; - int l3 = a1 + a2; // COMPLIANT - int l4 = a1 + a1; // NON_COMPLIANT - a1 = a1 + 1; // COMPLIANT + int l3 = a1 + a2; // COMPLIANT + int l4 = a1 + a1; // NON_COMPLIANT + a1 = a1 + 1; // COMPLIANT atomic_load(&a1) + atomic_load(&a1); // NON_COMPLIANT atomic_load(&a1) + atomic_load(&a2); // COMPLIANT atomic_store(&a1, atomic_load(&a1)); // COMPLIANT - atomic_store(&a1, a1); // COMPLIANT + atomic_store(&a1, a1); // COMPLIANT } \ No newline at end of file From 7732fd690d5704f939acc732e96581f83e00772b Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 19 Dec 2024 12:49:47 -0800 Subject: [PATCH 119/370] Fix cert test --- .../CON40-C/AtomicVariableTwiceInExpression.expected | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/c/cert/test/rules/CON40-C/AtomicVariableTwiceInExpression.expected b/c/cert/test/rules/CON40-C/AtomicVariableTwiceInExpression.expected index ddff311b59..42d3ea924d 100644 --- a/c/cert/test/rules/CON40-C/AtomicVariableTwiceInExpression.expected +++ b/c/cert/test/rules/CON40-C/AtomicVariableTwiceInExpression.expected @@ -1,6 +1,6 @@ | test.c:7:18:7:39 | ATOMIC_VAR_INIT(value) | Atomic variable possibly referred to twice in an $@. | test.c:33:3:33:10 | ... += ... | expression | | test.c:7:18:7:39 | ATOMIC_VAR_INIT(value) | Atomic variable possibly referred to twice in an $@. | test.c:34:3:34:13 | ... = ... | expression | -| test.c:11:3:11:23 | atomic_store(a,b) | Atomic variable possibly referred to twice in an $@. | test.c:11:3:11:23 | atomic_store(a,b) | expression | -| test.c:12:3:12:35 | atomic_store_explicit(a,b,c) | Atomic variable possibly referred to twice in an $@. | test.c:12:3:12:35 | atomic_store_explicit(a,b,c) | expression | -| test.c:25:3:25:49 | atomic_compare_exchange_weak(a,b,c) | Atomic variable possibly referred to twice in an $@. | test.c:25:3:25:49 | atomic_compare_exchange_weak(a,b,c) | expression | -| test.c:26:3:27:42 | atomic_compare_exchange_weak_explicit(a,b,c,d,e) | Atomic variable possibly referred to twice in an $@. | test.c:26:3:27:42 | atomic_compare_exchange_weak_explicit(a,b,c,d,e) | expression | +| test.c:11:3:11:23 | atomic_store(object,desired) | Atomic variable possibly referred to twice in an $@. | test.c:11:3:11:23 | atomic_store(object,desired) | expression | +| test.c:12:3:12:23 | atomic_store_explicit | Atomic variable possibly referred to twice in an $@. | test.c:12:3:12:23 | atomic_store_explicit | expression | +| test.c:25:3:25:49 | atomic_compare_exchange_weak(object,expected,desired) | Atomic variable possibly referred to twice in an $@. | test.c:25:3:25:49 | atomic_compare_exchange_weak(object,expected,desired) | expression | +| test.c:26:3:26:39 | atomic_compare_exchange_weak_explicit | Atomic variable possibly referred to twice in an $@. | test.c:26:3:26:39 | atomic_compare_exchange_weak_explicit | expression | From 45e6b5289862db731a59e025ec5b2fab5ff8bc2a Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 20 Dec 2024 13:43:59 -0800 Subject: [PATCH 120/370] fix tests --- .../WrapFunctionsThatCanFailSpuriouslyInLoop.expected | 8 ++++---- .../test/rules/RULE-13-2/UnsequencedAtomicReads.expected | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/c/cert/test/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.expected b/c/cert/test/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.expected index 0c1e25cd00..b1c224173e 100644 --- a/c/cert/test/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.expected +++ b/c/cert/test/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.expected @@ -1,4 +1,4 @@ -| test.c:6:8:6:46 | atomic_compare_exchange_weak(a,b,c) | Function that can spuriously fail not wrapped in a loop. | -| test.c:10:3:10:41 | atomic_compare_exchange_weak(a,b,c) | Function that can spuriously fail not wrapped in a loop. | -| test.c:12:8:13:47 | atomic_compare_exchange_weak_explicit(a,b,c,d,e) | Function that can spuriously fail not wrapped in a loop. | -| test.c:17:3:17:56 | atomic_compare_exchange_weak_explicit(a,b,c,d,e) | Function that can spuriously fail not wrapped in a loop. | +| test.c:6:8:6:46 | atomic_compare_exchange_weak(object,expected,desired) | Function that can spuriously fail not wrapped in a loop. | +| test.c:10:3:10:41 | atomic_compare_exchange_weak(object,expected,desired) | Function that can spuriously fail not wrapped in a loop. | +| test.c:12:8:12:44 | atomic_compare_exchange_weak_explicit | Function that can spuriously fail not wrapped in a loop. | +| test.c:17:3:17:39 | atomic_compare_exchange_weak_explicit | Function that can spuriously fail not wrapped in a loop. | diff --git a/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected b/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected index e84aef7128..2231a83735 100644 --- a/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected +++ b/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected @@ -1,5 +1,5 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:89,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:89,67-75) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:89,5-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:87,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:87,67-75) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:87,5-18) | test.c:44:12:44:18 | ... + ... | Atomic variable $@ has a $@ that is unsequenced with $@. | test.c:42:15:42:16 | a1 | a1 | test.c:44:12:44:13 | a1 | previous read | test.c:44:17:44:18 | a1 | another read | | test.c:46:3:46:37 | ... + ... | Atomic variable $@ has a $@ that is unsequenced with $@. | test.c:42:15:42:16 | a1 | a1 | test.c:46:16:46:17 | a1 | previous read | test.c:46:35:46:36 | a1 | another read | From 81ff0c08005b59e4b2bcd87c97b30da738e4e435 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Fri, 27 Dec 2024 23:38:55 +0000 Subject: [PATCH 121/370] Skip external help integration from forks PRs from forks do not have access to the help repo. --- .github/workflows/code-scanning-pack-gen.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/code-scanning-pack-gen.yml b/.github/workflows/code-scanning-pack-gen.yml index 1b620260c3..51ffb1edb7 100644 --- a/.github/workflows/code-scanning-pack-gen.yml +++ b/.github/workflows/code-scanning-pack-gen.yml @@ -80,6 +80,8 @@ jobs: - name: Checkout external help files id: checkout-external-help-files + # Forks do not have access to an appropriate token for the help files + if: !github.event.pull_request.head.repo.fork uses: actions/checkout@v4 with: ssh-key: ${{ secrets.CODEQL_CODING_STANDARDS_HELP_KEY }} @@ -88,7 +90,7 @@ jobs: path: external-help-files - name: Include external help files - if: steps.checkout-external-help-files.outcome == 'success' + if: !github.event.pull_request.head.repo.fork && steps.checkout-external-help-files.outcome == 'success' run: | pushd external-help-files find . -name '*.md' -exec rsync -av --relative {} "$GITHUB_WORKSPACE" \; From 30fdad18a36ea99fa6049748373b8b7bc2b59a38 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2024 04:17:43 +0000 Subject: [PATCH 122/370] Bump peter-evans/create-pull-request from 7.0.5 to 7.0.6 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.5 to 7.0.6. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/5e914681df9dc83aa4e4905692ca88beb2f9e91f...67ccf781d68cd99b580ae25a5c18a1cc84ffff1f) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/upgrade_codeql_dependencies.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/upgrade_codeql_dependencies.yml b/.github/workflows/upgrade_codeql_dependencies.yml index 841b78fcd6..ca6779871e 100644 --- a/.github/workflows/upgrade_codeql_dependencies.yml +++ b/.github/workflows/upgrade_codeql_dependencies.yml @@ -53,7 +53,7 @@ jobs: find c \( -name '*.ql' -or -name '*.qll' \) -print0 | xargs -0 --max-procs "$XARGS_MAX_PROCS" codeql query format --in-place - name: Create Pull Request - uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 + uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 with: title: "Upgrade `github/codeql` dependency to ${{ github.event.inputs.codeql_cli_version }}" body: | From 99af17c4b0737a51b460456bc82f6757f4f8868a Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sat, 4 Jan 2025 21:00:10 -0800 Subject: [PATCH 123/370] Implement RULE-11-10 banning atomic void. --- .../AtomicQualifierAppliedToVoid.ql | 36 +++++++++++++++++++ .../AtomicQualifierAppliedToVoid.expected | 3 ++ .../AtomicQualifierAppliedToVoid.qlref | 1 + c/misra/test/rules/RULE-11-10/test.c | 18 ++++++++++ .../cpp/exclusions/c/Declarations9.qll | 26 ++++++++++++++ .../cpp/exclusions/c/RuleMetadata.qll | 3 ++ rule_packages/c/Declarations9.json | 25 +++++++++++++ rules.csv | 2 +- 8 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 c/misra/src/rules/RULE-11-10/AtomicQualifierAppliedToVoid.ql create mode 100644 c/misra/test/rules/RULE-11-10/AtomicQualifierAppliedToVoid.expected create mode 100644 c/misra/test/rules/RULE-11-10/AtomicQualifierAppliedToVoid.qlref create mode 100644 c/misra/test/rules/RULE-11-10/test.c create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/c/Declarations9.qll create mode 100644 rule_packages/c/Declarations9.json diff --git a/c/misra/src/rules/RULE-11-10/AtomicQualifierAppliedToVoid.ql b/c/misra/src/rules/RULE-11-10/AtomicQualifierAppliedToVoid.ql new file mode 100644 index 0000000000..d867241518 --- /dev/null +++ b/c/misra/src/rules/RULE-11-10/AtomicQualifierAppliedToVoid.ql @@ -0,0 +1,36 @@ +/** + * @id c/misra/atomic-qualifier-applied-to-void + * @name RULE-11-10: The _Atomic qualifier shall not be applied to the incomplete type void + * @description Conversions between types by using an _Atomic void type may result in undefined + * behavior. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-11-10 + * correctness + * external/misra/c/2012/third-edition-first-revision + * external/misra/c/2012/amendment4 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra + +class AtomicVoidType extends Type { + AtomicVoidType() { + hasSpecifier("atomic") and + getUnspecifiedType() instanceof VoidType + } +} + +Type getNestedType(Type root) { + result = root + or + exists(DerivedType derived | derived = root | result = getNestedType(derived.getBaseType())) +} + +from DeclarationEntry decl, AtomicVoidType atomicVoid +where + not isExcluded(decl, Declarations9Package::atomicQualifierAppliedToVoidQuery()) and + atomicVoid = getNestedType(decl.getType()) +select decl, decl.getName() + " declared with an atomic void type." diff --git a/c/misra/test/rules/RULE-11-10/AtomicQualifierAppliedToVoid.expected b/c/misra/test/rules/RULE-11-10/AtomicQualifierAppliedToVoid.expected new file mode 100644 index 0000000000..e3a6746ae7 --- /dev/null +++ b/c/misra/test/rules/RULE-11-10/AtomicQualifierAppliedToVoid.expected @@ -0,0 +1,3 @@ +| test.c:3:15:3:16 | definition of g3 | g3 declared with an atomic void type. | +| test.c:10:17:10:18 | definition of m3 | m3 declared with an atomic void type. | +| test.c:15:22:15:23 | definition of p2 | p2 declared with an atomic void type. | diff --git a/c/misra/test/rules/RULE-11-10/AtomicQualifierAppliedToVoid.qlref b/c/misra/test/rules/RULE-11-10/AtomicQualifierAppliedToVoid.qlref new file mode 100644 index 0000000000..2046575237 --- /dev/null +++ b/c/misra/test/rules/RULE-11-10/AtomicQualifierAppliedToVoid.qlref @@ -0,0 +1 @@ +rules/RULE-11-10/AtomicQualifierAppliedToVoid.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-11-10/test.c b/c/misra/test/rules/RULE-11-10/test.c new file mode 100644 index 0000000000..e030345dde --- /dev/null +++ b/c/misra/test/rules/RULE-11-10/test.c @@ -0,0 +1,18 @@ +// _Atomic void g1; // doesn't compile +_Atomic int g2; // COMPLIANT +_Atomic void *g3; // NON_COMPLIANT +// _Atomic void g4[]; // doesn't compile +void *_Atomic g5; // COMPLIANT + +struct { + _Atomic int m1; // COMPLIANT + // _Atomic void m2; // doesn't compile + _Atomic void *m3; // NON_COMPLIANT + void *_Atomic m4; // COMPLIANT +} s1; + +void f(_Atomic int p1, // COMPLIANT + _Atomic void *p2 // NON_COMPLIANT + // _Atomic void p3[] // doesn't compile, even though it perhaps should as + // it is adjusted to void*. +) {} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations9.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations9.qll new file mode 100644 index 0000000000..8a63e50ed4 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations9.qll @@ -0,0 +1,26 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype Declarations9Query = TAtomicQualifierAppliedToVoidQuery() + +predicate isDeclarations9QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `atomicQualifierAppliedToVoid` query + Declarations9Package::atomicQualifierAppliedToVoidQuery() and + queryId = + // `@id` for the `atomicQualifierAppliedToVoid` query + "c/misra/atomic-qualifier-applied-to-void" and + ruleId = "RULE-11-10" and + category = "required" +} + +module Declarations9Package { + Query atomicQualifierAppliedToVoidQuery() { + //autogenerate `Query` type + result = + // `Query` type for `atomicQualifierAppliedToVoid` query + TQueryC(TDeclarations9PackageQuery(TAtomicQualifierAppliedToVoidQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index 1562ba7894..448b764526 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -28,6 +28,7 @@ import Declarations5 import Declarations6 import Declarations7 import Declarations8 +import Declarations9 import EssentialTypes import Expressions import FloatingTypes @@ -107,6 +108,7 @@ newtype TCQuery = TDeclarations6PackageQuery(Declarations6Query q) or TDeclarations7PackageQuery(Declarations7Query q) or TDeclarations8PackageQuery(Declarations8Query q) or + TDeclarations9PackageQuery(Declarations9Query q) or TEssentialTypesPackageQuery(EssentialTypesQuery q) or TExpressionsPackageQuery(ExpressionsQuery q) or TFloatingTypesPackageQuery(FloatingTypesQuery q) or @@ -186,6 +188,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isDeclarations6QueryMetadata(query, queryId, ruleId, category) or isDeclarations7QueryMetadata(query, queryId, ruleId, category) or isDeclarations8QueryMetadata(query, queryId, ruleId, category) or + isDeclarations9QueryMetadata(query, queryId, ruleId, category) or isEssentialTypesQueryMetadata(query, queryId, ruleId, category) or isExpressionsQueryMetadata(query, queryId, ruleId, category) or isFloatingTypesQueryMetadata(query, queryId, ruleId, category) or diff --git a/rule_packages/c/Declarations9.json b/rule_packages/c/Declarations9.json new file mode 100644 index 0000000000..ebfcf7c41f --- /dev/null +++ b/rule_packages/c/Declarations9.json @@ -0,0 +1,25 @@ +{ + "MISRA-C-2012": { + "RULE-11-10": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Conversions between types by using an _Atomic void type may result in undefined behavior.", + "kind": "problem", + "name": "The _Atomic qualifier shall not be applied to the incomplete type void", + "precision": "very-high", + "severity": "error", + "short_name": "AtomicQualifierAppliedToVoid", + "tags": [ + "correctness", + "external/misra/c/2012/third-edition-first-revision", + "external/misra/c/2012/amendment4" + ] + } + ], + "title": "The _Atomic qualifier shall not be applied to the incomplete type void" + } + } +} \ No newline at end of file diff --git a/rules.csv b/rules.csv index 475ea1d66c..6657055cad 100644 --- a/rules.csv +++ b/rules.csv @@ -677,7 +677,7 @@ c,MISRA-C-2012,RULE-9-2,Yes,Required,,,The initializer for an aggregate or union 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,No,Required,,,Where designated initializers are used to initialize an array object the size of the array shall be specified explicitly,,,Medium, -c,MISRA-C-2012,RULE-9-6,Yes,Required,,,An initializer using chained designators shall not contain initializers without designators,,Declarations9,Hard, +c,MISRA-C-2012,RULE-9-6,Yes,Required,,,An initializer using chained designators shall not contain initializers without designators,,Declarations10,Hard, c,MISRA-C-2012,RULE-9-7,Yes,Mandatory,,,Atomic objects shall be appropriately initialized before being accessed,,Concurrency6,Hard, c,MISRA-C-2012,RULE-10-1,Yes,Required,,,Operands shall not be of an inappropriate essential type,,EssentialTypes,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,,EssentialTypes,Medium, From 6b8ba85dea62ff4ebac192b15db278e51cb431c0 Mon Sep 17 00:00:00 2001 From: Luke Cartey <5377966+lcartey@users.noreply.github.com> Date: Sun, 5 Jan 2025 23:05:14 +0000 Subject: [PATCH 124/370] Update rules.csv Use Contracts8 as next entry --- rules.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules.csv b/rules.csv index 8391149b9f..a7f6c1f0db 100644 --- a/rules.csv +++ b/rules.csv @@ -615,7 +615,7 @@ c,MISRA-C-2012,DIR-4-10,Yes,Required,,,Precautions shall be taken in order to pr c,MISRA-C-2012,DIR-4-11,Yes,Required,,,The validity of values passed to library functions shall be checked,,Contracts,Hard, c,MISRA-C-2012,DIR-4-12,Yes,Required,,,Dynamic memory allocation shall not be used,,Banned,Medium, c,MISRA-C-2012,DIR-4-13,No,Advisory,,,Functions which are designed to provide operations on a resource should be called in an appropriate sequence,,,,"Rule 22.1, 22.2 and 22.6 cover aspects of this rule. In other cases this is a design issue and needs to be checked manually." -c,MISRA-C-2012,DIR-4-14,Yes,Required,,,The validity of values received from external sources shall be checked,,Contracts9,Hard,This is supported by CodeQLs default C security queries. +c,MISRA-C-2012,DIR-4-14,Yes,Required,,,The validity of values received from external sources shall be checked,,Contracts8,Hard,This is supported by CodeQLs default C security queries. c,MISRA-C-2012,RULE-1-1,No,Required,,,"The program shall contain no violations of the standard C syntax and constraints, and shall not exceed the implementation's translation limits",,,Easy,"This should be checked via the compiler output, rather than CodeQL, which adds unnecessary steps." c,MISRA-C-2012,RULE-1-2,Yes,Advisory,,,Language extensions should not be used,,Language3,Hard, c,MISRA-C-2012,RULE-1-3,Yes,Required,,,There shall be no occurrence of undefined or critical unspecified behaviour,,Language3,Hard, From 6f595af4c404c3d77e6eea7f7f0568ecb4d5c189 Mon Sep 17 00:00:00 2001 From: Luke Cartey <5377966+lcartey@users.noreply.github.com> Date: Mon, 6 Jan 2025 10:21:17 +0000 Subject: [PATCH 125/370] Exclude Dependabot PRs from help checkout Dependabot does not have access to the external help repo. --- .github/workflows/code-scanning-pack-gen.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/code-scanning-pack-gen.yml b/.github/workflows/code-scanning-pack-gen.yml index 51ffb1edb7..b67db3d413 100644 --- a/.github/workflows/code-scanning-pack-gen.yml +++ b/.github/workflows/code-scanning-pack-gen.yml @@ -81,7 +81,7 @@ jobs: - name: Checkout external help files id: checkout-external-help-files # Forks do not have access to an appropriate token for the help files - if: !github.event.pull_request.head.repo.fork + if: !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' uses: actions/checkout@v4 with: ssh-key: ${{ secrets.CODEQL_CODING_STANDARDS_HELP_KEY }} @@ -90,7 +90,7 @@ jobs: path: external-help-files - name: Include external help files - if: !github.event.pull_request.head.repo.fork && steps.checkout-external-help-files.outcome == 'success' + if: !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]'&& steps.checkout-external-help-files.outcome == 'success' run: | pushd external-help-files find . -name '*.md' -exec rsync -av --relative {} "$GITHUB_WORKSPACE" \; From b817d0cde9701c3d2b1e343a9eb37ab224f6aff7 Mon Sep 17 00:00:00 2001 From: Luke Cartey <5377966+lcartey@users.noreply.github.com> Date: Mon, 6 Jan 2025 20:17:03 +0000 Subject: [PATCH 126/370] Improve comment Explain why we exclude dependabot PRs. --- .github/workflows/code-scanning-pack-gen.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code-scanning-pack-gen.yml b/.github/workflows/code-scanning-pack-gen.yml index b67db3d413..85a157d8b6 100644 --- a/.github/workflows/code-scanning-pack-gen.yml +++ b/.github/workflows/code-scanning-pack-gen.yml @@ -80,7 +80,7 @@ jobs: - name: Checkout external help files id: checkout-external-help-files - # Forks do not have access to an appropriate token for the help files + # PRs from forks and dependabot do not have access to an appropriate token for cloning the help files repos if: !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' uses: actions/checkout@v4 with: From b952fc8595c121804533c184eeeed739d138c09e Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 6 Jan 2025 23:27:04 +0000 Subject: [PATCH 127/370] Use expression syntax --- .github/workflows/code-scanning-pack-gen.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/code-scanning-pack-gen.yml b/.github/workflows/code-scanning-pack-gen.yml index 85a157d8b6..678b3be403 100644 --- a/.github/workflows/code-scanning-pack-gen.yml +++ b/.github/workflows/code-scanning-pack-gen.yml @@ -81,7 +81,7 @@ jobs: - name: Checkout external help files id: checkout-external-help-files # PRs from forks and dependabot do not have access to an appropriate token for cloning the help files repos - if: !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' + if: ${{ !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' }} uses: actions/checkout@v4 with: ssh-key: ${{ secrets.CODEQL_CODING_STANDARDS_HELP_KEY }} @@ -90,7 +90,7 @@ jobs: path: external-help-files - name: Include external help files - if: !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]'&& steps.checkout-external-help-files.outcome == 'success' + if: ${{ !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]'&& steps.checkout-external-help-files.outcome == 'success' }} run: | pushd external-help-files find . -name '*.md' -exec rsync -av --relative {} "$GITHUB_WORKSPACE" \; From d9a41f0f5b559e44753bdf25fa1b6f84e6a2ac60 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 9 Jan 2025 14:14:17 +0100 Subject: [PATCH 128/370] Update A2-10-4 after QL changes --- .../IdentifierNameOfStaticNonMemberObjectReusedInNamespace.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/autosar/src/rules/A2-10-4/IdentifierNameOfStaticNonMemberObjectReusedInNamespace.ql b/cpp/autosar/src/rules/A2-10-4/IdentifierNameOfStaticNonMemberObjectReusedInNamespace.ql index e04bb89cfa..79e17305fb 100644 --- a/cpp/autosar/src/rules/A2-10-4/IdentifierNameOfStaticNonMemberObjectReusedInNamespace.ql +++ b/cpp/autosar/src/rules/A2-10-4/IdentifierNameOfStaticNonMemberObjectReusedInNamespace.ql @@ -22,7 +22,7 @@ class CandidateVariable extends Variable { isStatic() and not this instanceof MemberVariable and //exclude partially specialized template variables - not exists(TemplateVariable v | this = v.getAnInstantiation()) + not this.isSpecialization() } } From 0c7b50321f47936b7857e7e5f788a62c2596bae4 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 10 Jan 2025 20:06:49 -0800 Subject: [PATCH 129/370] save work --- amendments.csv | 12 +- .../c/misra/EssentialTypes.qll | 10 +- ...dditionSubtractionOnEssentiallyCharType.ql | 2 +- ...nSubtractionOnEssentiallyCharType.expected | 34 ++-- c/misra/test/rules/RULE-10-2/test.c | 14 +- .../ControllingExprInvariant.expected | 1 + c/misra/test/rules/RULE-14-3/test.c | 7 + ...ringLiteralAssignedToNonConstChar.expected | 1 + c/misra/test/rules/RULE-7-4/test.c | 12 ++ c/misra/test/rules/RULE-8-3/function1.c | 4 + c/misra/test/rules/RULE-8-3/function2.c | 4 +- ...025-1-04-misra-c-technical-corrigenda-2.md | 11 ++ .../src/codingstandards/cpp/Compatible.qll | 8 +- ...nterArithmeticToAddressDifferentArrays.qll | 158 ++++++++++++++---- .../InvalidatedEnvStringPointers.qll | 6 + ...rithmeticToAddressDifferentArrays.expected | 14 +- .../test.cpp | 24 +++ .../InvalidatedEnvStringPointers.expected | 5 + .../invalidatedenvstringpointers/test.cpp | 37 ++++ 19 files changed, 298 insertions(+), 66 deletions(-) create mode 100644 change_notes/2025-1-04-misra-c-technical-corrigenda-2.md diff --git a/amendments.csv b/amendments.csv index ce285a29ba..20eb874fde 100644 --- a/amendments.csv +++ b/amendments.csv @@ -28,22 +28,22 @@ c,MISRA-C-2012,Corrigendum2,RULE-1-4,Yes,Replace,No,Easy c,MISRA-C-2012,Corrigendum2,RULE-9-1,Yes,Refine,No,Easy c,MISRA-C-2012,Corrigendum2,RULE-9-2,Yes,Refine,No,Import c,MISRA-C-2012,Corrigendum2,DIR-4-10,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-7-4,Yes,Refine,No,Easy +c,MISRA-C-2012,Corrigendum2,RULE-7-4,Yes,Refine,Yes,Easy c,MISRA-C-2012,Corrigendum2,RULE-8-2,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-8-3,Yes,Refine,No,Easy +c,MISRA-C-2012,Corrigendum2,RULE-8-3,Yes,Refine,Yes,Easy c,MISRA-C-2012,Corrigendum2,RULE-8-7,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-10-2,Yes,Refine,No,Easy +c,MISRA-C-2012,Corrigendum2,RULE-10-2,Yes,Refine,Yes,Easy c,MISRA-C-2012,Corrigendum2,RULE-10-3,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-11-3,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-11-6,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-13-2,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-13-6,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-14-3,Yes,Refine,No,Easy +c,MISRA-C-2012,Corrigendum2,RULE-14-3,Yes,Refine,Yes,Easy c,MISRA-C-2012,Corrigendum2,RULE-15-7,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-17-4,Yes,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-17-5,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-18-1,Yes,Refine,No,Easy +c,MISRA-C-2012,Corrigendum2,RULE-18-1,Yes,Refine,Yes,Easy c,MISRA-C-2012,Corrigendum2,RULE-20-14,No,Clarification,No,Import c,MISRA-C-2012,Corrigendum2,RULE-21-19,Yes,Clarification,No,Import -c,MISRA-C-2012,Corrigendum2,RULE-21-20,Yes,Refine,No,Easy +c,MISRA-C-2012,Corrigendum2,RULE-21-20,Yes,Refine,Yes,Easy c,MISRA-C-2012,Corrigendum2,RULE-22-9,Yes,Clarification,No,Import \ No newline at end of file diff --git a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll index 4783547ed2..b229bd54e2 100644 --- a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll +++ b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll @@ -297,12 +297,15 @@ class EssentialBinaryArithmeticExpr extends EssentialExpr, BinaryArithmeticOpera exists( Type leftEssentialType, Type rightEssentialType, EssentialTypeCategory leftEssentialTypeCategory, - EssentialTypeCategory rightEssentialTypeCategory + EssentialTypeCategory rightEssentialTypeCategory, + int intTypeSize | leftEssentialType = getEssentialType(getLeftOperand()) and rightEssentialType = getEssentialType(getRightOperand()) and leftEssentialTypeCategory = getEssentialTypeCategory(leftEssentialType) and - rightEssentialTypeCategory = getEssentialTypeCategory(rightEssentialType) + rightEssentialTypeCategory = getEssentialTypeCategory(rightEssentialType) and + // For rules around addition/subtraction with char types: + intTypeSize = any(IntType i | i.isSigned()).getSize() | if leftEssentialTypeCategory = EssentiallySignedType() and @@ -338,15 +341,18 @@ class EssentialBinaryArithmeticExpr extends EssentialExpr, BinaryArithmeticOpera ( leftEssentialTypeCategory = [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] + and leftEssentialType.getSize() <= intTypeSize or rightEssentialTypeCategory = [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] + and rightEssentialType.getSize() <= intTypeSize ) or this instanceof SubExpr and leftEssentialTypeCategory = EssentiallyCharacterType() and rightEssentialTypeCategory = [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] + and rightEssentialType.getSize() <= intTypeSize then result instanceof PlainCharType else result = this.getStandardType() ) diff --git a/c/misra/src/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.ql b/c/misra/src/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.ql index 750e589a1c..0e98c6c570 100644 --- a/c/misra/src/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.ql +++ b/c/misra/src/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.ql @@ -32,7 +32,7 @@ where // But the overall essential type is not essentially character type getEssentialTypeCategory(getEssentialType(addOrSub)) = EssentiallyCharacterType() or - // Or this is a subtration of one character with another, which is permitted, but produces an integral type + // Or this is a subtraction of one character with another, which is permitted, but produces an integral type getEssentialTypeCategory(getEssentialType(addOrSub.getLeftOperand())) = EssentiallyCharacterType() and getEssentialTypeCategory(getEssentialType(addOrSub.getRightOperand())) = diff --git a/c/misra/test/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.expected b/c/misra/test/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.expected index 0a5c7ae0bb..a1d3657a1e 100644 --- a/c/misra/test/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.expected +++ b/c/misra/test/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.expected @@ -1,15 +1,19 @@ -| test.c:15:3:15:11 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | -| test.c:16:3:16:9 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | -| test.c:17:3:17:9 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | -| test.c:18:3:18:9 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | -| test.c:19:3:19:9 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | -| test.c:20:3:20:10 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | -| test.c:21:3:21:10 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | -| test.c:27:3:27:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | -| test.c:28:3:28:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | -| test.c:29:3:29:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | -| test.c:30:3:30:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | -| test.c:31:3:31:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | -| test.c:32:3:32:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | -| test.c:33:3:33:10 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | -| test.c:34:3:34:10 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:19:3:19:11 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:20:3:20:9 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:21:3:21:9 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:22:3:22:9 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:23:3:23:9 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:24:3:24:10 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:25:3:25:10 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:28:3:28:9 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:29:3:29:10 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:35:3:35:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:36:3:36:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:37:3:37:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:38:3:38:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:39:3:39:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:40:3:40:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:41:3:41:10 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:42:3:42:10 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:45:3:45:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:46:3:46:10 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | diff --git a/c/misra/test/rules/RULE-10-2/test.c b/c/misra/test/rules/RULE-10-2/test.c index 186c49226e..1d86013c07 100644 --- a/c/misra/test/rules/RULE-10-2/test.c +++ b/c/misra/test/rules/RULE-10-2/test.c @@ -5,6 +5,10 @@ void testRules() { enum E1 { A, B, C } e1 = A; signed int i = 100; unsigned int u = 100; + signed short s = 100; + unsigned short us = 100; + signed long l = 100L; + unsigned long ul = 100UL; float f = 10.0f; // Addition cases @@ -19,8 +23,12 @@ void testRules() { b + 'a'; // NON_COMPLIANT 'a' + e1; // NON_COMPLIANT e1 + 'a'; // NON_COMPLIANT + 'a' + s; // COMPLIANT + 'a' + us; // COMPLIANT + 'a' + l; // NON_COMPLIANT + 'a' + ul; // NON_COMPLIANT - // Subtration cases + // Subtraction cases 'a' - i; // COMPLIANT 'a' - u; // COMPLIANT 'a' - 'a'; // COMPLIANT @@ -32,4 +40,8 @@ void testRules() { 'a' - b; // NON_COMPLIANT e1 - 'a'; // NON_COMPLIANT 'a' - e1; // NON_COMPLIANT + 'a' - s; // COMPLIANT + 'a' - us; // COMPLIANT + 'a' - l; // NON_COMPLIANT + 'a' - ul; // NON_COMPLIANT } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-14-3/ControllingExprInvariant.expected b/c/misra/test/rules/RULE-14-3/ControllingExprInvariant.expected index c03c04d6cc..3beb834f84 100644 --- a/c/misra/test/rules/RULE-14-3/ControllingExprInvariant.expected +++ b/c/misra/test/rules/RULE-14-3/ControllingExprInvariant.expected @@ -5,3 +5,4 @@ | test.c:27:10:27:14 | ... < ... | Controlling expression in loop statement has an invariant value. | | test.c:37:3:37:6 | 1 | Controlling expression in conditional statement has an invariant value. | | test.c:38:3:38:3 | 1 | Controlling expression in conditional statement has an invariant value. | +| test.c:45:10:45:26 | ... && ... | Controlling expression in loop statement has an invariant value. | diff --git a/c/misra/test/rules/RULE-14-3/test.c b/c/misra/test/rules/RULE-14-3/test.c index 38db3e1286..ed8854afd2 100644 --- a/c/misra/test/rules/RULE-14-3/test.c +++ b/c/misra/test/rules/RULE-14-3/test.c @@ -37,4 +37,11 @@ void f5(bool b1) { true ? 1 : 2; // NON_COMPLIANT 1 ? 1 : 2; // NON_COMPLIANT b1 ? 1 : 2; // COMPLIANT +} + +void f6(int p1) { + while (p1 < 10 && p1 > 12) { // NON_COMPLIANT[FALSE_NEGATIVE] + } + while (1 == 0 && p1 > 12) { // NON_COMPLIANT + } } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-7-4/StringLiteralAssignedToNonConstChar.expected b/c/misra/test/rules/RULE-7-4/StringLiteralAssignedToNonConstChar.expected index 46b8e5a47b..208e98f632 100644 --- a/c/misra/test/rules/RULE-7-4/StringLiteralAssignedToNonConstChar.expected +++ b/c/misra/test/rules/RULE-7-4/StringLiteralAssignedToNonConstChar.expected @@ -6,3 +6,4 @@ | test.c:58:5:58:22 | return ... | wchar_t * function w_sample3 is returning a string literal. | | test.c:69:3:69:9 | call to sample4 | char * parameter of sample4 is passed a string literal. | | test.c:78:3:78:11 | call to w_sample4 | wchar_t * parameter of w_sample4 is passed a string literal. | +| test.c:91:3:91:11 | call to w_sample7 | char * parameter of w_sample7 is passed a string literal. | diff --git a/c/misra/test/rules/RULE-7-4/test.c b/c/misra/test/rules/RULE-7-4/test.c index c178915200..ff270b611f 100644 --- a/c/misra/test/rules/RULE-7-4/test.c +++ b/c/misra/test/rules/RULE-7-4/test.c @@ -79,4 +79,16 @@ void w_call45() { w_sample5(L"string9"); // COMPLIANT: passing string literal to const char* } +void w_sample6(int x, ...) {} + +void w_call6() { + w_sample6(1, "string10"); // COMPLIANT by first (and only) exception +} + +void w_sample7(char* x, ...) {} + +void w_call7() { + w_sample7("string11", 1); // NON_COMPLIANT, does not fit exceptional case +} + int main() { return 0; } diff --git a/c/misra/test/rules/RULE-8-3/function1.c b/c/misra/test/rules/RULE-8-3/function1.c index 2072748047..7f42f87f53 100644 --- a/c/misra/test/rules/RULE-8-3/function1.c +++ b/c/misra/test/rules/RULE-8-3/function1.c @@ -24,4 +24,8 @@ a f21(wi w, wi h) { // NON_COMPLIANT void f22(int f22b, int f22a) { // NON_COMPLIANT return; +} + +void f23(int f23a) { // COMPLIANT + return; } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-3/function2.c b/c/misra/test/rules/RULE-8-3/function2.c index 979e002466..159dbe105d 100644 --- a/c/misra/test/rules/RULE-8-3/function2.c +++ b/c/misra/test/rules/RULE-8-3/function2.c @@ -16,4 +16,6 @@ typedef long a; extern a f21(wi w, hi h); // NON_COMPLIANT -extern void f22(int f22a, int f22b); // NON_COMPLIANT \ No newline at end of file +extern void f22(int f22a, int f22b); // NON_COMPLIANT + +extern void f23(int); // COMPLIANT \ No newline at end of file diff --git a/change_notes/2025-1-04-misra-c-technical-corrigenda-2.md b/change_notes/2025-1-04-misra-c-technical-corrigenda-2.md new file mode 100644 index 0000000000..81ae3eb561 --- /dev/null +++ b/change_notes/2025-1-04-misra-c-technical-corrigenda-2.md @@ -0,0 +1,11 @@ + - `RULE-8-3` - `DeclarationsOfAFunctionSameNameAndType.ql`: + - Implement new exception, unnamed parameters are not covered by this rule. + - `RULE-10-2` - `AdditionSubtractionOnEssentiallCharType.ql`: + - Disallow `+` and `-` operations with an essentially char type and other types larger than int type. + - Note, this change affects the essential type of such expressions, which may affect other essential types rules. + - `RULE-18-1`, `M5-0-16` - `PointerAndDerivedPointerMustAddressSameArray.ql`, `PointerAndDerivedPointerAccessDifferentArray.ql`: + - Treat casts to byte pointers as pointers to arrays of the size of the pointed-to type + - Fix typo in report message, "passed" replaced with "past." + - `RULE-21-10`, `RULE-25-5-3`, `ENV34-C` - `CallToSetlocaleInvalidatesOldPointers.ql`, `CallToSetlocaleInvalidatesOldPointersMisra.ql`, `DoNotStorePointersReturnedByEnvFunctions.ql`: + - Report usage of returned pointers from `asctime`, `ctime`, during a call to either of the former. + - Report usage of returned pointers from `gmtime`, `localtime`, during a call to either of the former. \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/Compatible.qll b/cpp/common/src/codingstandards/cpp/Compatible.qll index 0f6e2108ff..d2dbc55778 100644 --- a/cpp/common/src/codingstandards/cpp/Compatible.qll +++ b/cpp/common/src/codingstandards/cpp/Compatible.qll @@ -21,10 +21,10 @@ predicate parameterTypesIncompatible(FunctionDeclarationEntry f1, FunctionDeclar predicate parameterNamesIncompatible(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { f1.getDeclaration() = f2.getDeclaration() and - exists(ParameterDeclarationEntry p1, ParameterDeclarationEntry p2, int i | - p1 = f1.getParameterDeclarationEntry(i) and - p2 = f2.getParameterDeclarationEntry(i) + exists(string p1Name, string p2Name, int i | + p1Name = f1.getParameterDeclarationEntry(i).getName() and + p2Name = f2.getParameterDeclarationEntry(i).getName() | - not p1.getName() = p2.getName() + not p1Name = p2Name ) } diff --git a/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll b/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll index 57b4eb0bfb..9728bc1f6d 100644 --- a/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll +++ b/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll @@ -7,20 +7,118 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.new.DataFlow import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis +import codeql.util.Boolean abstract class DoNotUsePointerArithmeticToAddressDifferentArraysSharedQuery extends Query { } Query getQuery() { result instanceof DoNotUsePointerArithmeticToAddressDifferentArraysSharedQuery } +/** + * A `VariableAccess` of a variable that is an array, or a pointer type casted to a byte pointer. + */ +abstract class ArrayLikeAccess extends Expr { + abstract Element getElement(); + + abstract string getName(); + + abstract int getSize(); + + abstract DataFlow::Node getNode(); +} + +/** + * A `VariableAccess` of a variable that is an array. + */ +class ArrayVariableAccess extends ArrayLikeAccess, VariableAccess { + int size; + + ArrayVariableAccess() { size = getType().(ArrayType).getArraySize() } + + override Variable getElement() { result = getTarget() } + + override string getName() { result = getElement().getName() } + + override int getSize() { result = size } + + override DataFlow::Node getNode() { result.asExpr() = this } +} + +/** + * Get the size of the object pointed to by a type (pointer or array). + * + * Depth of type unwrapping depends on the type. Pointer will be dereferenced only once: the element + * size of `T*` is `sizeof(T)` while the element size of `T**` is `sizeof(T*)`. However, array types + * will be deeply unwrapped, as the pointed to size of `T[][]` is `sizeof(T)`. These processes + * interact, so the element size of a pointer to an array of `T` has an element size of `sizeof(T)` + * and not `sizeof(T[length])`. + */ +int elementSize(Type type, Boolean deref) { + if type instanceof ArrayType + then result = elementSize(type.(ArrayType).getBaseType(), false) + else + if deref = true and type instanceof PointerType + then result = elementSize(type.(PointerType).getBaseType(), false) + else result = type.getSize() +} + +/** + * A pointer type casted to a byte pointer, which is effectively a pointer to a byte array whose + * length depends on `elementSize()` of the original pointed-to type. + */ +class CastedToBytePointer extends ArrayLikeAccess, Conversion { + int size; + + CastedToBytePointer() { + getType().(PointerType).getBaseType().getSize() = 1 and + size = elementSize(getExpr().getType(), true) + } + + override Element getElement() { result = this } + + override string getName() { + result = "cast to btye pointer " + this.toString() + or + exists(Cast cast | + cast.getExpr() = this and + result = cast.getType().(PointerType).getBaseType().toString() + ) + } + + override int getSize() { result = size } + + override DataFlow::Node getNode() { result.asConvertedExpr() = this } +} + +/** + * A data-flow configuration that tracks access to an array to type to an array index expression. + * This is used to determine possible pointer to array creations. + */ +module ByteArrayToArrayExprConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { exists(CastedToBytePointer a | a.getNode() = source) } + + // TODO: casting to different size pointed-to-type invalidates + predicate isSink(DataFlow::Node sink) { exists(ArrayExpr c | c.getArrayBase() = sink.asExpr()) } +} + +module BytePointerToArrayExprFlow = DataFlow::Global; + /** * A data-flow configuration that tracks access to an array to type to an array index expression. * This is used to determine possible pointer to array creations. */ module ArrayToArrayExprConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { - source.asExpr().(VariableAccess).getType() instanceof ArrayType + predicate isSource(DataFlow::Node source) { exists(ArrayVariableAccess a | a.getNode() = source) } + + predicate isBarrier(DataFlow::Node barrier) { + // Casting to a differently sized pointer invalidates this analysis. + exists(CStyleCast cast, Expr casted | + cast.getExpr() = casted and casted = barrier.asConvertedExpr() + | + not casted.getType().(PointerType).getBaseType().getSize() = + cast.getType().(PointerType).getBaseType().getSize() + ) } predicate isSink(DataFlow::Node sink) { exists(ArrayExpr c | c.getArrayBase() = sink.asExpr()) } @@ -28,12 +126,19 @@ module ArrayToArrayExprConfig implements DataFlow::ConfigSig { module ArrayToArrayExprFlow = DataFlow::Global; -/** Holds if the address taken expression `addressOf` takes the address of an array element at `index` of `array` with size `arraySize`. */ -predicate pointerOperandCreation(AddressOfExpr addressOf, Variable array, int arraySize, int index) { - arraySize = array.getType().(ArrayType).getArraySize() and +/** Holds if the address taken expression `addressOf` takes the address of an array element at `index` of `array`. */ +predicate pointerOperandCreation(AddressOfExpr addressOf, ArrayLikeAccess array, int index) { exists(ArrayExpr ae | - ArrayToArrayExprFlow::flow(DataFlow::exprNode(array.getAnAccess()), - DataFlow::exprNode(ae.getArrayBase())) and + ( + ArrayToArrayExprFlow::flow(array.getNode(), DataFlow::exprNode(ae.getArrayBase())) and + array instanceof ArrayVariableAccess + or + // Since casts can occur in the middle of flow, barriers are not perfect for modeling the + // desired behavior. Handle casts to byte pointers as sources in a separate flow analysis. + BytePointerToArrayExprFlow::flow(array.getNode(), DataFlow::exprNode(ae.getArrayBase())) and + // flow() may hold for `ArrayVariableAccess` in the above, even though they aren't sources + array instanceof CastedToBytePointer + ) and index = lowerBound(ae.getArrayOffset().getFullyConverted()) and addressOf.getOperand() = ae ) @@ -41,19 +146,16 @@ predicate pointerOperandCreation(AddressOfExpr addressOf, Variable array, int ar /** A variable that points to an element of an array. */ class PointerOperand extends Variable { - Variable array; - int arraySize; + ArrayLikeAccess array; int index; AddressOfExpr source; PointerOperand() { - pointerOperandCreation(source, array, arraySize, index) and + pointerOperandCreation(source, array, index) and this.getAnAssignedValue() = source } - Variable getArray() { result = array } - - int getArraySize() { result = arraySize } + ArrayLikeAccess getArray() { result = array } int getIndex() { result = index } @@ -111,9 +213,7 @@ class DerivedArrayPointer extends Variable { DerivedArrayPointer() { derivedPointer(this, source, operand, index) } - Variable getArray() { result = operand.getArray() } - - int getArraySize() { result = operand.getArraySize() } + ArrayLikeAccess getArray() { result = operand.getArray() } int getIndex() { result = index } @@ -131,15 +231,10 @@ class DerivedArrayPointerOrPointerOperand extends Variable { this instanceof PointerOperand } - Variable getArray() { + ArrayLikeAccess getArray() { result = this.(DerivedArrayPointer).getArray() or result = this.(PointerOperand).getArray() } - int getArraySize() { - result = this.(DerivedArrayPointer).getArraySize() or - result = this.(PointerOperand).getArraySize() - } - int getIndex() { result = this.(DerivedArrayPointer).getIndex() or result = this.(PointerOperand).getIndex() } @@ -149,14 +244,16 @@ class DerivedArrayPointerOrPointerOperand extends Variable { } } -query predicate problems(Expr arrayPointerCreation, string message, Variable array, string arrayName) { +query predicate problems(Expr arrayPointerCreation, string message, Element array, string arrayName) { not isExcluded(arrayPointerCreation, getQuery()) and exists( DerivedArrayPointerOrPointerOperand derivedArrayPointerOrPointerOperand, int index, - int arraySize, int difference, string denomination + ArrayLikeAccess arrayAccess, int arraySize, int difference, string denomination | - array = derivedArrayPointerOrPointerOperand.getArray() and - arraySize = derivedArrayPointerOrPointerOperand.getArraySize() and + arrayAccess = derivedArrayPointerOrPointerOperand.getArray() and + array = arrayAccess.getElement() and + arrayName = arrayAccess.getName() and + arraySize = arrayAccess.getSize() and index = derivedArrayPointerOrPointerOperand.getIndex() and arrayPointerCreation = derivedArrayPointerOrPointerOperand.getSource() and difference = index - arraySize and @@ -173,7 +270,6 @@ query predicate problems(Expr arrayPointerCreation, string message, Variable arr ) and message = "Array pointer " + derivedArrayPointerOrPointerOperand.getName() + " points " + - (index - arraySize).toString() + " " + denomination + " passed the end of $@." - ) and - arrayName = array.getName() -} + difference.toString() + " " + denomination + " past the end of $@." + ) +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointers/InvalidatedEnvStringPointers.qll b/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointers/InvalidatedEnvStringPointers.qll index 3949ff50a8..0f4a98cf6f 100644 --- a/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointers/InvalidatedEnvStringPointers.qll +++ b/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointers/InvalidatedEnvStringPointers.qll @@ -45,6 +45,12 @@ predicate incompatibleFunctions(GetenvFunction f1, GetenvFunction f2) { or f1.getName() = ["setlocale", "localeconv"] and f2.getName() = ["setlocale", "localeconv"] + or + f1.getName() = ["asctime", "ctime"] and + f2.getName() = ["asctime", "ctime"] + or + f1.getName() = ["gmtime", "localtime"] and + f2.getName() = ["gmtime", "localtime"] } query predicate problems( diff --git a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected index fa181755e8..438b697775 100644 --- a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected +++ b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected @@ -1,5 +1,9 @@ -| test.cpp:4:13:4:18 | ... + ... | Array pointer p2 points 1 element passed the end of $@. | test.cpp:2:7:2:8 | l1 | l1 | -| test.cpp:5:13:5:18 | ... + ... | Array pointer p3 points 1 element passed the end of $@. | test.cpp:2:7:2:8 | l1 | l1 | -| test.cpp:6:13:6:18 | & ... | Array pointer p4 points 1 element passed the end of $@. | test.cpp:2:7:2:8 | l1 | l1 | -| test.cpp:11:8:11:11 | ... -- | Array pointer p7 points 1 element passed the end of $@. | test.cpp:2:7:2:8 | l1 | l1 | -| test.cpp:12:8:12:9 | p3 | Array pointer p8 points 1 element passed the end of $@. | test.cpp:2:7:2:8 | l1 | l1 | +| test.cpp:4:13:4:18 | ... + ... | Array pointer p2 points 1 element past the end of $@. | test.cpp:2:7:2:8 | l1 | l1 | +| test.cpp:5:13:5:18 | ... + ... | Array pointer p3 points 1 element past the end of $@. | test.cpp:2:7:2:8 | l1 | l1 | +| test.cpp:6:13:6:18 | & ... | Array pointer p4 points 1 element past the end of $@. | test.cpp:2:7:2:8 | l1 | l1 | +| test.cpp:11:8:11:11 | ... -- | Array pointer p7 points 1 element past the end of $@. | test.cpp:2:7:2:8 | l1 | l1 | +| test.cpp:12:8:12:9 | p3 | Array pointer p8 points 1 element past the end of $@. | test.cpp:2:7:2:8 | l1 | l1 | +| test.cpp:25:15:25:21 | & ... | Array pointer p14 points 1 element past the end of $@. | test.cpp:2:7:2:8 | l1 | l1 | +| test.cpp:30:15:30:21 | & ... | Array pointer p17 points 1 element past the end of $@. | test.cpp:28:24:28:42 | (unsigned char *)... | cast to btye pointer (unsigned char *)... | +| test.cpp:35:15:35:21 | & ... | Array pointer p20 points 1 element past the end of $@. | test.cpp:33:24:33:43 | (unsigned char *)... | cast to btye pointer (unsigned char *)... | +| test.cpp:43:15:43:23 | & ... | Array pointer p23 points 96 elements past the end of $@. | test.cpp:28:24:28:42 | (unsigned char *)... | cast to btye pointer (unsigned char *)... | diff --git a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp index c1032ee735..f81026870d 100644 --- a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp +++ b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp @@ -17,4 +17,28 @@ void f1() { 3 + p1; // COMPLIANT - points to an element on beyond the end of the array int *p11 = &l1[3]; // COMPLIANT - points to an element on beyond the end of the array + + // Casting to a pointer to a type of the same size doesn't invalidate the + // analysis + unsigned int *p12 = (unsigned int *)l1; + void *p13 = &p12[3]; // COMPLIANT + void *p14 = &p12[4]; // NON_COMPLIANT + + // Casting to a char* is effectively a new array of length sizeof(T) + unsigned char *p15 = (unsigned char *)l1; + void *p16 = &p15[4]; // COMPLIANT + void *p17 = &p15[5]; // NON_COMPLIANT + + long l2[3]; + unsigned char *p18 = (unsigned char *)&l2; + void *p19 = &p18[8]; // COMPLIANT + void *p20 = &p18[9]; // NON_COMPLIANT + + // Casting to a pointer to a differently sized type that isn't char + // invalidates analysis + int l3[3]; + long *p21 = (long*)&l1; + void *p22 = &p21[0]; // COMPLIANT + // Not compliant, but we shouldn't detect it, but we do for the wrong reason: + void *p23 = &p21[100]; // NON_COMPLIANT[FALSE_NEGATIVE][FALSE_POSITIVE] } \ No newline at end of file diff --git a/cpp/common/test/rules/invalidatedenvstringpointers/InvalidatedEnvStringPointers.expected b/cpp/common/test/rules/invalidatedenvstringpointers/InvalidatedEnvStringPointers.expected index 9a39d3a88d..36c66a94fe 100644 --- a/cpp/common/test/rules/invalidatedenvstringpointers/InvalidatedEnvStringPointers.expected +++ b/cpp/common/test/rules/invalidatedenvstringpointers/InvalidatedEnvStringPointers.expected @@ -4,3 +4,8 @@ | test.cpp:165:14:165:26 | tmpvar_global | This pointer was returned by a $@ and may have been overwritten by the susequent $@. | test.cpp:157:19:157:24 | call to getenv | call to getenv | test.cpp:161:20:161:25 | call to getenv | call to getenv | | test.cpp:188:18:188:18 | r | This pointer was returned by a $@ and may have been overwritten by the susequent $@. | test.cpp:185:7:185:15 | call to setlocale | call to setlocale | test.cpp:187:8:187:17 | call to localeconv | call to localeconv | | test.cpp:208:10:208:15 | tmpvar | This pointer was returned by a $@ and may have been overwritten by the susequent $@. | test.cpp:202:12:202:17 | call to getenv | call to getenv | test.cpp:206:3:206:8 | call to f11fun | call to f11fun | +| test.cpp:216:16:216:17 | r1 | This pointer was returned by a $@ and may have been overwritten by the susequent $@. | test.cpp:214:14:214:18 | call to ctime | call to ctime | test.cpp:215:3:215:9 | call to asctime | call to asctime | +| test.cpp:226:16:226:17 | r1 | This pointer was returned by a $@ and may have been overwritten by the susequent $@. | test.cpp:222:14:222:18 | call to ctime | call to ctime | test.cpp:225:14:225:20 | call to asctime | call to asctime | +| test.cpp:231:16:231:17 | r2 | This pointer was returned by a $@ and may have been overwritten by the susequent $@. | test.cpp:225:14:225:20 | call to asctime | call to asctime | test.cpp:229:8:229:12 | call to ctime | call to ctime | +| test.cpp:240:16:240:17 | r1 | This pointer was returned by a $@ and may have been overwritten by the susequent $@. | test.cpp:236:19:236:27 | call to localtime | call to localtime | test.cpp:239:19:239:24 | call to gmtime | call to gmtime | +| test.cpp:245:16:245:17 | r2 | This pointer was returned by a $@ and may have been overwritten by the susequent $@. | test.cpp:239:19:239:24 | call to gmtime | call to gmtime | test.cpp:243:8:243:16 | call to localtime | call to localtime | diff --git a/cpp/common/test/rules/invalidatedenvstringpointers/test.cpp b/cpp/common/test/rules/invalidatedenvstringpointers/test.cpp index 74e3d1b8f5..167d770ef6 100644 --- a/cpp/common/test/rules/invalidatedenvstringpointers/test.cpp +++ b/cpp/common/test/rules/invalidatedenvstringpointers/test.cpp @@ -207,3 +207,40 @@ void f11(void) { printf(tmpvar); // NON_COMPLIANT } + +void f12(void) { + time_t rawtime; + time(&rawtime); + char* r1 = ctime(&rawtime); + asctime(localtime(&rawtime)); + printf("%s", r1); // NON_COMPLIANT +} + +void f13(void) { + time_t rawtime; + time(&rawtime); + char* r1 = ctime(&rawtime); + printf("%s", r1); // COMPLIANT + + char* r2 = asctime(localtime(&rawtime)); + printf("%s", r1); // NON_COMPLIANT + printf("%s", r2); // COMPLIANT + + r1 = ctime(&rawtime); + printf("%s", r1); // COMPLIANT + printf("%s", r2); // NON_COMPLIANT +} + +void f14(void) { + time_t rawtime; + struct tm *r1 = localtime(&rawtime); + printf("%d", r1->tm_year); // COMPLIANT + + struct tm *r2 = gmtime(&rawtime); + printf("%s", r1->tm_year); // NON_COMPLIANT + printf("%s", r2->tm_year); // COMPLIANT + + r1 = localtime(&rawtime); + printf("%s", r1->tm_year); // COMPLIANT + printf("%s", r2->tm_year); // NON_COMPLIANT +} \ No newline at end of file From 6316375dfcd09132d0f1759571f1da5959a0f1b3 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 12 Jan 2025 22:00:41 +0000 Subject: [PATCH 130/370] ReturnRefOrPointerToAutoVar: Exclude global or member variables This false positive case was introduced when the rule was shared during the creation of RULE-6-8-2, where `Variable` was used instead of `StackVariable`. --- change_notes/2025-01-09-return-reference.md | 2 ++ ...rnReferenceOrPointerToAutomaticLocalVariable.qll | 2 +- .../test.cpp | 13 +++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 change_notes/2025-01-09-return-reference.md diff --git a/change_notes/2025-01-09-return-reference.md b/change_notes/2025-01-09-return-reference.md new file mode 100644 index 0000000000..69480916c7 --- /dev/null +++ b/change_notes/2025-01-09-return-reference.md @@ -0,0 +1,2 @@ + - `M7-5-1`, `RULE-6-8-2` - `FunctionReturnAutomaticVarCondition.ql`, `ReturnReferenceOrPointerToAutomaticLocalVariable.ql`: + - Remove false positives for member and global variables reported under this rule. \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/rules/returnreferenceorpointertoautomaticlocalvariable/ReturnReferenceOrPointerToAutomaticLocalVariable.qll b/cpp/common/src/codingstandards/cpp/rules/returnreferenceorpointertoautomaticlocalvariable/ReturnReferenceOrPointerToAutomaticLocalVariable.qll index cd623f711c..b37a9cd02b 100644 --- a/cpp/common/src/codingstandards/cpp/rules/returnreferenceorpointertoautomaticlocalvariable/ReturnReferenceOrPointerToAutomaticLocalVariable.qll +++ b/cpp/common/src/codingstandards/cpp/rules/returnreferenceorpointertoautomaticlocalvariable/ReturnReferenceOrPointerToAutomaticLocalVariable.qll @@ -13,7 +13,7 @@ abstract class ReturnReferenceOrPointerToAutomaticLocalVariableSharedQuery exten Query getQuery() { result instanceof ReturnReferenceOrPointerToAutomaticLocalVariableSharedQuery } query predicate problems( - ReturnStmt rs, string message, Function f, string f_string, Variable auto, string auto_string + ReturnStmt rs, string message, Function f, string f_string, StackVariable auto, string auto_string ) { exists(VariableAccess va, string returnType | not isExcluded(rs, getQuery()) and diff --git a/cpp/common/test/rules/returnreferenceorpointertoautomaticlocalvariable/test.cpp b/cpp/common/test/rules/returnreferenceorpointertoautomaticlocalvariable/test.cpp index bc4fbf8f1d..d383d7859f 100644 --- a/cpp/common/test/rules/returnreferenceorpointertoautomaticlocalvariable/test.cpp +++ b/cpp/common/test/rules/returnreferenceorpointertoautomaticlocalvariable/test.cpp @@ -32,4 +32,17 @@ void test_templatefunction_return() { int j = 2; int k = 3; t1(j, k); +} + +class C1 { +private: + int x; + +public: + int test() { return x; } // COMPLIANT - ignore member vars +}; + +int x; +int test_global() { + return x; // COMPLIANT - ignore global vars } \ No newline at end of file From 99a310642c211ff13204cbbe624ea999b6d545a0 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 12 Jan 2025 22:08:19 +0000 Subject: [PATCH 131/370] Contracts: Add MISRA C 2012 tags --- rule_packages/c/Contracts.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rule_packages/c/Contracts.json b/rule_packages/c/Contracts.json index 735e84d9da..40bf3d8b0b 100644 --- a/rule_packages/c/Contracts.json +++ b/rule_packages/c/Contracts.json @@ -38,7 +38,8 @@ "short_name": "CheckMathLibraryFunctionParameters", "shared_implementation_short_name": "UncheckedRangeDomainPoleErrors", "tags": [ - "correctness" + "correctness", + "external/misra/c/2012/third-edition-first-revision" ], "implementation_scope": { "description": "This query identifies possible domain, pole and range errors on a selection of C standard library fuctions from math.h." @@ -61,7 +62,8 @@ "short_name": "FunctionErrorInformationUntested", "shared_implementation_short_name": "FunctionErroneousReturnValueNotTested", "tags": [ - "maintainability" + "maintainability", + "external/misra/c/2012/third-edition-first-revision" ], "implementation_scope": { "description": "This query enforces checking on some C standard library functions that may return error codes." From 82440695528fce9e12846cb92298572cd7aa1fdd Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 12 Jan 2025 22:15:43 +0000 Subject: [PATCH 132/370] Regenerate package files --- c/misra/src/rules/DIR-4-11/CheckMathLibraryFunctionParameters.ql | 1 + c/misra/src/rules/DIR-4-7/FunctionErrorInformationUntested.ql | 1 + 2 files changed, 2 insertions(+) diff --git a/c/misra/src/rules/DIR-4-11/CheckMathLibraryFunctionParameters.ql b/c/misra/src/rules/DIR-4-11/CheckMathLibraryFunctionParameters.ql index 6810784a0e..4011b210f8 100644 --- a/c/misra/src/rules/DIR-4-11/CheckMathLibraryFunctionParameters.ql +++ b/c/misra/src/rules/DIR-4-11/CheckMathLibraryFunctionParameters.ql @@ -8,6 +8,7 @@ * @problem.severity error * @tags external/misra/id/dir-4-11 * correctness + * external/misra/c/2012/third-edition-first-revision * external/misra/obligation/required */ diff --git a/c/misra/src/rules/DIR-4-7/FunctionErrorInformationUntested.ql b/c/misra/src/rules/DIR-4-7/FunctionErrorInformationUntested.ql index 63236d422d..0c0a3d7b1a 100644 --- a/c/misra/src/rules/DIR-4-7/FunctionErrorInformationUntested.ql +++ b/c/misra/src/rules/DIR-4-7/FunctionErrorInformationUntested.ql @@ -12,6 +12,7 @@ * @problem.severity recommendation * @tags external/misra/id/dir-4-7 * maintainability + * external/misra/c/2012/third-edition-first-revision * external/misra/obligation/required */ From 37ac088223e3cab5e000fb36103d4fa70056e84a Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 12 Jan 2025 23:03:53 +0000 Subject: [PATCH 133/370] EssentialType: Merge binary operation implementations EssentialBinaryArithmeticOperation and EssentialBinaryBitwiseOperation only differ in their handling of + and - operations, so combine the two implementations to reduce duplication. In addition, change the characteristic predicate to an allow list. This ensures we only capture the intended binary operations, and exclude any others. --- .../c/misra/EssentialTypes.qll | 71 ++++++------------- 1 file changed, 21 insertions(+), 50 deletions(-) diff --git a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll index 4dbe8dbb34..57250d42c5 100644 --- a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll +++ b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll @@ -286,11 +286,26 @@ class EssentialConditionalExpr extends EssentialExpr, ConditionalExpr { } } -class EssentialBinaryArithmeticExpr extends EssentialExpr, BinaryArithmeticOperation { - EssentialBinaryArithmeticExpr() { - // GNU C extension has min/max which we can ignore - not this instanceof MinExpr and - not this instanceof MaxExpr +/** + * A binary operation subject to usual conversions, with essential type behaviour as specified by D.7.9. + */ +class EssentialBinaryOperationSubjectToUsualConversions extends EssentialExpr, BinaryOperation { + EssentialBinaryOperationSubjectToUsualConversions() { + this instanceof MulExpr + or + this instanceof DivExpr + or + this instanceof RemExpr + or + this instanceof AddExpr + or + this instanceof SubExpr + or + this instanceof BitwiseAndExpr + or + this instanceof BitwiseOrExpr + or + this instanceof BitwiseXorExpr } override Type getEssentialType() { @@ -353,51 +368,7 @@ class EssentialBinaryArithmeticExpr extends EssentialExpr, BinaryArithmeticOpera } } -class EssentialBinaryBitwiseExpr extends EssentialExpr, BinaryBitwiseOperation { - EssentialBinaryBitwiseExpr() { - not this instanceof LShiftExpr and - not this instanceof RShiftExpr - } - - override Type getEssentialType() { - exists( - Type leftEssentialType, Type rightEssentialType, - EssentialTypeCategory leftEssentialTypeCategory, - EssentialTypeCategory rightEssentialTypeCategory - | - leftEssentialType = getEssentialType(getLeftOperand()) and - rightEssentialType = getEssentialType(getRightOperand()) and - leftEssentialTypeCategory = getEssentialTypeCategory(leftEssentialType) and - rightEssentialTypeCategory = getEssentialTypeCategory(rightEssentialType) - | - if - leftEssentialTypeCategory = EssentiallySignedType() and - rightEssentialTypeCategory = EssentiallySignedType() - then - if exists(getValue()) - then result = stlr(this) - else ( - if leftEssentialType.getSize() > rightEssentialType.getSize() - then result = leftEssentialType - else result = rightEssentialType - ) - else - if - leftEssentialTypeCategory = EssentiallyUnsignedType() and - rightEssentialTypeCategory = EssentiallyUnsignedType() - then - if exists(getValue()) - then result = utlr(this) - else ( - if leftEssentialType.getSize() > rightEssentialType.getSize() - then result = leftEssentialType - else result = rightEssentialType - ) - else result = this.getStandardType() - ) - } -} - +// } /** * A named Enum type, as per D.5. */ From 9dc3f1894b3b853c7c8459cc25715698d06eaff2 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 12 Jan 2025 23:19:27 +0000 Subject: [PATCH 134/370] EssentialType: extract Add/Sub expressions Extract out add/sub expressions special behaviour to improve clarity. This commit also simplifies the add case by avoiding referring to left/right explicitly. --- .../c/misra/EssentialTypes.qll | 66 ++++++++++++------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll index 57250d42c5..2852f5d842 100644 --- a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll +++ b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll @@ -342,28 +342,50 @@ class EssentialBinaryOperationSubjectToUsualConversions extends EssentialExpr, B then result = leftEssentialType else result = rightEssentialType ) - else - if - this instanceof AddExpr and - ( - leftEssentialTypeCategory = EssentiallyCharacterType() - or - rightEssentialTypeCategory = EssentiallyCharacterType() - ) and - ( - leftEssentialTypeCategory = - [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] - or - rightEssentialTypeCategory = - [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] - ) - or - this instanceof SubExpr and - leftEssentialTypeCategory = EssentiallyCharacterType() and - rightEssentialTypeCategory = - [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] - then result instanceof PlainCharType - else result = this.getStandardType() + else result = this.getStandardType() + ) + } +} + +/** + * An add expression, with essential type behaviour as specified by D.7.9. + */ +class EssentialAddExpr extends EssentialBinaryOperationSubjectToUsualConversions, AddExpr { + override Type getEssentialType() { + exists( + EssentialTypeCategory operandTypeCategory, EssentialTypeCategory otherOperandTypeCategory + | + operandTypeCategory = getEssentialTypeCategory(getEssentialType(getAnOperand())) and + otherOperandTypeCategory = getEssentialTypeCategory(getEssentialType(getAnOperand())) + | + if + operandTypeCategory = EssentiallyCharacterType() and + otherOperandTypeCategory = + [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] + then result instanceof PlainCharType + else result = super.getEssentialType() + ) + } +} + +/** + * A sub expression, with essential type behaviour as specified by D.7.9. + */ +class EssentialSubExpr extends EssentialBinaryOperationSubjectToUsualConversions, SubExpr { + override Type getEssentialType() { + exists( + EssentialTypeCategory leftEssentialTypeCategory, + EssentialTypeCategory rightEssentialTypeCategory + | + leftEssentialTypeCategory = getEssentialTypeCategory(getEssentialType(getLeftOperand())) and + rightEssentialTypeCategory = getEssentialTypeCategory(getEssentialType(getRightOperand())) + | + if + leftEssentialTypeCategory = EssentiallyCharacterType() and + rightEssentialTypeCategory = + [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] + then result instanceof PlainCharType + else result = super.getEssentialType() ) } } From 29420e93e0f286a6cafe06a6ef44989c2e517676 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 12 Jan 2025 23:33:13 +0000 Subject: [PATCH 135/370] EssentialType: Combine binary cases Reduce repitition through combining cases. --- .../c/misra/EssentialTypes.qll | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll index 2852f5d842..633660b952 100644 --- a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll +++ b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll @@ -320,29 +320,21 @@ class EssentialBinaryOperationSubjectToUsualConversions extends EssentialExpr, B rightEssentialTypeCategory = getEssentialTypeCategory(rightEssentialType) | if - leftEssentialTypeCategory = EssentiallySignedType() and - rightEssentialTypeCategory = EssentiallySignedType() + leftEssentialTypeCategory = rightEssentialTypeCategory and + leftEssentialTypeCategory = + [EssentiallyUnsignedType(), EssentiallySignedType().(TEssentialTypeCategory)] then if exists(getValue()) - then result = stlr(this) - else ( + then ( + leftEssentialTypeCategory = EssentiallySignedType() and result = stlr(this) + or + leftEssentialTypeCategory = EssentiallyUnsignedType() and result = utlr(this) + ) else ( if leftEssentialType.getSize() > rightEssentialType.getSize() then result = leftEssentialType else result = rightEssentialType ) - else - if - leftEssentialTypeCategory = EssentiallyUnsignedType() and - rightEssentialTypeCategory = EssentiallyUnsignedType() - then - if exists(getValue()) - then result = utlr(this) - else ( - if leftEssentialType.getSize() > rightEssentialType.getSize() - then result = leftEssentialType - else result = rightEssentialType - ) - else result = this.getStandardType() + else result = this.getStandardType() ) } } From 62da9c88ba9c6a5acb88f79a94405947f3505a4c Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 12 Jan 2025 23:45:14 +0000 Subject: [PATCH 136/370] EssentialType: Simplify (Signed or Unsigned) --- .../c/misra/EssentialTypes.qll | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll index 633660b952..555d3d2b2d 100644 --- a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll +++ b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll @@ -31,17 +31,19 @@ class EssentialTypeCategory extends TEssentialTypeCategory { } } +class EssentiallySignedOrUnsignedType extends EssentialTypeCategory { + EssentiallySignedOrUnsignedType() { + this = EssentiallySignedType() or this = EssentiallyUnsignedType() + } +} + /** * An expression in the program that evaluates to a compile time constant signed or unsigned integer. */ private class ConstantIntegerExpr extends Expr { pragma[noinline] ConstantIntegerExpr() { - getEssentialTypeCategory(this.getType()) = - [ - EssentiallyUnsignedType().(EssentialTypeCategory), - EssentiallySignedType().(EssentialTypeCategory) - ] and + getEssentialTypeCategory(this.getType()) instanceof EssentiallySignedOrUnsignedType and exists(this.getValue().toFloat()) and not this instanceof Conversion } @@ -235,9 +237,7 @@ class EssentialUnaryPlusExpr extends EssentialExpr, UnaryPlusExpr { operandEssentialType = getEssentialType(getOperand()) and operandEssentialTypeCategory = getEssentialTypeCategory(operandEssentialType) | - if - operandEssentialTypeCategory = - [EssentiallyUnsignedType().(TEssentialTypeCategory), EssentiallySignedType()] + if operandEssentialTypeCategory instanceof EssentiallySignedOrUnsignedType then result = operandEssentialType else result = getStandardType() ) @@ -321,8 +321,7 @@ class EssentialBinaryOperationSubjectToUsualConversions extends EssentialExpr, B | if leftEssentialTypeCategory = rightEssentialTypeCategory and - leftEssentialTypeCategory = - [EssentiallyUnsignedType(), EssentiallySignedType().(TEssentialTypeCategory)] + leftEssentialTypeCategory instanceof EssentiallySignedOrUnsignedType then if exists(getValue()) then ( @@ -352,8 +351,7 @@ class EssentialAddExpr extends EssentialBinaryOperationSubjectToUsualConversions | if operandTypeCategory = EssentiallyCharacterType() and - otherOperandTypeCategory = - [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] + otherOperandTypeCategory instanceof EssentiallySignedOrUnsignedType then result instanceof PlainCharType else result = super.getEssentialType() ) @@ -374,8 +372,7 @@ class EssentialSubExpr extends EssentialBinaryOperationSubjectToUsualConversions | if leftEssentialTypeCategory = EssentiallyCharacterType() and - rightEssentialTypeCategory = - [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] + rightEssentialTypeCategory instanceof EssentiallySignedOrUnsignedType then result instanceof PlainCharType else result = super.getEssentialType() ) From cd8ea6767da83d0783502e826a4c7be6b86bdb05 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 12 Jan 2025 23:48:01 +0000 Subject: [PATCH 137/370] EssentialType: Reduce duplication in conditional calc Avoid repeating code for both the signed and unsigned cases. --- .../src/codingstandards/c/misra/EssentialTypes.qll | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll index 555d3d2b2d..97a9604f58 100644 --- a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll +++ b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll @@ -267,21 +267,13 @@ class EssentialConditionalExpr extends EssentialExpr, ConditionalExpr { then result = thenEssentialType else if - getEssentialTypeCategory(thenEssentialType) = EssentiallySignedType() and - getEssentialTypeCategory(elseEssentialType) = EssentiallySignedType() + getEssentialTypeCategory(thenEssentialType) = getEssentialTypeCategory(elseEssentialType) and + getEssentialTypeCategory(thenEssentialType) instanceof EssentiallySignedOrUnsignedType then if thenEssentialType.getSize() > elseEssentialType.getSize() then result = thenEssentialType else result = elseEssentialType - else - if - getEssentialTypeCategory(thenEssentialType) = EssentiallyUnsignedType() and - getEssentialTypeCategory(elseEssentialType) = EssentiallyUnsignedType() - then - if thenEssentialType.getSize() > elseEssentialType.getSize() - then result = thenEssentialType - else result = elseEssentialType - else result = this.getStandardType() + else result = this.getStandardType() ) } } From 7a465dd340948eb3a6a5a0e6f5b14c068bc601a7 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 12 Jan 2025 23:52:35 +0000 Subject: [PATCH 138/370] EssentialType: Add maxRank predicate --- .../c/misra/EssentialTypes.qll | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll index 97a9604f58..0a4e64e98d 100644 --- a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll +++ b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll @@ -257,6 +257,13 @@ class EssentialUnaryMinusExpr extends EssentialExpr, UnaryMinusExpr { } } +bindingset[essentialTypeA, essentialTypeB] +private Type maxRankType(Type essentialTypeA, Type essentialTypeB) { + if essentialTypeA.getSize() > essentialTypeB.getSize() + then result = essentialTypeA + else result = essentialTypeB +} + class EssentialConditionalExpr extends EssentialExpr, ConditionalExpr { override Type getEssentialType() { exists(Type thenEssentialType, Type elseEssentialType | @@ -269,10 +276,7 @@ class EssentialConditionalExpr extends EssentialExpr, ConditionalExpr { if getEssentialTypeCategory(thenEssentialType) = getEssentialTypeCategory(elseEssentialType) and getEssentialTypeCategory(thenEssentialType) instanceof EssentiallySignedOrUnsignedType - then - if thenEssentialType.getSize() > elseEssentialType.getSize() - then result = thenEssentialType - else result = elseEssentialType + then result = maxRankType(thenEssentialType, elseEssentialType) else result = this.getStandardType() ) } @@ -316,15 +320,11 @@ class EssentialBinaryOperationSubjectToUsualConversions extends EssentialExpr, B leftEssentialTypeCategory instanceof EssentiallySignedOrUnsignedType then if exists(getValue()) - then ( + then leftEssentialTypeCategory = EssentiallySignedType() and result = stlr(this) or leftEssentialTypeCategory = EssentiallyUnsignedType() and result = utlr(this) - ) else ( - if leftEssentialType.getSize() > rightEssentialType.getSize() - then result = leftEssentialType - else result = rightEssentialType - ) + else result = maxRankType(leftEssentialType, rightEssentialType) else result = this.getStandardType() ) } From 3fd82fd7bf2cb2a61f2c1c476d53806f2e932834 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 13 Jan 2025 00:06:10 +0000 Subject: [PATCH 139/370] EssentialType: Fix test comments --- c/misra/test/c/misra/test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/c/misra/test/c/misra/test.c b/c/misra/test/c/misra/test.c index e271a67e30..7bcb5d7bad 100644 --- a/c/misra/test/c/misra/test.c +++ b/c/misra/test/c/misra/test.c @@ -139,8 +139,8 @@ void testBitwise() { s32 ^ s16; // Essentially signed, int s16 ^ s32; // Essentially signed, int - u32 & s32; // Essentially signed, int - s32 & u32; // Essentially signed, int + u32 & s32; // Essentially unsigned, int + s32 & u32; // Essentially unsigned, int u8 & s32; // Essentially signed, int s32 & u8; // Essentially signed, int u8 & s8; // Essentially signed, int From 8a070839bb679f5eb7ed57638cfb3ed4ab662485 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 13 Jan 2025 00:11:41 +0000 Subject: [PATCH 140/370] Avoid formatting colisions --- c/misra/test/c/misra/test.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/c/misra/test/c/misra/test.c b/c/misra/test/c/misra/test.c index 7bcb5d7bad..36a3eb0b10 100644 --- a/c/misra/test/c/misra/test.c +++ b/c/misra/test/c/misra/test.c @@ -82,8 +82,8 @@ void testControlChar() { } #include - -void testBitwise() { +// clang-format off +void testBitwise() { // Clang format disabled to avoid confusion with variable declarations uint8_t u8 = 0; uint16_t u16 = 0; uint32_t u32 = 0; @@ -160,7 +160,7 @@ void testBitwise() { u8 ^ s8; // Essentially signed, int s8 ^ u8; // Essentially signed, int } - +// clang-format on void testShifts() { int32_t s32 = 1; From 2c2c3fbac9f7efeca6199d9ee626ccc67092e863 Mon Sep 17 00:00:00 2001 From: knewbury01 Date: Tue, 14 Jan 2025 14:59:01 +0000 Subject: [PATCH 141/370] Bump version to 2.41.0-dev --- c/cert/src/qlpack.yml | 2 +- c/cert/test/qlpack.yml | 2 +- c/common/src/qlpack.yml | 2 +- c/common/test/qlpack.yml | 2 +- c/misra/src/qlpack.yml | 2 +- c/misra/test/qlpack.yml | 2 +- cpp/autosar/src/qlpack.yml | 2 +- cpp/autosar/test/qlpack.yml | 2 +- cpp/cert/src/qlpack.yml | 2 +- cpp/cert/test/qlpack.yml | 2 +- cpp/common/src/qlpack.yml | 2 +- cpp/common/test/qlpack.yml | 2 +- cpp/misra/src/qlpack.yml | 2 +- cpp/misra/test/qlpack.yml | 2 +- cpp/report/src/qlpack.yml | 2 +- docs/user_manual.md | 12 ++++++------ 16 files changed, 21 insertions(+), 21 deletions(-) diff --git a/c/cert/src/qlpack.yml b/c/cert/src/qlpack.yml index 2778e44435..4945abe49c 100644 --- a/c/cert/src/qlpack.yml +++ b/c/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards -version: 2.40.0-dev +version: 2.41.0-dev description: CERT C 2016 suites: codeql-suites license: MIT diff --git a/c/cert/test/qlpack.yml b/c/cert/test/qlpack.yml index 461ebe9677..af5e71d2a1 100644 --- a/c/cert/test/qlpack.yml +++ b/c/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards-tests -version: 2.40.0-dev +version: 2.41.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/common/src/qlpack.yml b/c/common/src/qlpack.yml index f39f3cb1c4..9545a88178 100644 --- a/c/common/src/qlpack.yml +++ b/c/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards -version: 2.40.0-dev +version: 2.41.0-dev license: MIT dependencies: codeql/common-cpp-coding-standards: '*' diff --git a/c/common/test/qlpack.yml b/c/common/test/qlpack.yml index d417a17df2..febda7a63b 100644 --- a/c/common/test/qlpack.yml +++ b/c/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards-tests -version: 2.40.0-dev +version: 2.41.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/misra/src/qlpack.yml b/c/misra/src/qlpack.yml index 9aceed1a49..758c059c01 100644 --- a/c/misra/src/qlpack.yml +++ b/c/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards -version: 2.40.0-dev +version: 2.41.0-dev description: MISRA C 2012 suites: codeql-suites license: MIT diff --git a/c/misra/test/qlpack.yml b/c/misra/test/qlpack.yml index d53bc95f28..d367e8d06d 100644 --- a/c/misra/test/qlpack.yml +++ b/c/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards-tests -version: 2.40.0-dev +version: 2.41.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/autosar/src/qlpack.yml b/cpp/autosar/src/qlpack.yml index f44ad54c74..565cfc12db 100644 --- a/cpp/autosar/src/qlpack.yml +++ b/cpp/autosar/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards -version: 2.40.0-dev +version: 2.41.0-dev description: AUTOSAR C++14 Guidelines R22-11, R21-11, R20-11, R19-11 and R19-03 suites: codeql-suites license: MIT diff --git a/cpp/autosar/test/qlpack.yml b/cpp/autosar/test/qlpack.yml index 178d8cc314..66755fe907 100644 --- a/cpp/autosar/test/qlpack.yml +++ b/cpp/autosar/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards-tests -version: 2.40.0-dev +version: 2.41.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/cert/src/qlpack.yml b/cpp/cert/src/qlpack.yml index 735dd9f5b4..cc981411c2 100644 --- a/cpp/cert/src/qlpack.yml +++ b/cpp/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards -version: 2.40.0-dev +version: 2.41.0-dev description: CERT C++ 2016 suites: codeql-suites license: MIT diff --git a/cpp/cert/test/qlpack.yml b/cpp/cert/test/qlpack.yml index 3a6d02e7d4..af6e4f8659 100644 --- a/cpp/cert/test/qlpack.yml +++ b/cpp/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards-tests -version: 2.40.0-dev +version: 2.41.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/common/src/qlpack.yml b/cpp/common/src/qlpack.yml index 1ae6dfd997..4d0aeb01f1 100644 --- a/cpp/common/src/qlpack.yml +++ b/cpp/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards -version: 2.40.0-dev +version: 2.41.0-dev license: MIT dependencies: codeql/cpp-all: 1.4.2 diff --git a/cpp/common/test/qlpack.yml b/cpp/common/test/qlpack.yml index 90236b203e..a6d2ae30eb 100644 --- a/cpp/common/test/qlpack.yml +++ b/cpp/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards-tests -version: 2.40.0-dev +version: 2.41.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/misra/src/qlpack.yml b/cpp/misra/src/qlpack.yml index 96fc96ce24..a6ac09f1b1 100644 --- a/cpp/misra/src/qlpack.yml +++ b/cpp/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards -version: 2.40.0-dev +version: 2.41.0-dev description: MISRA C++ 2023 default-suite: codeql-suites/misra-cpp-default.qls license: MIT diff --git a/cpp/misra/test/qlpack.yml b/cpp/misra/test/qlpack.yml index 207facda4e..0265144f4f 100644 --- a/cpp/misra/test/qlpack.yml +++ b/cpp/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards-tests -version: 2.40.0-dev +version: 2.41.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/report/src/qlpack.yml b/cpp/report/src/qlpack.yml index e569153ae8..d1c854206c 100644 --- a/cpp/report/src/qlpack.yml +++ b/cpp/report/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/report-cpp-coding-standards -version: 2.40.0-dev +version: 2.41.0-dev license: MIT dependencies: codeql/cpp-all: 1.4.2 diff --git a/docs/user_manual.md b/docs/user_manual.md index 952a9a3c99..d076759571 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -33,14 +33,14 @@ ## Release information -This user manual documents release `2.40.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). +This user manual documents release `2.41.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). The release page documents the release notes and contains the following artifacts part of the release: - `coding-standards-codeql-packs-2.37.0-dev.zip`: CodeQL packs that can be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `code-scanning-cpp-query-pack-2.40.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `supported_rules_list_2.40.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. -- `supported_rules_list_2.40.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. -- `user_manual_2.40.0-dev.md`: This user manual. +- `code-scanning-cpp-query-pack-2.41.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. +- `supported_rules_list_2.41.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. +- `supported_rules_list_2.41.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. +- `user_manual_2.41.0-dev.md`: This user manual. - `Source Code (zip)`: A zip archive containing the contents of https://github.com/github/codeql-coding-standards - `Source Code (tar.gz)`: A GZip compressed tar archive containing the contents of https://github.com/github/codeql-coding-standards - `checksums.txt`: A text file containing sha256 checksums for the aforementioned artifacts. @@ -573,7 +573,7 @@ This section describes known failure modes for "CodeQL Coding Standards" and des | | Out of space | Less output. Some files may be only be partially analyzed, or not analyzed at all. | Error reported on the command line. | Increase space. If it remains an issue report space consumption issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False positives | More output. Results are reported which are not violations of the guidelines. | All reported results must be reviewed. | Report false positive issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False negatives | Less output. Violations of the guidelines are not reported. | Other validation and verification processes during software development should be used to complement the analysis performed by CodeQL Coding Standards. | Report false negative issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.40.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | +| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.41.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | | | Incorrect deviation record specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation records with a reason. Ensure that all deviation records are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Incorrect deviation permit specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation permits with a reason. Ensure that all deviation permits are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Unapproved use of a deviation record | Less output. Results for guideline violations are not reported. | Validate that the deviation record use is approved by verifying the approved-by attribute of the deviation record specification. | Ensure that each raised deviation record is approved by an independent approver through an auditable process. | From a75dc0af9db6f80aaff1ca18af5839912c9edc8c Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 15 Jan 2025 20:01:39 -0800 Subject: [PATCH 142/370] Address feedback --- .../rules/RULE-2-8/UnusedObjectDefinition.ql | 2 +- .../RULE-2-8/UnusedObjectDefinitionInMacro.ql | 24 ---- .../UnusedObjectDefinitionInMacroStrict.ql | 27 ---- .../RULE-2-8/UnusedObjectDefinitionStrict.ql | 2 +- .../RULE-2-8/UnusedObjectDefinition.expected | 22 +-- .../UnusedObjectDefinitionInMacro.expected | 2 - .../UnusedObjectDefinitionInMacro.qlref | 1 - ...usedObjectDefinitionInMacroStrict.expected | 2 - .../UnusedObjectDefinitionInMacroStrict.qlref | 1 - .../UnusedObjectDefinitionStrict.expected | 6 +- c/misra/test/rules/RULE-2-8/test.c | 2 + .../DeduplicateMacroResults.qll | 55 ++++++-- .../cpp/deadcode/UnusedObjects.qll | 129 ++---------------- .../cpp/exclusions/c/DeadCode2.qll | 36 +---- .../DeduplicateMacroResults.expected | 1 + .../alertreporting/DeduplicateMacroResults.ql | 7 +- .../deduplicatemacroresults.cpp | 2 +- docs/development_handbook.md | 1 + docs/user_manual.md | 3 +- rule_packages/c/DeadCode2.json | 27 ---- 20 files changed, 84 insertions(+), 268 deletions(-) delete mode 100644 c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacro.ql delete mode 100644 c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.ql delete mode 100644 c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.expected delete mode 100644 c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.qlref delete mode 100644 c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.expected delete mode 100644 c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.qlref diff --git a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinition.ql b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinition.ql index 420733d4ac..2230a74592 100644 --- a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinition.ql +++ b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinition.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.deadcode.UnusedObjects -from ReportDeadObjectAtDefinition report +from ReportDeadObject report where not isExcluded(report.getPrimaryElement(), DeadCode2Package::unusedObjectDefinitionQuery()) and not report.hasAttrUnused() diff --git a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacro.ql b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacro.ql deleted file mode 100644 index d5c339c157..0000000000 --- a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacro.ql +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @id c/misra/unused-object-definition-in-macro - * @name RULE-2-8: Project macros should not include unused object definitions - * @description Macros should not have unused object definitions. - * @kind problem - * @precision very-high - * @problem.severity recommendation - * @tags external/misra/id/rule-2-8 - * maintainability - * performance - * external/misra/c/2012/amendment4 - * external/misra/obligation/advisory - */ - -import cpp -import codingstandards.c.misra -import codingstandards.cpp.deadcode.UnusedObjects - -from ReportDeadObjectInMacro report -where - not isExcluded(report.getPrimaryElement(), DeadCode2Package::unusedObjectDefinitionInMacroQuery()) and - not report.hasAttrUnused() -select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocation(), - report.getOptionalPlaceholderMessage() diff --git a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.ql b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.ql deleted file mode 100644 index 7eead60424..0000000000 --- a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.ql +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @id c/misra/unused-object-definition-in-macro-strict - * @name RULE-2-8: Project macros should not include '__attribute__((unused))' object definitions - * @description A strict query which reports all unused object definitions in macros with - * '__attribute__((unused))'. - * @kind problem - * @precision very-high - * @problem.severity recommendation - * @tags external/misra/id/rule-2-8 - * maintainability - * performance - * external/misra/c/2012/amendment4 - * external/misra/c/strict - * external/misra/obligation/advisory - */ - -import cpp -import codingstandards.c.misra -import codingstandards.cpp.deadcode.UnusedObjects - -from ReportDeadObjectInMacro report -where - not isExcluded(report.getPrimaryElement(), - DeadCode2Package::unusedObjectDefinitionInMacroStrictQuery()) and - report.hasAttrUnused() -select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocation(), - report.getOptionalPlaceholderMessage() diff --git a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionStrict.ql b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionStrict.ql index ad92c79481..cc117763ee 100644 --- a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionStrict.ql +++ b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionStrict.ql @@ -18,7 +18,7 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.deadcode.UnusedObjects -from ReportDeadObjectAtDefinition report +from ReportDeadObject report where not isExcluded(report.getPrimaryElement(), DeadCode2Package::unusedObjectDefinitionStrictQuery()) and report.hasAttrUnused() diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected index ce7e198122..731aebb1be 100644 --- a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected +++ b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected @@ -1,10 +1,12 @@ -| test.c:6:5:6:6 | definition of g2 | Unused object definition 'g2'. | test.c:6:5:6:6 | test.c:6:5:6:6 | | -| test.c:9:5:9:6 | definition of g3 | Unused object definition 'g3'. | test.c:9:5:9:6 | test.c:9:5:9:6 | | -| test.c:20:7:20:8 | definition of l2 | Unused object definition 'l2'. | test.c:20:7:20:8 | test.c:20:7:20:8 | | -| test.c:27:7:27:8 | definition of l5 | Unused object definition 'l5'. | test.c:27:7:27:8 | test.c:27:7:27:8 | | -| test.c:37:10:37:11 | definition of g5 | Unused object definition 'g5'. | test.c:37:10:37:11 | test.c:37:10:37:11 | | -| test.c:45:9:45:10 | definition of g6 | Unused object definition 'g6'. | test.c:45:9:45:10 | test.c:45:9:45:10 | | -| test.c:51:5:51:6 | definition of g7 | Unused object definition 'g7'. | test.c:51:5:51:6 | test.c:51:5:51:6 | | -| test.c:64:3:64:18 | ONLY_DEF_VAR(x) | Unused object definition 'l2' from macro '$@'. | test.c:60:1:60:34 | test.c:60:1:60:34 | ONLY_DEF_VAR | -| test.c:117:11:117:13 | definition of g10 | Unused object definition 'g10'. | test.c:117:11:117:13 | test.c:117:11:117:13 | | -| test.c:122:13:122:14 | definition of l2 | Unused object definition 'l2'. | test.c:122:13:122:14 | test.c:122:13:122:14 | | +| test.c:6:5:6:6 | definition of g2 | Unused object 'g2'. | test.c:6:5:6:6 | test.c:6:5:6:6 | (ignored) | +| test.c:9:5:9:6 | definition of g3 | Unused object 'g3'. | test.c:9:5:9:6 | test.c:9:5:9:6 | (ignored) | +| test.c:20:7:20:8 | definition of l2 | Unused object 'l2'. | test.c:20:7:20:8 | test.c:20:7:20:8 | (ignored) | +| test.c:27:7:27:8 | definition of l5 | Unused object 'l5'. | test.c:27:7:27:8 | test.c:27:7:27:8 | (ignored) | +| test.c:37:10:37:11 | definition of g5 | Unused object 'g5'. | test.c:37:10:37:11 | test.c:37:10:37:11 | (ignored) | +| test.c:45:9:45:10 | definition of g6 | Unused object 'g6'. | test.c:45:9:45:10 | test.c:45:9:45:10 | (ignored) | +| test.c:51:5:51:6 | definition of g7 | Unused object 'g7'. | test.c:51:5:51:6 | test.c:51:5:51:6 | (ignored) | +| test.c:64:3:64:18 | ONLY_DEF_VAR(x) | Invocation of macro '$@' defines unused object 'l2'. | test.c:60:1:60:34 | test.c:60:1:60:34 | ONLY_DEF_VAR | +| test.c:68:1:71:5 | #define ALSO_DEF_VAR(x) int x = 0; while (1) ; | Macro 'ALSO_DEF_VAR' defines unused object with an invocation-dependent name, for example, '$@'. | test.c:73:16:73:17 | test.c:73:16:73:17 | l1 | +| test.c:77:1:82:3 | #define DEF_UNUSED_INNER_VAR() { int _v = 0; while (1) ; } | Macro 'DEF_UNUSED_INNER_VAR' defines unused object '_v'. | test.c:77:1:82:3 | test.c:77:1:82:3 | (ignored) | +| test.c:119:11:119:13 | definition of g10 | Unused object 'g10'. | test.c:119:11:119:13 | test.c:119:11:119:13 | (ignored) | +| test.c:124:13:124:14 | definition of l2 | Unused object 'l2'. | test.c:124:13:124:14 | test.c:124:13:124:14 | (ignored) | diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.expected b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.expected deleted file mode 100644 index c25c136789..0000000000 --- a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.expected +++ /dev/null @@ -1,2 +0,0 @@ -| test.c:68:1:71:5 | #define ALSO_DEF_VAR(x) int x = 0; while (1) ; | Macro 'ALSO_DEF_VAR' defines unused object of varied names, for example, '$@'. | test.c:73:16:73:17 | test.c:73:16:73:17 | l1 | -| test.c:77:1:82:3 | #define DEF_UNUSED_INNER_VAR() { int _v = 0; while (1) ; } | Macro 'DEF_UNUSED_INNER_VAR' defines unused object '_v'. | test.c:77:1:82:3 | test.c:77:1:82:3 | (ignored) | diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.qlref b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.qlref deleted file mode 100644 index 057e684fd0..0000000000 --- a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacro.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/RULE-2-8/UnusedObjectDefinitionInMacro.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.expected b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.expected deleted file mode 100644 index 2919c65cb7..0000000000 --- a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.expected +++ /dev/null @@ -1,2 +0,0 @@ -| test.c:94:1:97:5 | #define ALSO_DEF_ATTR_UNUSED_VAR(x) __attribute__((unused)) int x = 0; while (1) ; | Macro 'ALSO_DEF_ATTR_UNUSED_VAR' defines unused object of varied names, for example, '$@'. | test.c:99:28:99:29 | test.c:99:28:99:29 | l1 | -| test.c:104:1:109:3 | #define DEF_ATTR_UNUSED_INNER_VAR() { __attribute__((unused)) int _v = 0; while (1) ; } | Macro 'DEF_ATTR_UNUSED_INNER_VAR' defines unused object '_v'. | test.c:104:1:109:3 | test.c:104:1:109:3 | (ignored) | diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.qlref b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.qlref deleted file mode 100644 index f04653dcb6..0000000000 --- a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/RULE-2-8/UnusedObjectDefinitionInMacroStrict.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.expected b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.expected index 624368ac54..cf3c0b64e1 100644 --- a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.expected +++ b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.expected @@ -1,2 +1,4 @@ -| test.c:87:29:87:30 | definition of g8 | Unused object definition 'g8'. | test.c:87:29:87:30 | test.c:87:29:87:30 | | -| test.c:90:3:90:30 | ONLY_DEF_ATTR_UNUSED_VAR(x) | Unused object definition 'l2' from macro '$@'. | test.c:88:1:88:70 | test.c:88:1:88:70 | ONLY_DEF_ATTR_UNUSED_VAR | +| test.c:87:29:87:30 | definition of g8 | Unused object 'g8'. | test.c:87:29:87:30 | test.c:87:29:87:30 | (ignored) | +| test.c:92:3:92:30 | ONLY_DEF_ATTR_UNUSED_VAR(x) | Invocation of macro '$@' defines unused object 'l2'. | test.c:88:1:88:70 | test.c:88:1:88:70 | ONLY_DEF_ATTR_UNUSED_VAR | +| test.c:96:1:99:5 | #define ALSO_DEF_ATTR_UNUSED_VAR(x) __attribute__((unused)) int x = 0; while (1) ; | Macro 'ALSO_DEF_ATTR_UNUSED_VAR' defines unused object with an invocation-dependent name, for example, '$@'. | test.c:101:28:101:29 | test.c:101:28:101:29 | l1 | +| test.c:106:1:111:3 | #define DEF_ATTR_UNUSED_INNER_VAR() { __attribute__((unused)) int _v = 0; while (1) ; } | Macro 'DEF_ATTR_UNUSED_INNER_VAR' defines unused object '_v'. | test.c:106:1:111:3 | test.c:106:1:111:3 | (ignored) | diff --git a/c/misra/test/rules/RULE-2-8/test.c b/c/misra/test/rules/RULE-2-8/test.c index ef40dfb2a4..e35bf15567 100644 --- a/c/misra/test/rules/RULE-2-8/test.c +++ b/c/misra/test/rules/RULE-2-8/test.c @@ -87,6 +87,8 @@ void f6() { __attribute__((unused)) int g8 = 1; // NON-COMPLIANT #define ONLY_DEF_ATTR_UNUSED_VAR(x) __attribute__((unused)) int x = 0; void f7() { + ONLY_DEF_ATTR_UNUSED_VAR(l1); // COMPLIANT + l1; ONLY_DEF_ATTR_UNUSED_VAR(l2); // NON-COMPLIANT } diff --git a/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll b/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll index 7c4e8ef41d..6462ac855a 100644 --- a/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll +++ b/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll @@ -29,12 +29,16 @@ signature module MacroReportConfigSig { /* Create a message to describe this macro, using '$@' to describe an example `ResultElement`. */ string getMessageVariedResultInAllExpansions(Macro m); - /* + /** * Create a message to describe this macro expansion which produces a `ResultElement`, using '$@' * to describe the relevant macro. */ - string getMessageResultInIsolatedExpansion(ResultElement element); + + /** + * Create a message to describe a `ResultElement` which is not generated by a macro expansion. + */ + string getMessageNotInMacro(ResultElement element); } /** @@ -88,7 +92,7 @@ signature module MacroReportConfigSig { * ## Generating Report Objects * * This module also can be used to more easily report issues across these cases, by implementing - * `MacroReportConfigSig` and importing `DeduplicateMacroResults::Report::ReportResultInMacro`. + * `MacroReportConfigSig` and importing `DeduplicateMacroResults::Report::ReportResult`. * * ``` * module InvalidFooInMacroReportConfig implements MacroReportConfigSig { @@ -106,11 +110,15 @@ signature module MacroReportConfigSig { * string getMessageResultInIsolatedExpansion(InvalidFoo foo) { * result = "Invocation of macro $@ has invalid foo '" + foo.getName() + "'." * } + * + * string getMessageNotInMacro(ResultElement element) { + * result = "Invalid foo '" + element.getName() + "'." + * } * } * * import DeduplicateFooInMacros::Report as Report; * - * from Report::ReportResultInMacro report + * from Report::ReportResult report * where not excluded(report.getPrimaryElement(), ...) * select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocation(), * report.getOptionalPlaceholderMessage() @@ -234,11 +242,10 @@ module DeduplicateMacroResults< } } - /* + /** * Convenience predicate to know when invalid macro expansions have been reported at their macro * definition. */ - private predicate reported(Macro macro) { macro instanceof PrimaryMacroSameResultElementInAllInvocations or macro instanceof PrimaryMacroDifferentResultElementInAllInvocations @@ -248,7 +255,7 @@ module DeduplicateMacroResults< * A macro invocation for which the target macro does not always produce a `ResultElement`, but * this specific invocation of it does. * - * This is "primary" / most specific macro for these result elements. It will also does not match + * This is the "primary" / most specific macro for these result elements. It also does not match * `MacroInvocation`s inside of a `MacroInvocation` of a `Macro` which always produces a * `ResultElement`, indicating that the real problem lies with that other `Macro` instead of with * this particular invocation. @@ -274,10 +281,15 @@ module DeduplicateMacroResults< * See the doc comment for the `DeduplicateMacroResults` module for more info. */ module Report ReportConfig> { - newtype TReportResultInMacro = + newtype TReportResult = TReportMacroResultWithSameName(PrimaryMacroSameResultElementInAllInvocations def) or TReportMacroResultWithVariedName(PrimaryMacroDifferentResultElementInAllInvocations def) or - TReportIsolatedMacroResult(IsolatedMacroExpansionWithResultElement def) + TReportIsolatedMacroResult(IsolatedMacroExpansionWithResultElement def) or + TReportNotInMacro(ResultElement def) { + not exists (ResultMacroExpansion macroExpansion | + macroExpansion.getResultElement() = def + ) + } /** * An instance of a `ResultElement` to be reported to a user. @@ -291,7 +303,7 @@ module DeduplicateMacroResults< * The values returned by these methods are configured by the `MacroReportConfigSig` * signature parameter. */ - class ReportResultInMacro extends TReportResultInMacro { + class ReportResult extends TReportResult { string toString() { result = getMessage() } string getMessage() { @@ -310,6 +322,11 @@ module DeduplicateMacroResults< this = TReportIsolatedMacroResult(def) and result = ReportConfig::getMessageResultInIsolatedExpansion(def.getResultElement()) ) + or + exists(ResultElement def | + this = TReportNotInMacro(def) and + result = ReportConfig::getMessageNotInMacro(def) + ) } Element getPrimaryElement() { @@ -318,6 +335,8 @@ module DeduplicateMacroResults< this = TReportMacroResultWithVariedName(result) or this = TReportIsolatedMacroResult(result) + or + this = TReportNotInMacro(result) } Location getOptionalPlaceholderLocation() { @@ -335,6 +354,11 @@ module DeduplicateMacroResults< this = TReportIsolatedMacroResult(def) and result = def.getMacro().getLocation() ) + or + exists(ResultElement def | + this = TReportNotInMacro(def) and + result = def.getLocation() + ) } string getOptionalPlaceholderMessage() { @@ -343,7 +367,10 @@ module DeduplicateMacroResults< result = Config::describe(def.getExampleResultElement()) ) or - this = TReportMacroResultWithSameName(_) and + ( + this = TReportMacroResultWithSameName(_) + or this = TReportNotInMacro(_) + ) and result = "(ignored)" or this = TReportIsolatedMacroResult(_) and @@ -374,6 +401,12 @@ module DeduplicateMacroResults< or this = TReportIsolatedMacroResult(result) } + + ResultElement getAResultElement() { + result = getAResultMacroExpansion().getResultElement() + or + this = TReportNotInMacro(result) + } } } } diff --git a/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll b/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll index 96dcc8d315..fc262b5d93 100644 --- a/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll +++ b/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll @@ -40,141 +40,28 @@ module UnusedObjectDefinitionDedupeConfig implements import DeduplicateMacroResults as DeduplicateUnusedMacroObjects -/** - * A macro invocation that only defines one unused variable. - * - * These are reported at the invocation site when the variable is unused. - */ -class MacroExpansionWithOnlyUnusedObjectDefinition extends MacroInvocation { - UnusedObjectDefinition unusedObject; - - MacroExpansionWithOnlyUnusedObjectDefinition() { - exists(DeclStmt stmt, Declaration decl | - stmt = getStmt() and - count(getStmt()) = 1 and - count(stmt.getADeclaration()) = 1 and - decl = stmt.getADeclaration() and - count(decl.getADeclarationEntry()) = 1 and - unusedObject = decl.getADeclarationEntry() - ) and - not exists(this.getParentInvocation()) - } - - UnusedObjectDefinition getUnusedObject() { result = unusedObject } -} - -/** - * An object definition which is not from a macro, and for which all copies are unused. - * - * Extends the `HoldForAllCopies::LogicalResultElement` class, because these dead objects are often - * duplicated across defines and sometimes aren't marked used due to extractor bugs. - */ -class SimpleDeadObjectDefinition extends HoldsForAllCopies::LogicalResultElement -{ - SimpleDeadObjectDefinition() { not getAnElementInstance().isInMacroExpansion() } - - string getName() { result = getAnElementInstance().getName() } -} - -/* Make a type for reporting these two results in one query */ -newtype TReportDeadObjectAtDefinition = - TSimpleDeadObjectDefinition(SimpleDeadObjectDefinition def) or - TMacroExpansionWithOnlyUnusedObject(MacroExpansionWithOnlyUnusedObjectDefinition def) - -/** - * Class to report simple dead object definitions, and dead objects from macros that do nothing but - * define an object. - * - * To report all cases, make sure to also use the `DeduplicateUnusedMacroObjects::Report` module. - * - * To report these cases, use the methods: - * - `getMessage()` - * - `getPrimaryElement()`, - * - `getOptionalPlaceholderLocation()` - * - `getOptionalPlaceholderMessage()` - */ -class ReportDeadObjectAtDefinition extends TReportDeadObjectAtDefinition { - string toString() { result = getMessage() } - - string getMessage() { - exists(MacroExpansionWithOnlyUnusedObjectDefinition def | - this = TMacroExpansionWithOnlyUnusedObject(def) and - result = "Unused object definition '" + def.getUnusedObject().getName() + "' from macro '$@'." - ) - or - exists(SimpleDeadObjectDefinition def | - this = TSimpleDeadObjectDefinition(def) and - result = "Unused object definition '" + def.getName() + "'." - ) - } - - predicate hasAttrUnused() { - exists(MacroExpansionWithOnlyUnusedObjectDefinition def | - this = TMacroExpansionWithOnlyUnusedObject(def) and - def.getUnusedObject().hasAttrUnused() - ) - or - exists(SimpleDeadObjectDefinition def | - this = TSimpleDeadObjectDefinition(def) and - def.getAnElementInstance().hasAttrUnused() - ) - } - - Element getPrimaryElement() { - this = TMacroExpansionWithOnlyUnusedObject(result) - or - exists(SimpleDeadObjectDefinition def | - this = TSimpleDeadObjectDefinition(def) and - result = def.getAnElementInstance() - ) - } - - Location getOptionalPlaceholderLocation() { - exists(MacroExpansionWithOnlyUnusedObjectDefinition def | - this = TMacroExpansionWithOnlyUnusedObject(def) and - result = def.getMacro().getLocation() - ) - or - exists(SimpleDeadObjectDefinition def | - this = TSimpleDeadObjectDefinition(def) and - result = def.getAnElementInstance().getLocation() - ) - } - - string getOptionalPlaceholderMessage() { - exists(MacroExpansionWithOnlyUnusedObjectDefinition def | - this = TMacroExpansionWithOnlyUnusedObject(def) and - result = def.getMacroName() - ) - or - this = TSimpleDeadObjectDefinition(_) and - result = "" - } -} - /* Module config to use the `DeduplicateUnusedMacroObjects::Report` module */ -module ReportDeadObjectInMacroConfig implements MacroReportConfigSig { +module ReportDeadObjectConfig implements MacroReportConfigSig { bindingset[description] string getMessageSameResultInAllExpansions(Macro m, string description) { result = "Macro '" + m.getName() + "' defines unused object '" + description + "'." } string getMessageVariedResultInAllExpansions(Macro m) { - result = "Macro '" + m.getName() + "' defines unused object of varied names, for example, '$@'." + result = "Macro '" + m.getName() + "' defines unused object with an invocation-dependent name, for example, '$@'." } string getMessageResultInIsolatedExpansion(UnusedObjectDefinition unused) { result = "Invocation of macro '$@' defines unused object '" + unused.getName() + "'." } + + string getMessageNotInMacro(UnusedObjectDefinition unused) { + result = "Unused object '" + unused.getName() + "'." + } } /* The object to report in queries of dead objects used in macros */ -class ReportDeadObjectInMacro extends DeduplicateUnusedMacroObjects::Report::ReportResultInMacro +class ReportDeadObject extends DeduplicateUnusedMacroObjects::Report::ReportResult { - ReportDeadObjectInMacro() { - // `MacroExpansionWithOnlyUnusedObjectDefinition` is reported by class `ReportDeadObjectAtDefinition` - not getAResultMacroExpansion() instanceof MacroExpansionWithOnlyUnusedObjectDefinition - } - - predicate hasAttrUnused() { getAResultMacroExpansion().getResultElement().hasAttrUnused() } + predicate hasAttrUnused() { getAResultElement().hasAttrUnused() } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/DeadCode2.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/DeadCode2.qll index 8f8edc03fa..611062a5ac 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/DeadCode2.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/DeadCode2.qll @@ -5,9 +5,7 @@ import codingstandards.cpp.exclusions.RuleMetadata newtype DeadCode2Query = TUnusedObjectDefinitionQuery() or - TUnusedObjectDefinitionInMacroQuery() or - TUnusedObjectDefinitionStrictQuery() or - TUnusedObjectDefinitionInMacroStrictQuery() + TUnusedObjectDefinitionStrictQuery() predicate isDeadCode2QueryMetadata(Query query, string queryId, string ruleId, string category) { query = @@ -19,15 +17,6 @@ predicate isDeadCode2QueryMetadata(Query query, string queryId, string ruleId, s ruleId = "RULE-2-8" and category = "advisory" or - query = - // `Query` instance for the `unusedObjectDefinitionInMacro` query - DeadCode2Package::unusedObjectDefinitionInMacroQuery() and - queryId = - // `@id` for the `unusedObjectDefinitionInMacro` query - "c/misra/unused-object-definition-in-macro" and - ruleId = "RULE-2-8" and - category = "advisory" - or query = // `Query` instance for the `unusedObjectDefinitionStrict` query DeadCode2Package::unusedObjectDefinitionStrictQuery() and @@ -36,15 +25,6 @@ predicate isDeadCode2QueryMetadata(Query query, string queryId, string ruleId, s "c/misra/unused-object-definition-strict" and ruleId = "RULE-2-8" and category = "advisory" - or - query = - // `Query` instance for the `unusedObjectDefinitionInMacroStrict` query - DeadCode2Package::unusedObjectDefinitionInMacroStrictQuery() and - queryId = - // `@id` for the `unusedObjectDefinitionInMacroStrict` query - "c/misra/unused-object-definition-in-macro-strict" and - ruleId = "RULE-2-8" and - category = "advisory" } module DeadCode2Package { @@ -55,24 +35,10 @@ module DeadCode2Package { TQueryC(TDeadCode2PackageQuery(TUnusedObjectDefinitionQuery())) } - Query unusedObjectDefinitionInMacroQuery() { - //autogenerate `Query` type - result = - // `Query` type for `unusedObjectDefinitionInMacro` query - TQueryC(TDeadCode2PackageQuery(TUnusedObjectDefinitionInMacroQuery())) - } - Query unusedObjectDefinitionStrictQuery() { //autogenerate `Query` type result = // `Query` type for `unusedObjectDefinitionStrict` query TQueryC(TDeadCode2PackageQuery(TUnusedObjectDefinitionStrictQuery())) } - - Query unusedObjectDefinitionInMacroStrictQuery() { - //autogenerate `Query` type - result = - // `Query` type for `unusedObjectDefinitionInMacroStrict` query - TQueryC(TDeadCode2PackageQuery(TUnusedObjectDefinitionInMacroStrictQuery())) - } } diff --git a/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.expected b/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.expected index eb55b83924..d9a7fe6a07 100644 --- a/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.expected +++ b/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.expected @@ -1,3 +1,4 @@ +| deduplicatemacroresults.cpp:4:8:4:9 | definition of g1 | Findme var 'g1'. | deduplicatemacroresults.cpp:4:8:4:9 | deduplicatemacroresults.cpp:4:8:4:9 | (ignored) | | deduplicatemacroresults.cpp:10:1:10:34 | SOMETIMES_HAS_RESULTS1(type,name) | Invocation of macro $@ has findme var 'g3'. | deduplicatemacroresults.cpp:6:1:6:52 | deduplicatemacroresults.cpp:6:1:6:52 | SOMETIMES_HAS_RESULTS1 | | deduplicatemacroresults.cpp:13:1:13:34 | SOMETIMES_HAS_RESULTS2(type,name) | Invocation of macro $@ has findme var 'g5'. | deduplicatemacroresults.cpp:7:1:7:53 | deduplicatemacroresults.cpp:7:1:7:53 | SOMETIMES_HAS_RESULTS2 | | deduplicatemacroresults.cpp:15:1:15:50 | #define ALWAYS_HAS_SAME_RESULT() extern findme g6; | Macro ALWAYS_HAS_SAME_RESULT always has findme var named g6 | deduplicatemacroresults.cpp:15:1:15:50 | deduplicatemacroresults.cpp:15:1:15:50 | (ignored) | diff --git a/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.ql b/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.ql index cd999d72c9..9cae8d4ae8 100644 --- a/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.ql +++ b/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.ql @@ -22,11 +22,16 @@ module FindMeReportConfig implements MacroReportConfigSig { string getMessageResultInIsolatedExpansion(FindMe f) { result = "Invocation of macro $@ has findme var '" + f.getName() + "'." } + + string getMessageNotInMacro(FindMe f) { + result = "Findme var '" + f.getName() + "'." + + } } import DeduplicateMacroResults import DeduplicateMacroResults::Report -from ReportResultInMacro report +from ReportResult report select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocation(), report.getOptionalPlaceholderMessage() diff --git a/cpp/common/test/library/codingstandards/cpp/alertreporting/deduplicatemacroresults.cpp b/cpp/common/test/library/codingstandards/cpp/alertreporting/deduplicatemacroresults.cpp index 3c5d8bca5b..d9b3659bf6 100644 --- a/cpp/common/test/library/codingstandards/cpp/alertreporting/deduplicatemacroresults.cpp +++ b/cpp/common/test/library/codingstandards/cpp/alertreporting/deduplicatemacroresults.cpp @@ -1,7 +1,7 @@ typedef struct { } findme; -findme g1; // ignore -- not in a macro +findme g1; // baseline report, not in a macro #define SOMETIMES_HAS_RESULTS1(type, name) type name // ignore #define SOMETIMES_HAS_RESULTS2(type, name) type name; // ignore diff --git a/docs/development_handbook.md b/docs/development_handbook.md index 97c615ba2e..83670dbbc8 100644 --- a/docs/development_handbook.md +++ b/docs/development_handbook.md @@ -42,6 +42,7 @@ | 0.32.0 | 2024-05-01 | Luke Cartey | Refer to the user manual for the list of supported standards. | | 0.33.0 | 2024-07-30 | Kristen Newbury | Remove out dated references to codeql modules directory usage. | | 0.34.0 | 2024-08-22 | Kristen Newbury | Remove out dated references to git submodules usage. | +| 0.35.0 | 2025-01-15 | Mike Fairhurst | Add guidance for the addition of 'strict' queries. | ## Scope of work diff --git a/docs/user_manual.md b/docs/user_manual.md index 5e808a1401..ae02555091 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -29,7 +29,8 @@ | 0.21.0 | 2024-05-01 | Luke Cartey | Add MISRA C++ 2023 as under development, and clarify MISRA C 2012 coverage. | | 0.22.0 | 2024-10-02 | Luke Cartey | Add MISRA C 2023 as under development, and clarify MISRA C 2012 coverage. | | 0.23.0 | 2024-10-21 | Luke Cartey | Add assembly as a hazard. | -| 0.24.0 | 2024-10-22 | Luke Cartey | Add CodeQL packs as a usable output, update release artifacts list. | +| 0.24.0 | 2024-10-22 | Luke Cartey | Add CodeQL packs as a usable output, update release artifacts list. | +| 0.25.0 | 2025-01-15 | Mike Fairhurst | Add guidance for the usage of 'strict' queries. | ## Release information diff --git a/rule_packages/c/DeadCode2.json b/rule_packages/c/DeadCode2.json index b897f595e6..8b373c31b6 100644 --- a/rule_packages/c/DeadCode2.json +++ b/rule_packages/c/DeadCode2.json @@ -18,19 +18,6 @@ "external/misra/c/2012/amendment4" ] }, - { - "description": "Macros should not have unused object definitions.", - "kind": "problem", - "name": "Project macros should not include unused object definitions", - "precision": "very-high", - "severity": "recommendation", - "short_name": "UnusedObjectDefinitionInMacro", - "tags": [ - "maintainability", - "performance", - "external/misra/c/2012/amendment4" - ] - }, { "description": "A strict query which reports all unused object definitions with '__attribute__((unused))'.", "kind": "problem", @@ -44,20 +31,6 @@ "external/misra/c/2012/amendment4", "external/misra/c/strict" ] - }, - { - "description": "A strict query which reports all unused object definitions in macros with '__attribute__((unused))'.", - "kind": "problem", - "name": "Project macros should not include '__attribute__((unused))' object definitions", - "precision": "very-high", - "severity": "recommendation", - "short_name": "UnusedObjectDefinitionInMacroStrict", - "tags": [ - "maintainability", - "performance", - "external/misra/c/2012/amendment4", - "external/misra/c/strict" - ] } ], "title": "A project should not contain unused object definitions", From 333cc77a08606fc3ecf089791555647b295aef98 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 15 Jan 2025 20:04:29 -0800 Subject: [PATCH 143/370] Code format --- .../cpp/alertreporting/DeduplicateMacroResults.qll | 10 ++++------ .../src/codingstandards/cpp/deadcode/UnusedObjects.qll | 4 +++- .../cpp/alertreporting/DeduplicateMacroResults.ql | 5 +---- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll b/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll index 6462ac855a..c56c40b730 100644 --- a/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll +++ b/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll @@ -110,7 +110,7 @@ signature module MacroReportConfigSig { * string getMessageResultInIsolatedExpansion(InvalidFoo foo) { * result = "Invocation of macro $@ has invalid foo '" + foo.getName() + "'." * } - * + * * string getMessageNotInMacro(ResultElement element) { * result = "Invalid foo '" + element.getName() + "'." * } @@ -286,9 +286,7 @@ module DeduplicateMacroResults< TReportMacroResultWithVariedName(PrimaryMacroDifferentResultElementInAllInvocations def) or TReportIsolatedMacroResult(IsolatedMacroExpansionWithResultElement def) or TReportNotInMacro(ResultElement def) { - not exists (ResultMacroExpansion macroExpansion | - macroExpansion.getResultElement() = def - ) + not exists(ResultMacroExpansion macroExpansion | macroExpansion.getResultElement() = def) } /** @@ -368,8 +366,8 @@ module DeduplicateMacroResults< ) or ( - this = TReportMacroResultWithSameName(_) - or this = TReportNotInMacro(_) + this = TReportMacroResultWithSameName(_) or + this = TReportNotInMacro(_) ) and result = "(ignored)" or diff --git a/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll b/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll index fc262b5d93..60e732873a 100644 --- a/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll +++ b/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll @@ -48,7 +48,9 @@ module ReportDeadObjectConfig implements MacroReportConfigSig { result = "Invocation of macro $@ has findme var '" + f.getName() + "'." } - string getMessageNotInMacro(FindMe f) { - result = "Findme var '" + f.getName() + "'." - - } + string getMessageNotInMacro(FindMe f) { result = "Findme var '" + f.getName() + "'." } } import DeduplicateMacroResults From bd3e06bc63297ab0dd992e2e5f2ad8be2ce15d87 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 15 Jan 2025 20:47:22 -0800 Subject: [PATCH 144/370] Fix 18-1 amendment use-use flow --- ...interArithmeticToAddressDifferentArrays.qll | 18 ++++++++++++++---- ...ArithmeticToAddressDifferentArrays.expected | 1 - .../test.cpp | 6 ++---- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll b/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll index 9728bc1f6d..b19df81570 100644 --- a/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll +++ b/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll @@ -33,7 +33,7 @@ abstract class ArrayLikeAccess extends Expr { */ class ArrayVariableAccess extends ArrayLikeAccess, VariableAccess { int size; - + ArrayVariableAccess() { size = getType().(ArrayType).getArraySize() } override Variable getElement() { result = getTarget() } @@ -47,7 +47,7 @@ class ArrayVariableAccess extends ArrayLikeAccess, VariableAccess { /** * Get the size of the object pointed to by a type (pointer or array). - * + * * Depth of type unwrapping depends on the type. Pointer will be dereferenced only once: the element * size of `T*` is `sizeof(T)` while the element size of `T**` is `sizeof(T*)`. However, array types * will be deeply unwrapped, as the pointed to size of `T[][]` is `sizeof(T)`. These processes @@ -88,7 +88,17 @@ class CastedToBytePointer extends ArrayLikeAccess, Conversion { override int getSize() { result = size } - override DataFlow::Node getNode() { result.asConvertedExpr() = this } + override DataFlow::Node getNode() { + // Carefully avoid use-use flow, which would mean any later usage of the original pointer value + // after the cast would be considered a usage of the byte pointer value. + // + // To fix this, we currently assume the value is assigned to a variable, and find that variable + // with `.asDefinition()` like so: + exists(DataFlow::Node conversion | + conversion.asConvertedExpr() = this and + result.asDefinition() = conversion.asExpr() + ) + } } /** @@ -272,4 +282,4 @@ query predicate problems(Expr arrayPointerCreation, string message, Element arra "Array pointer " + derivedArrayPointerOrPointerOperand.getName() + " points " + difference.toString() + " " + denomination + " past the end of $@." ) -} \ No newline at end of file +} diff --git a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected index 438b697775..5bb4881b81 100644 --- a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected +++ b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected @@ -6,4 +6,3 @@ | test.cpp:25:15:25:21 | & ... | Array pointer p14 points 1 element past the end of $@. | test.cpp:2:7:2:8 | l1 | l1 | | test.cpp:30:15:30:21 | & ... | Array pointer p17 points 1 element past the end of $@. | test.cpp:28:24:28:42 | (unsigned char *)... | cast to btye pointer (unsigned char *)... | | test.cpp:35:15:35:21 | & ... | Array pointer p20 points 1 element past the end of $@. | test.cpp:33:24:33:43 | (unsigned char *)... | cast to btye pointer (unsigned char *)... | -| test.cpp:43:15:43:23 | & ... | Array pointer p23 points 96 elements past the end of $@. | test.cpp:28:24:28:42 | (unsigned char *)... | cast to btye pointer (unsigned char *)... | diff --git a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp index f81026870d..70b26a2a57 100644 --- a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp +++ b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp @@ -36,9 +36,7 @@ void f1() { // Casting to a pointer to a differently sized type that isn't char // invalidates analysis - int l3[3]; - long *p21 = (long*)&l1; + long *p21 = (long *)&l1; void *p22 = &p21[0]; // COMPLIANT - // Not compliant, but we shouldn't detect it, but we do for the wrong reason: - void *p23 = &p21[100]; // NON_COMPLIANT[FALSE_NEGATIVE][FALSE_POSITIVE] + void *p23 = &p21[100]; // NON_COMPLIANT[FALSE_NEGATIVE] } \ No newline at end of file From a5eb426ee248936e93dc1e51b8c7298094091038 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 15 Jan 2025 21:07:49 -0800 Subject: [PATCH 145/370] Fix format issues --- .../codingstandards/c/misra/EssentialTypes.qll | 15 +++++++-------- c/misra/test/rules/RULE-7-4/test.c | 2 +- .../rules/invalidatedenvstringpointers/test.cpp | 6 +++--- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll index b229bd54e2..7120921eed 100644 --- a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll +++ b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll @@ -297,8 +297,7 @@ class EssentialBinaryArithmeticExpr extends EssentialExpr, BinaryArithmeticOpera exists( Type leftEssentialType, Type rightEssentialType, EssentialTypeCategory leftEssentialTypeCategory, - EssentialTypeCategory rightEssentialTypeCategory, - int intTypeSize + EssentialTypeCategory rightEssentialTypeCategory, int intTypeSize | leftEssentialType = getEssentialType(getLeftOperand()) and rightEssentialType = getEssentialType(getRightOperand()) and @@ -340,19 +339,19 @@ class EssentialBinaryArithmeticExpr extends EssentialExpr, BinaryArithmeticOpera ) and ( leftEssentialTypeCategory = - [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] - and leftEssentialType.getSize() <= intTypeSize + [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] and + leftEssentialType.getSize() <= intTypeSize or rightEssentialTypeCategory = - [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] - and rightEssentialType.getSize() <= intTypeSize + [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] and + rightEssentialType.getSize() <= intTypeSize ) or this instanceof SubExpr and leftEssentialTypeCategory = EssentiallyCharacterType() and rightEssentialTypeCategory = - [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] - and rightEssentialType.getSize() <= intTypeSize + [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] and + rightEssentialType.getSize() <= intTypeSize then result instanceof PlainCharType else result = this.getStandardType() ) diff --git a/c/misra/test/rules/RULE-7-4/test.c b/c/misra/test/rules/RULE-7-4/test.c index ff270b611f..ab7ea21ce9 100644 --- a/c/misra/test/rules/RULE-7-4/test.c +++ b/c/misra/test/rules/RULE-7-4/test.c @@ -85,7 +85,7 @@ void w_call6() { w_sample6(1, "string10"); // COMPLIANT by first (and only) exception } -void w_sample7(char* x, ...) {} +void w_sample7(char *x, ...) {} void w_call7() { w_sample7("string11", 1); // NON_COMPLIANT, does not fit exceptional case diff --git a/cpp/common/test/rules/invalidatedenvstringpointers/test.cpp b/cpp/common/test/rules/invalidatedenvstringpointers/test.cpp index 167d770ef6..920d97c657 100644 --- a/cpp/common/test/rules/invalidatedenvstringpointers/test.cpp +++ b/cpp/common/test/rules/invalidatedenvstringpointers/test.cpp @@ -211,7 +211,7 @@ void f11(void) { void f12(void) { time_t rawtime; time(&rawtime); - char* r1 = ctime(&rawtime); + char *r1 = ctime(&rawtime); asctime(localtime(&rawtime)); printf("%s", r1); // NON_COMPLIANT } @@ -219,10 +219,10 @@ void f12(void) { void f13(void) { time_t rawtime; time(&rawtime); - char* r1 = ctime(&rawtime); + char *r1 = ctime(&rawtime); printf("%s", r1); // COMPLIANT - char* r2 = asctime(localtime(&rawtime)); + char *r2 = asctime(localtime(&rawtime)); printf("%s", r1); // NON_COMPLIANT printf("%s", r2); // COMPLIANT From 57b2067abce8fe8b55080bb6bfd560e60bc6fd4e Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 16 Jan 2025 10:14:18 -0800 Subject: [PATCH 146/370] Improve 18-1, void* casts and FPs where lowerBound appears incorrect --- .../2025-1-04-misra-c-technical-corrigenda-2.md | 3 ++- ...tUsePointerArithmeticToAddressDifferentArrays.qll | 12 +++++++++--- .../test.cpp | 6 ++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/change_notes/2025-1-04-misra-c-technical-corrigenda-2.md b/change_notes/2025-1-04-misra-c-technical-corrigenda-2.md index 81ae3eb561..be037074f6 100644 --- a/change_notes/2025-1-04-misra-c-technical-corrigenda-2.md +++ b/change_notes/2025-1-04-misra-c-technical-corrigenda-2.md @@ -4,8 +4,9 @@ - Disallow `+` and `-` operations with an essentially char type and other types larger than int type. - Note, this change affects the essential type of such expressions, which may affect other essential types rules. - `RULE-18-1`, `M5-0-16` - `PointerAndDerivedPointerMustAddressSameArray.ql`, `PointerAndDerivedPointerAccessDifferentArray.ql`: - - Treat casts to byte pointers as pointers to arrays of the size of the pointed-to type + - Treat casts to byte pointers as pointers to arrays of the size of the pointed-to type. - Fix typo in report message, "passed" replaced with "past." + - Suppress results where range analysis appears potentially unreliable. - `RULE-21-10`, `RULE-25-5-3`, `ENV34-C` - `CallToSetlocaleInvalidatesOldPointers.ql`, `CallToSetlocaleInvalidatesOldPointersMisra.ql`, `DoNotStorePointersReturnedByEnvFunctions.ql`: - Report usage of returned pointers from `asctime`, `ctime`, during a call to either of the former. - Report usage of returned pointers from `gmtime`, `localtime`, during a call to either of the former. \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll b/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll index b19df81570..5a45ff703e 100644 --- a/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll +++ b/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll @@ -9,6 +9,7 @@ import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import semmle.code.cpp.dataflow.new.DataFlow import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis +import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils import codeql.util.Boolean abstract class DoNotUsePointerArithmeticToAddressDifferentArraysSharedQuery extends Query { } @@ -68,11 +69,13 @@ int elementSize(Type type, Boolean deref) { * length depends on `elementSize()` of the original pointed-to type. */ class CastedToBytePointer extends ArrayLikeAccess, Conversion { + /** The sizeof() the pointed-to type */ int size; CastedToBytePointer() { getType().(PointerType).getBaseType().getSize() = 1 and - size = elementSize(getExpr().getType(), true) + size = elementSize(getExpr().getType(), true) and + size > 1 } override Element getElement() { result = this } @@ -138,7 +141,7 @@ module ArrayToArrayExprFlow = DataFlow::Global; /** Holds if the address taken expression `addressOf` takes the address of an array element at `index` of `array`. */ predicate pointerOperandCreation(AddressOfExpr addressOf, ArrayLikeAccess array, int index) { - exists(ArrayExpr ae | + exists(ArrayExpr ae, Expr arrayOffset | ( ArrayToArrayExprFlow::flow(array.getNode(), DataFlow::exprNode(ae.getArrayBase())) and array instanceof ArrayVariableAccess @@ -149,7 +152,10 @@ predicate pointerOperandCreation(AddressOfExpr addressOf, ArrayLikeAccess array, // flow() may hold for `ArrayVariableAccess` in the above, even though they aren't sources array instanceof CastedToBytePointer ) and - index = lowerBound(ae.getArrayOffset().getFullyConverted()) and + arrayOffset = ae.getArrayOffset().getFullyConverted() and + index = lowerBound(arrayOffset) and + // This case typically indicates range analysis has gone wrong: + not index = exprMaxVal(arrayOffset) and addressOf.getOperand() = ae ) } diff --git a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp index 70b26a2a57..4e373420e6 100644 --- a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp +++ b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp @@ -39,4 +39,10 @@ void f1() { long *p21 = (long *)&l1; void *p22 = &p21[0]; // COMPLIANT void *p23 = &p21[100]; // NON_COMPLIANT[FALSE_NEGATIVE] + + // Void pointers have size zero and can't be analyzed. + void *p24 = 0; + unsigned char* p25 = (unsigned char*)p24; + void *p26 = &p25[100]; // COMPLIANT + } \ No newline at end of file From 2d1cc22a68c1245831d66c483703deb4223db690 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 16 Jan 2025 10:14:29 -0800 Subject: [PATCH 147/370] Fix c tests --- ...ePointerArithmeticToAddressDifferentArrays.expected | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/c/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected b/c/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected index 1d487765df..bc471c0dc4 100644 --- a/c/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected +++ b/c/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected @@ -1,5 +1,5 @@ -| test.c:4:13:4:18 | ... + ... | Array pointer p2 points 1 element passed the end of $@. | test.c:2:7:2:8 | l1 | l1 | -| test.c:5:13:5:18 | ... + ... | Array pointer p3 points 1 element passed the end of $@. | test.c:2:7:2:8 | l1 | l1 | -| test.c:6:13:6:18 | & ... | Array pointer p4 points 1 element passed the end of $@. | test.c:2:7:2:8 | l1 | l1 | -| test.c:11:8:11:11 | ... -- | Array pointer p7 points 1 element passed the end of $@. | test.c:2:7:2:8 | l1 | l1 | -| test.c:12:8:12:9 | p3 | Array pointer p8 points 1 element passed the end of $@. | test.c:2:7:2:8 | l1 | l1 | +| test.c:4:13:4:18 | ... + ... | Array pointer p2 points 1 element past the end of $@. | test.c:2:7:2:8 | l1 | l1 | +| test.c:5:13:5:18 | ... + ... | Array pointer p3 points 1 element past the end of $@. | test.c:2:7:2:8 | l1 | l1 | +| test.c:6:13:6:18 | & ... | Array pointer p4 points 1 element past the end of $@. | test.c:2:7:2:8 | l1 | l1 | +| test.c:11:8:11:11 | ... -- | Array pointer p7 points 1 element past the end of $@. | test.c:2:7:2:8 | l1 | l1 | +| test.c:12:8:12:9 | p3 | Array pointer p8 points 1 element past the end of $@. | test.c:2:7:2:8 | l1 | l1 | From 5289894bc6a592628bda47bf24b806dfc16d11a8 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 16 Jan 2025 12:10:32 -0800 Subject: [PATCH 148/370] Fix test case format --- .../donotusepointerarithmetictoaddressdifferentarrays/test.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp index 4e373420e6..3a86d7963e 100644 --- a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp +++ b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp @@ -42,7 +42,6 @@ void f1() { // Void pointers have size zero and can't be analyzed. void *p24 = 0; - unsigned char* p25 = (unsigned char*)p24; + unsigned char *p25 = (unsigned char *)p24; void *p26 = &p25[100]; // COMPLIANT - } \ No newline at end of file From eae738532551f269a1c5cf07f6748c6ed708d6ee Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 16 Jan 2025 23:02:20 +0000 Subject: [PATCH 149/370] Remove stray comment --- c/misra/src/codingstandards/c/misra/EssentialTypes.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll index 0a4e64e98d..50b588d422 100644 --- a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll +++ b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll @@ -371,7 +371,6 @@ class EssentialSubExpr extends EssentialBinaryOperationSubjectToUsualConversions } } -// } /** * A named Enum type, as per D.5. */ From a8784e1c26bc68622cb16389f9a0e1562db436e5 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 19 Jan 2025 17:26:38 -0800 Subject: [PATCH 150/370] Simplify DeduplicateMacroResults::Report::ReportResult::toString() for performance reasons --- .../alertreporting/DeduplicateMacroResults.qll | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll b/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll index c56c40b730..b3c3d44ff4 100644 --- a/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll +++ b/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll @@ -302,7 +302,21 @@ module DeduplicateMacroResults< * signature parameter. */ class ReportResult extends TReportResult { - string toString() { result = getMessage() } + string toString() { + this = TReportMacroResultWithVariedName(_) and + result = + "Macro that always expands to a result element with invocation-dependent description" + or + this = TReportMacroResultWithSameName(_) and + result = "Macro that always expands to a result element with a constant description" + or + this = TReportIsolatedMacroResult(_) and + result = + "Specific macro expansion which produces a result element, but not all expansions do" + or + this = TReportNotInMacro(_) and + result = "Result element that is not in a macro" + } string getMessage() { exists(PrimaryMacroDifferentResultElementInAllInvocations def | From 0ba3359671fee9bb186aaf35cc3ce8794a3dfc01 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 21 Jan 2025 23:14:56 +0000 Subject: [PATCH 151/370] A7-1-2: Remove FunctionMissingConstexpr query As per #843 --- .../rules/A7-1-2/FunctionMissingConstexpr.ql | 160 ------------------ .../A7-1-2/FunctionMissingConstexpr.expected | 16 -- .../A7-1-2/FunctionMissingConstexpr.qlref | 1 - .../cpp/exclusions/cpp/Const.qll | 17 -- rule_packages/cpp/Const.json | 11 -- 5 files changed, 205 deletions(-) delete mode 100644 cpp/autosar/src/rules/A7-1-2/FunctionMissingConstexpr.ql delete mode 100644 cpp/autosar/test/rules/A7-1-2/FunctionMissingConstexpr.expected delete mode 100644 cpp/autosar/test/rules/A7-1-2/FunctionMissingConstexpr.qlref diff --git a/cpp/autosar/src/rules/A7-1-2/FunctionMissingConstexpr.ql b/cpp/autosar/src/rules/A7-1-2/FunctionMissingConstexpr.ql deleted file mode 100644 index 1cd68447fe..0000000000 --- a/cpp/autosar/src/rules/A7-1-2/FunctionMissingConstexpr.ql +++ /dev/null @@ -1,160 +0,0 @@ -/** - * @id cpp/autosar/function-missing-constexpr - * @name A7-1-2: The constexpr specifier shall be used for functions whose return value can be determined at compile time - * @description Using 'constexpr' makes it clear that a function is intended to return a compile - * time constant. - * @kind problem - * @precision high - * @problem.severity recommendation - * @tags external/autosar/id/a7-1-2 - * maintainability - * external/autosar/allocated-target/implementation - * external/autosar/enforcement/automated - * external/autosar/obligation/required - */ - -import cpp -import codingstandards.cpp.autosar -import codingstandards.cpp.TrivialType - -/** Gets a non-variant member field. */ -Field getANonVariantField(Class c) { - result = c.getAField() and - result.isInitializable() and - not result instanceof AnonymousUnionField -} - -/** - * A `Field` holding an "anonymous union" as described by `[class.union]`. - * - * For example, the union in this example: - * ``` - * class C { - * union { - * int x; - * short y; - * }; - * } - * ``` - */ -class AnonymousUnionField extends Field { - AnonymousUnionField() { hasName("(unknown field)") } - - /** - * Get a direct or indirect union member. - * - * Indirect members can come from nested anonymous unions. - */ - Field getAVariantMember() { - exists(Field f | f = getType().(Union).getAField() | - if f instanceof AnonymousUnionField - then result = f.(AnonymousUnionField).getAVariantMember() - else result = f - ) - } - - /** - * Holds if one variant member of this anonymous union field is initialized using NSDMI. - */ - predicate isExplicitlyInitialized() { exists(getAVariantMember().getInitializer().getExpr()) } -} - -/** - * Get a union which is not initialized by NSDMI. - */ -AnonymousUnionField getAnUninitializedAnonymousUnionField(Class c) { - result = c.getAField() and - not result.isExplicitlyInitialized() -} - -/** - * A function that can be `constexpr` specified according to the constraints for a `constexpr` - * function as specified in `[dcl.constexpr]/3`. - */ -class EffectivelyConstExprFunction extends Function { - EffectivelyConstExprFunction() { - // Not already marked as constexpr - not isDeclaredConstexpr() and - // Not virtual - not isVirtual() and - // Returns a literal type (which can be 'void') - (isLiteralType(getType()) or this instanceof Constructor) and - // Exclude cases that shouldn't be const or can't be const - not this instanceof Destructor and - not this instanceof CopyAssignmentOperator and - not this instanceof MoveAssignmentOperator and - not this.isCompilerGenerated() and - // All parameters are literal types - forall(Parameter p | p = getAParameter() | isLiteralType(p.getType())) and - // The function body is either deleted, defaulted or does not include one of the precluding - // statement kinds and is both side-effect free and created by the user - ( - isDeleted() - or - isDefaulted() - or - not this = any(AsmStmt a).getEnclosingFunction() and - not this = any(GotoStmt g).getEnclosingFunction() and - not this = any(TryStmt t).getEnclosingFunction() and - not exists(LocalVariable lv | this = lv.getFunction() | - not isLiteralType(lv.getType()) - or - lv instanceof StaticStorageDurationVariable - or - lv.isThreadLocal() - or - not exists(lv.getInitializer().getExpr()) - ) and - // For `constexpr` functions, the compiler only checks the rules above - it doesn't check - // whether the function can be evaluated as a compile time constant until the function is used, - // and then only confirms that it evaluates to a compile-time constant for a specific set of - // arguments used in another constexpr calculation. We approximate this by identifying the set - // of functions that are (conservatively) side-effect free. - isSideEffectFree() and - // "User defined" in some way - hasDefinition() and - not isCompilerGenerated() - ) and - ( - // A constructor should satisfy the constraints as specified in `[dcl.constexpr]/4`. - this instanceof Constructor - implies - ( - // No virtual base class - not getDeclaringType().getDerivation(_).isVirtual() and - ( - // All non-variant members initialized by this constructor - forall(Field f | f = getANonVariantField(getDeclaringType()) | - exists(ConstructorFieldInit cfi | - // Even if this field has a `getInitializer()` a `ConstructorFieldInit` will also be - // present on each constructor - cfi.getEnclosingFunction() = this and cfi.getTarget() = f - ) - ) and - // At least one variant member is initialized for each `AnonymousUnionField` which is not - // initialized with a `Field.getInitializer()`. This is different to the non-variant - // member case above - forall(AnonymousUnionField f | - f = getAnUninitializedAnonymousUnionField(getDeclaringType()) - | - exists(ConstructorFieldInit cfi | - cfi.getEnclosingFunction() = this and cfi.getTarget() = f.getAVariantMember() - ) - ) - or - // The function is deleted or defaulted, and every field has an NSDMI, and there are no - // uninitialized anonymous union fields - (isDeleted() or isDefaulted()) and - forall(Field f | f = getANonVariantField(getDeclaringType()) | - exists(f.getInitializer().getExpr()) - ) and - not exists(getAnUninitializedAnonymousUnionField(getDeclaringType())) - ) - ) - ) - } -} - -from EffectivelyConstExprFunction ecef -where not isExcluded(ecef, ConstPackage::functionMissingConstexprQuery()) -select ecef, ecef.getName() + " function could be marked as 'constexpr'." diff --git a/cpp/autosar/test/rules/A7-1-2/FunctionMissingConstexpr.expected b/cpp/autosar/test/rules/A7-1-2/FunctionMissingConstexpr.expected deleted file mode 100644 index a6de3fd724..0000000000 --- a/cpp/autosar/test/rules/A7-1-2/FunctionMissingConstexpr.expected +++ /dev/null @@ -1,16 +0,0 @@ -| test.cpp:30:3:30:17 | NonLiteralClass | NonLiteralClass function could be marked as 'constexpr'. | -| test.cpp:59:5:59:6 | h1 | h1 function could be marked as 'constexpr'. | -| test.cpp:67:5:67:6 | h2 | h2 function could be marked as 'constexpr'. | -| test.cpp:100:5:100:6 | h8 | h8 function could be marked as 'constexpr'. | -| test.cpp:117:7:117:9 | mf1 | mf1 function could be marked as 'constexpr'. | -| test.cpp:126:3:126:23 | MissingConstexprClass | MissingConstexprClass function could be marked as 'constexpr'. | -| test.cpp:127:3:127:23 | MissingConstexprClass | MissingConstexprClass function could be marked as 'constexpr'. | -| test.cpp:128:3:128:23 | MissingConstexprClass | MissingConstexprClass function could be marked as 'constexpr'. | -| test.cpp:161:3:161:26 | VariantMemberInitialized | VariantMemberInitialized function could be marked as 'constexpr'. | -| test.cpp:162:3:162:26 | VariantMemberInitialized | VariantMemberInitialized function could be marked as 'constexpr'. | -| test.cpp:163:3:163:26 | VariantMemberInitialized | VariantMemberInitialized function could be marked as 'constexpr'. | -| test.cpp:190:3:190:22 | VariantMemberNotInit | VariantMemberNotInit function could be marked as 'constexpr'. | -| test.cpp:269:26:269:26 | init | init function could be marked as 'constexpr'. | -| test.cpp:269:26:269:29 | init | init function could be marked as 'constexpr'. | -| test.cpp:271:26:271:26 | init | init function could be marked as 'constexpr'. | -| test.cpp:277:6:277:32 | test_template_instantiation | test_template_instantiation function could be marked as 'constexpr'. | diff --git a/cpp/autosar/test/rules/A7-1-2/FunctionMissingConstexpr.qlref b/cpp/autosar/test/rules/A7-1-2/FunctionMissingConstexpr.qlref deleted file mode 100644 index 723a910948..0000000000 --- a/cpp/autosar/test/rules/A7-1-2/FunctionMissingConstexpr.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/A7-1-2/FunctionMissingConstexpr.ql \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/Const.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Const.qll index 09f40388cc..f542ddf486 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/cpp/Const.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Const.qll @@ -7,7 +7,6 @@ newtype ConstQuery = TRemoveConstOrVolatileQualificationAutosarQuery() or TDeclarationUnmodifiedObjectMissingConstSpecifierQuery() or TVariableMissingConstexprQuery() or - TFunctionMissingConstexprQuery() or TCvQualifiersNotPlacedOnTheRightHandSideQuery() or TOutputParametersUsedQuery() or TInOutParametersDeclaredAsTNotModifiedQuery() or @@ -45,15 +44,6 @@ predicate isConstQueryMetadata(Query query, string queryId, string ruleId, strin ruleId = "A7-1-2" and category = "required" or - query = - // `Query` instance for the `functionMissingConstexpr` query - ConstPackage::functionMissingConstexprQuery() and - queryId = - // `@id` for the `functionMissingConstexpr` query - "cpp/autosar/function-missing-constexpr" and - ruleId = "A7-1-2" and - category = "required" - or query = // `Query` instance for the `cvQualifiersNotPlacedOnTheRightHandSide` query ConstPackage::cvQualifiersNotPlacedOnTheRightHandSideQuery() and @@ -149,13 +139,6 @@ module ConstPackage { TQueryCPP(TConstPackageQuery(TVariableMissingConstexprQuery())) } - Query functionMissingConstexprQuery() { - //autogenerate `Query` type - result = - // `Query` type for `functionMissingConstexpr` query - TQueryCPP(TConstPackageQuery(TFunctionMissingConstexprQuery())) - } - Query cvQualifiersNotPlacedOnTheRightHandSideQuery() { //autogenerate `Query` type result = diff --git a/rule_packages/cpp/Const.json b/rule_packages/cpp/Const.json index c574e547bf..55c5ed6f90 100644 --- a/rule_packages/cpp/Const.json +++ b/rule_packages/cpp/Const.json @@ -71,17 +71,6 @@ "tags": [ "maintainability" ] - }, - { - "description": "Using 'constexpr' makes it clear that a function is intended to return a compile time constant.", - "kind": "problem", - "name": "The constexpr specifier shall be used for functions whose return value can be determined at compile time", - "precision": "high", - "severity": "recommendation", - "short_name": "FunctionMissingConstexpr", - "tags": [ - "maintainability" - ] } ], "title": "The constexpr specifier shall be used for values that can be determined at compile time." From f0e3c45740e1605d26108446809147f135c5cae2 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 21 Jan 2025 23:17:00 +0000 Subject: [PATCH 152/370] A7-1-2: Refactor test case to reflect rule intention Change the test case related to constexpr functions to highlight expected behaviour for local variables. --- .../A7-1-2/VariableMissingConstexpr.expected | 2 ++ cpp/autosar/test/rules/A7-1-2/test.cpp | 16 ++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected b/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected index 31c26a11ff..20fbeebe4a 100644 --- a/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected +++ b/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected @@ -8,6 +8,8 @@ | test.cpp:44:16:44:17 | lc | Variable 'lc' could be marked 'constexpr'. | | test.cpp:45:17:45:19 | lc2 | Variable 'lc2' could be marked 'constexpr'. | | test.cpp:55:7:55:8 | m2 | Variable 'm2' could be marked 'constexpr' and static. | +| test.cpp:65:7:65:8 | x2 | Variable 'x2' could be marked 'constexpr'. | +| test.cpp:66:13:66:14 | x3 | Variable 'x3' could be marked 'constexpr'. | | test.cpp:130:7:130:8 | m1 | Variable 'm1' could be marked 'constexpr' and static. | | test.cpp:141:7:141:8 | m1 | Variable 'm1' could be marked 'constexpr' and static. | | test.cpp:221:7:221:8 | l1 | Variable 'l1' could be marked 'constexpr'. | diff --git a/cpp/autosar/test/rules/A7-1-2/test.cpp b/cpp/autosar/test/rules/A7-1-2/test.cpp index 664a9cb8e7..12c4fed384 100644 --- a/cpp/autosar/test/rules/A7-1-2/test.cpp +++ b/cpp/autosar/test/rules/A7-1-2/test.cpp @@ -56,16 +56,16 @@ class MemberConstExpr { int m3 = 0; // COMPLIANT - can be set by constructor }; -int h1(int x, int y) { // NON_COMPLIANT - return x + y; -} +int h1(int x, int y) { return x + y; } -constexpr int h1_correct(int x, int y) { // COMPLIANT - return x + y; -} +constexpr int h1_const(int x, int y) { return x + y; } -int h2(int x) { return h1(x, 1) + 1; } // NON_COMPLIANT -constexpr int h2_correct(int x) { return h1_correct(x, 1) + 1; } // COMPLIANT +int h2() { + int x1 = h1(1, 1); // COMPLIANT + int x2 = h1_const(1, 1); // NON_COMPLIANT + const int x3 = h1_const(1, 1); // NON_COMPLIANT + constexpr int x4 = h1_const(1, 1); // COMPLIANT +} int h3(int x) { // COMPLIANT - uses goto, so can't be constexpr if (x) { From 5d0bfeeb5203c7a71cc57d1e4e6d3d36a076b5c0 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 21 Jan 2025 23:22:28 +0000 Subject: [PATCH 153/370] A7-1-2: Remove function constexpr test cases --- .../A7-1-2/VariableMissingConstexpr.expected | 25 ++-- cpp/autosar/test/rules/A7-1-2/test.cpp | 130 ------------------ 2 files changed, 12 insertions(+), 143 deletions(-) diff --git a/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected b/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected index 20fbeebe4a..5feec712b8 100644 --- a/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected +++ b/cpp/autosar/test/rules/A7-1-2/VariableMissingConstexpr.expected @@ -10,16 +10,15 @@ | test.cpp:55:7:55:8 | m2 | Variable 'm2' could be marked 'constexpr' and static. | | test.cpp:65:7:65:8 | x2 | Variable 'x2' could be marked 'constexpr'. | | test.cpp:66:13:66:14 | x3 | Variable 'x3' could be marked 'constexpr'. | -| test.cpp:130:7:130:8 | m1 | Variable 'm1' could be marked 'constexpr' and static. | -| test.cpp:141:7:141:8 | m1 | Variable 'm1' could be marked 'constexpr' and static. | -| test.cpp:221:7:221:8 | l1 | Variable 'l1' could be marked 'constexpr'. | -| test.cpp:235:7:235:8 | l6 | Variable 'l6' could be marked 'constexpr'. | -| test.cpp:237:7:237:8 | l8 | Variable 'l8' could be marked 'constexpr'. | -| test.cpp:240:7:240:9 | l10 | Variable 'l10' could be marked 'constexpr'. | -| test.cpp:243:7:243:9 | l12 | Variable 'l12' could be marked 'constexpr'. | -| test.cpp:248:7:248:9 | l15 | Variable 'l15' could be marked 'constexpr'. | -| test.cpp:250:7:250:9 | l16 | Variable 'l16' could be marked 'constexpr'. | -| test.cpp:251:7:251:9 | l17 | Variable 'l17' could be marked 'constexpr'. | -| test.cpp:257:7:257:9 | l21 | Variable 'l21' could be marked 'constexpr'. | -| test.cpp:262:7:262:9 | l24 | Variable 'l24' could be marked 'constexpr'. | -| test.cpp:263:7:263:9 | l25 | Variable 'l25' could be marked 'constexpr'. | +| test.cpp:76:7:76:8 | m1 | Variable 'm1' could be marked 'constexpr' and static. | +| test.cpp:91:7:91:8 | l1 | Variable 'l1' could be marked 'constexpr'. | +| test.cpp:105:7:105:8 | l6 | Variable 'l6' could be marked 'constexpr'. | +| test.cpp:107:7:107:8 | l8 | Variable 'l8' could be marked 'constexpr'. | +| test.cpp:110:7:110:9 | l10 | Variable 'l10' could be marked 'constexpr'. | +| test.cpp:113:7:113:9 | l12 | Variable 'l12' could be marked 'constexpr'. | +| test.cpp:118:7:118:9 | l15 | Variable 'l15' could be marked 'constexpr'. | +| test.cpp:120:7:120:9 | l16 | Variable 'l16' could be marked 'constexpr'. | +| test.cpp:121:7:121:9 | l17 | Variable 'l17' could be marked 'constexpr'. | +| test.cpp:127:7:127:9 | l21 | Variable 'l21' could be marked 'constexpr'. | +| test.cpp:132:7:132:9 | l24 | Variable 'l24' could be marked 'constexpr'. | +| test.cpp:133:7:133:9 | l25 | Variable 'l25' could be marked 'constexpr'. | diff --git a/cpp/autosar/test/rules/A7-1-2/test.cpp b/cpp/autosar/test/rules/A7-1-2/test.cpp index 12c4fed384..5366a59f95 100644 --- a/cpp/autosar/test/rules/A7-1-2/test.cpp +++ b/cpp/autosar/test/rules/A7-1-2/test.cpp @@ -67,60 +67,6 @@ int h2() { constexpr int x4 = h1_const(1, 1); // COMPLIANT } -int h3(int x) { // COMPLIANT - uses goto, so can't be constexpr - if (x) { - goto l1; - } else { - return 10; - } -l1: - return 1; -} - -int h4(int x) { // COMPLIANT - uses try, so can't be constexpr - try { - return 1; - } catch (...) { - } -} - -int h5(int x) { // COMPLIANT - declares non literal local var - NonLiteralClass nlc; -} - -int h6(int x) { // COMPLIANT - declares static variable - static int i = x; - return x; -} - -int h7(int x) { // COMPLIANT - declares no init variable - int i; -} - -int h8(int x) { // NON_COMPLIANT - could be constexpr - int i = x; - return i; -} - -constexpr int h8_correct(int x) { // COMPLIANT - int i = x; - return i; -} - -int h9(int x) { // COMPLIANT - declares thread local variable - thread_local int i = x; - return x; -} - -class ConstexprFunctionClass { -public: - int mf1(int x) { return m1 + x; } // NON_COMPLIANT - constexpr int mf1_correct(int x) { return m1 + x; } // COMPLIANT - -private: - int m1; -}; - class MissingConstexprClass { public: MissingConstexprClass() = default; // NON_COMPLIANT @@ -130,82 +76,6 @@ class MissingConstexprClass { int m1 = 0; // NON_COMPLIANT }; -class VirtualBaseClass {}; - -class DerivedClass : public virtual VirtualBaseClass { -public: - DerivedClass() = default; // COMPLIANT - DerivedClass(int i) = delete; // COMPLIANT - DerivedClass(int i, LiteralClass lc) {} // COMPLIANT -private: - int m1 = 0; // NON_COMPLIANT -}; - -class NotAllMembersInitializedClass { -public: - NotAllMembersInitializedClass() = default; // COMPLIANT - NotAllMembersInitializedClass(int i) = delete; // COMPLIANT - NotAllMembersInitializedClass(int i, LiteralClass lc) {} // COMPLIANT -private: - int m1; -}; - -class NonLiteralParamsClass { -public: - NonLiteralParamsClass(int i, NonLiteralClass lc) {} // COMPLIANT -}; - -// Variant members are always initialized, so this can be marked constexpr -class VariantMemberInitialized { -public: - VariantMemberInitialized() = default; // NON_COMPLIANT - VariantMemberInitialized(int i) = delete; // NON_COMPLIANT - VariantMemberInitialized(int i, LiteralClass lc) {} // NON_COMPLIANT -private: - union { - int i = 0; - short s; - }; -}; - -class VariantMemberInitConstexpr { -public: - constexpr VariantMemberInitConstexpr() = default; // COMPLIANT - constexpr VariantMemberInitConstexpr(int i) = delete; // COMPLIANT - constexpr VariantMemberInitConstexpr(int i, LiteralClass lc) {} // COMPLIANT -private: - union { - int i = 0; - short s; - }; -}; - -// Variant members are not initialized at declaration, so we can only mark the -// constructors as constexpr if we explicitly initialize the variant member -class VariantMemberNotInit { -public: - VariantMemberNotInit() = default; // COMPLIANT - VariantMemberNotInit(int pi) = delete; // COMPLIANT - VariantMemberNotInit(int pi, LiteralClass lc) {} // COMPLIANT - VariantMemberNotInit(LiteralClass lc, int pi) : i(pi) {} // NON_COMPLIANT - constexpr VariantMemberNotInit(LiteralClass lc, short pi) // COMPLIANT - : i(pi) {} - -private: - union { - int i; - short s; - }; -}; - -class ExcludedCases { -public: - ~ExcludedCases() {} // COMPLIANT - - void operator=(ExcludedCases &) {} // COMPLIANT - void operator=(ExcludedCases &&) {} // COMPLIANT -}; - extern int random(); constexpr int add(int x, int y) { return x + y; } // Example with compile time constant literal value as default argument From 07cea2acc07dd2854bee201d52dade4e4b5ca41b Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 21 Jan 2025 23:23:49 +0000 Subject: [PATCH 154/370] Add A7-1-2 change note --- change_notes/2025-01-21-a7-1-2-remove-function-constexpr.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 change_notes/2025-01-21-a7-1-2-remove-function-constexpr.md diff --git a/change_notes/2025-01-21-a7-1-2-remove-function-constexpr.md b/change_notes/2025-01-21-a7-1-2-remove-function-constexpr.md new file mode 100644 index 0000000000..ac9964adc9 --- /dev/null +++ b/change_notes/2025-01-21-a7-1-2-remove-function-constexpr.md @@ -0,0 +1,2 @@ + - `A7-1-2` - `FunctionMissingConstexpr.ql` + - Address false positives by removing the query - the rule is not intended to cover functions. \ No newline at end of file From 3180bfb0cfb2050e04773049a3baa69e5469837a Mon Sep 17 00:00:00 2001 From: Fernando Jose Date: Wed, 22 Jan 2025 09:56:51 +0900 Subject: [PATCH 155/370] Update A7-1-1 test for the exclusion of rvalue references. --- cpp/autosar/test/rules/A7-1-1/test.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cpp/autosar/test/rules/A7-1-1/test.cpp b/cpp/autosar/test/rules/A7-1-1/test.cpp index 7895fd950f..1fdc0d66eb 100644 --- a/cpp/autosar/test/rules/A7-1-1/test.cpp +++ b/cpp/autosar/test/rules/A7-1-1/test.cpp @@ -83,4 +83,16 @@ template extern constexpr bool recurse_var = true; // COMPLIANT template extern constexpr bool recurse_var = B1 &&recurse_var; -void fp_621() { recurse_var; } \ No newline at end of file +void fp_621() { recurse_var; } + +#include + +void variadic_forwarding() {} + +template +void variadic_forwarding(T &&first, Args &&...rest) { + first; + variadic_forwarding(std::forward(rest)...); +} + +int test_variadic_forwarding() { variadic_forwarding(1, 1.1, "a"); } From dd892ffc18a6b60e56b83c288779bf60fbf8b8a7 Mon Sep 17 00:00:00 2001 From: Fernando Jose Date: Wed, 22 Jan 2025 12:49:55 +0900 Subject: [PATCH 156/370] Formatting fix in test. --- cpp/autosar/test/rules/A7-1-1/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/autosar/test/rules/A7-1-1/test.cpp b/cpp/autosar/test/rules/A7-1-1/test.cpp index 1fdc0d66eb..5e47b9c0bf 100644 --- a/cpp/autosar/test/rules/A7-1-1/test.cpp +++ b/cpp/autosar/test/rules/A7-1-1/test.cpp @@ -90,7 +90,7 @@ void fp_621() { recurse_var; } void variadic_forwarding() {} template -void variadic_forwarding(T &&first, Args &&...rest) { +void variadic_forwarding(T &&first, Args &&... rest) { first; variadic_forwarding(std::forward(rest)...); } From 6e68fb86452eb386a972aae9c81c14e4f85347b1 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 23 Jan 2025 23:08:40 +0000 Subject: [PATCH 157/370] Deviations: Support an attribute like comment syntax --- .../deviations/CodeIdentifierDeviation.qll | 39 +++++++++++-------- .../deviations/deviations_basic_test/main.cpp | 14 +++---- docs/user_manual.md | 28 ++++++------- 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll index e6220711a9..94587dca34 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll @@ -5,10 +5,10 @@ * some range of lines in the file containing the comment based on the annotation. The supported marker annotation * formats are: * - `` - the deviation applies to results on the current line. - * - `DEVIATION()` - same as above. - * - `DEVIATION_NEXT_LINE()` - this deviation applies to results on the next line. - * - `DEVIATION_BEGIN()` - marks the beginning of a range of lines where the deviation applies. - * - `DEVIATION_END()` - marks the end of a range of lines where the deviation applies. + * - `[[codingstandards::deviation()]]` - same as above. + * - `[[codingstandards::deviation_next_line()]]` - this deviation applies to results on the next line. + * - `[[codingstandards::deviation_begin()]]` - marks the beginning of a range of lines where the deviation applies. + * - `[[codingstandards::deviation_end()]]` - marks the end of a range of lines where the deviation applies. * * The valid `code-identifier`s are specified in deviation records, which also specify the query whose results are * suppressed by the deviation. @@ -53,7 +53,7 @@ private predicate commentMatches(Comment comment, string codeIdentifier) { /** * A deviation marker in the code. */ -abstract class DeviationMarker extends Comment { +abstract class CommentDeviationMarker extends Comment { DeviationRecord record; /** @@ -65,45 +65,50 @@ abstract class DeviationMarker extends Comment { /** * A deviation marker for a deviation that applies to the current line. */ -class DeviationEndOfLineMarker extends DeviationMarker { +class DeviationEndOfLineMarker extends CommentDeviationMarker { DeviationEndOfLineMarker() { - commentMatches(this, "DEVIATION(" + record.getCodeIdentifier() + ")") + commentMatches(this, "[[codingstandards::deviation(" + record.getCodeIdentifier() + ")]]") } } /** * A deviation marker for a deviation that applies to the next line. */ -class DeviationNextLineMarker extends DeviationMarker { +class DeviationNextLineMarker extends CommentDeviationMarker { DeviationNextLineMarker() { - commentMatches(this, "DEVIATION_NEXT_LINE(" + record.getCodeIdentifier() + ")") + commentMatches(this, + "[[codingstandards::deviation_next_line(" + record.getCodeIdentifier() + ")]]") } } /** * A deviation marker for a deviation that applies to a range of lines */ -abstract class DeviationRangeMarker extends DeviationMarker { } +abstract class CommentDeviationRangeMarker extends CommentDeviationMarker { } /** * A deviation marker for a deviation that begins on this line. */ -class DeviationBegin extends DeviationRangeMarker { - DeviationBegin() { commentMatches(this, "DEVIATION_BEGIN(" + record.getCodeIdentifier() + ")") } +class DeviationBegin extends CommentDeviationRangeMarker { + DeviationBegin() { + commentMatches(this, "[[codingstandards::deviation_begin(" + record.getCodeIdentifier() + ")]]") + } } /** * A deviation marker for a deviation that ends on this line. */ -class DeviationEnd extends DeviationRangeMarker { - DeviationEnd() { commentMatches(this, "DEVIATION_END(" + record.getCodeIdentifier() + ")") } +class DeviationEnd extends CommentDeviationRangeMarker { + DeviationEnd() { + commentMatches(this, "[[codingstandards::deviation_end(" + record.getCodeIdentifier() + ")]]") + } } private predicate hasDeviationCommentFileOrdering( - DeviationRecord record, DeviationRangeMarker comment, File file, int index + DeviationRecord record, CommentDeviationRangeMarker comment, File file, int index ) { comment = - rank[index](DeviationRangeMarker c | + rank[index](CommentDeviationRangeMarker c | c.getRecord() = record and file = c.getFile() | @@ -115,7 +120,7 @@ private predicate mkBeginStack(DeviationRecord record, File file, BeginStack sta // Stack is empty at the start index = 0 and stack = TEmptyBeginStack() and - exists(DeviationRangeMarker marker | + exists(CommentDeviationRangeMarker marker | marker.getRecord() = record and marker.getLocation().getFile() = file ) or diff --git a/cpp/common/test/deviations/deviations_basic_test/main.cpp b/cpp/common/test/deviations/deviations_basic_test/main.cpp index 53258f00fd..e1faaec68c 100644 --- a/cpp/common/test/deviations/deviations_basic_test/main.cpp +++ b/cpp/common/test/deviations/deviations_basic_test/main.cpp @@ -13,28 +13,28 @@ int main(int argc, char **argv) { long double d1; // NON_COMPLIANT (A0-4-2) long double d2; // a-0-4-2-deviation COMPLIANT[DEVIATED] - long double d3; // DEVIATION(a-0-4-2-deviation) COMPLIANT[DEVIATED] - + long double d3; // [[codingstandards::deviation(a-0-4-2-deviation)]] + // COMPLIANT[DEVIATED] long double d4; // NON_COMPLIANT (A0-4-2) - // DEVIATION_NEXT_LINE(a-0-4-2-deviation) + // [[codingstandards::deviation_next_line(a-0-4-2-deviation)]] long double d5; // COMPLIANT[DEVIATED] long double d6; // NON_COMPLIANT (A0-4-2) - // DEVIATION_BEGIN(a-0-4-2-deviation) + // [[codingstandards::deviation_begin(a-0-4-2-deviation)]] long double d7; // COMPLIANT[DEVIATED] getX(); // NON_COMPLIANT (A0-1-2) long double d8; // COMPLIANT[DEVIATED] getX(); // NON_COMPLIANT (A0-1-2) long double d9; // COMPLIANT[DEVIATED] - // DEVIATION_END(a-0-4-2-deviation) + // [[codingstandards::deviation_end(a-0-4-2-deviation)]] long double d10; // NON_COMPLIANT (A0-4-2) - // DEVIATION_BEGIN(a-0-4-2-deviation) + // [[codingstandards::deviation_begin(a-0-4-2-deviation)]] long double d11; // COMPLIANT[DEVIATED] getX(); // NON_COMPLIANT (A0-1-2) long double d12; // COMPLIANT[DEVIATED] getX(); // NON_COMPLIANT (A0-1-2) long double d13; // COMPLIANT[DEVIATED] - // DEVIATION_END(a-0-4-2-deviation) + // [[codingstandards::deviation_end(a-0-4-2-deviation)]] long double d14; // NON_COMPLIANT (A0-4-2) getX(); // NON_COMPLIANT (A0-1-2) return 0; diff --git a/docs/user_manual.md b/docs/user_manual.md index 7ad4dc4208..a936118758 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -426,8 +426,8 @@ The `process_coding_standards_config.py` has a dependency on the package `pyyaml A code identifier specified in a deviation record can be applied to certain results in the code by adding a comment marker consisting of a `code-identifier` with some optional annotations. The supported marker annotation formats are: - `` - the deviation applies to results on the current line. - - `DEVIATION()` - the deviation applies to results on the current line. - - `DEVIATION_NEXT_LINE()` - this deviation applies to results on the next line. + - `codingstandards::deviation()` - the deviation applies to results on the current line. + - `codingstandards::deviation_next_line()` - this deviation applies to results on the next line. - `DEVIATION_BEGIN()` - marks the beginning of a range of lines where the deviation applies. - `DEVIATION_END()` - marks the end of a range of lines where the deviation applies. @@ -438,32 +438,32 @@ Here are some examples, using the deviation record with the `a-0-4-2-deviation` long double x2; // a-0-4-2-deviation - COMPLIANT long double x3; // COMPLIANT - a-0-4-2-deviation - long double x4; // DEVIATION(a-0-4-2-deviation) - COMPLIANT - long double x5; // COMPLIANT - DEVIATION(a-0-4-2-deviation) + long double x4; // [[codingstandards::deviation(a-0-4-2-deviation)]] - COMPLIANT + long double x5; // COMPLIANT - [[codingstandards::deviation(a-0-4-2-deviation)]] - // DEVIATION_NEXT_LINE(a-0-4-2-deviation) + // [[codingstandards::deviation_next_line(a-0-4-2-deviation)]] long double x6; // COMPLIANT - // DEVIATION_BEGIN(a-0-4-2-deviation) + // [[codingstandards::deviation_begin(a-0-4-2-deviation)]] long double x7; // COMPLIANT - // DEVIATION_END(a-0-4-2-deviation) + // [[codingstandards::deviation_end(a-0-4-2-deviation)]] ``` -`DEVIATION_END` markers will pair with the closest unmatched `DEVIATION_BEGIN` for the same `code-identifier`. Consider this example: +`codingstandards::deviation_end` markers will pair with the closest unmatched `codingstandards::deviation_begin` for the same `code-identifier`. Consider this example: ```cpp -1 | // DEVIATION_BEGIN(a-0-4-2-deviation) +1 | // [[codingstandards::deviation_begin(a-0-4-2-deviation)]] 2 | -3 | // DEVIATION_BEGIN(a-0-4-2-deviation) +3 | // [[codingstandards::deviation_begin(a-0-4-2-deviation)]] 4 | -5 | // DEVIATION_END(a-0-4-2-deviation) +5 | // [[codingstandards::deviation_end(a-0-4-2-deviation)]] 6 | -7 | // DEVIATION_END(a-0-4-2-deviation) +7 | // [[codingstandards::deviation_end(a-0-4-2-deviation)]] ``` Here, Line 1 will pair with Line 7, and Line 3 will pair with Line 8. -A `DEVIATION_END` without a matching `DEVIATION_BEGIN`, or `DEVIATION_BEGIN` without a matching `DEVIATION_END` is invalid and will be ignored. +A `codingstandards::deviation_end` without a matching `codingstandards::deviation_begin`, or `codingstandards::deviation_begin` without a matching `codingstandards::deviation_end` is invalid and will be ignored. -`DEVIATION_BEGIN` and `DEVIATION_END` markers only apply within a single file. Markers cannot be paired across files, and deviations do not apply to included files. +`codingstandards::deviation_begin` and `codingstandards::deviation_end` markers only apply within a single file. Markers cannot be paired across files, and deviations do not apply to included files. ##### Deviation permit From a19965e7643c5efdd7cb8cf10d3d9ed0c620cf4d Mon Sep 17 00:00:00 2001 From: Michael R Fairhurst Date: Fri, 24 Jan 2025 19:32:56 -0800 Subject: [PATCH 158/370] Fix typo Co-authored-by: Luke Cartey <5377966+lcartey@users.noreply.github.com> --- c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql b/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql index b0945db559..6c03d32dab 100644 --- a/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql +++ b/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql @@ -149,7 +149,7 @@ import MemoryOrderFlow::PathGraph /** * If the node is a memory order constant, or shares a value with a memory order constant, then - * return the name of that cnonstant. Otherwise, simply print the node. + * return the name of that constant. Otherwise, simply print the node. */ string describeMemoryOrderNode(DataFlow::Node node) { if node.asExpr() instanceof MemoryOrderConstantExpr From 74867cc66ab0f70941255a99620543a695d9d69a Mon Sep 17 00:00:00 2001 From: knewbury01 Date: Mon, 27 Jan 2025 20:59:21 +0000 Subject: [PATCH 159/370] Bump version to 2.42.0-dev --- c/cert/src/qlpack.yml | 2 +- c/cert/test/qlpack.yml | 2 +- c/common/src/qlpack.yml | 2 +- c/common/test/qlpack.yml | 2 +- c/misra/src/qlpack.yml | 2 +- c/misra/test/qlpack.yml | 2 +- cpp/autosar/src/qlpack.yml | 2 +- cpp/autosar/test/qlpack.yml | 2 +- cpp/cert/src/qlpack.yml | 2 +- cpp/cert/test/qlpack.yml | 2 +- cpp/common/src/qlpack.yml | 2 +- cpp/common/test/qlpack.yml | 2 +- cpp/misra/src/qlpack.yml | 2 +- cpp/misra/test/qlpack.yml | 2 +- cpp/report/src/qlpack.yml | 2 +- docs/user_manual.md | 12 ++++++------ 16 files changed, 21 insertions(+), 21 deletions(-) diff --git a/c/cert/src/qlpack.yml b/c/cert/src/qlpack.yml index 4945abe49c..d5ba524b14 100644 --- a/c/cert/src/qlpack.yml +++ b/c/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards -version: 2.41.0-dev +version: 2.42.0-dev description: CERT C 2016 suites: codeql-suites license: MIT diff --git a/c/cert/test/qlpack.yml b/c/cert/test/qlpack.yml index af5e71d2a1..98d9895612 100644 --- a/c/cert/test/qlpack.yml +++ b/c/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards-tests -version: 2.41.0-dev +version: 2.42.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/common/src/qlpack.yml b/c/common/src/qlpack.yml index 9545a88178..e775358108 100644 --- a/c/common/src/qlpack.yml +++ b/c/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards -version: 2.41.0-dev +version: 2.42.0-dev license: MIT dependencies: codeql/common-cpp-coding-standards: '*' diff --git a/c/common/test/qlpack.yml b/c/common/test/qlpack.yml index febda7a63b..f76badccfc 100644 --- a/c/common/test/qlpack.yml +++ b/c/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards-tests -version: 2.41.0-dev +version: 2.42.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/misra/src/qlpack.yml b/c/misra/src/qlpack.yml index 758c059c01..0ed5ef8b97 100644 --- a/c/misra/src/qlpack.yml +++ b/c/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards -version: 2.41.0-dev +version: 2.42.0-dev description: MISRA C 2012 suites: codeql-suites license: MIT diff --git a/c/misra/test/qlpack.yml b/c/misra/test/qlpack.yml index d367e8d06d..bf45171e18 100644 --- a/c/misra/test/qlpack.yml +++ b/c/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards-tests -version: 2.41.0-dev +version: 2.42.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/autosar/src/qlpack.yml b/cpp/autosar/src/qlpack.yml index 565cfc12db..80f6d1b0d2 100644 --- a/cpp/autosar/src/qlpack.yml +++ b/cpp/autosar/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards -version: 2.41.0-dev +version: 2.42.0-dev description: AUTOSAR C++14 Guidelines R22-11, R21-11, R20-11, R19-11 and R19-03 suites: codeql-suites license: MIT diff --git a/cpp/autosar/test/qlpack.yml b/cpp/autosar/test/qlpack.yml index 66755fe907..a1c802fec5 100644 --- a/cpp/autosar/test/qlpack.yml +++ b/cpp/autosar/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards-tests -version: 2.41.0-dev +version: 2.42.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/cert/src/qlpack.yml b/cpp/cert/src/qlpack.yml index cc981411c2..3005c15ec3 100644 --- a/cpp/cert/src/qlpack.yml +++ b/cpp/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards -version: 2.41.0-dev +version: 2.42.0-dev description: CERT C++ 2016 suites: codeql-suites license: MIT diff --git a/cpp/cert/test/qlpack.yml b/cpp/cert/test/qlpack.yml index af6e4f8659..9c49caac9f 100644 --- a/cpp/cert/test/qlpack.yml +++ b/cpp/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards-tests -version: 2.41.0-dev +version: 2.42.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/common/src/qlpack.yml b/cpp/common/src/qlpack.yml index 4d0aeb01f1..d97b322120 100644 --- a/cpp/common/src/qlpack.yml +++ b/cpp/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards -version: 2.41.0-dev +version: 2.42.0-dev license: MIT dependencies: codeql/cpp-all: 1.4.2 diff --git a/cpp/common/test/qlpack.yml b/cpp/common/test/qlpack.yml index a6d2ae30eb..a207965a5e 100644 --- a/cpp/common/test/qlpack.yml +++ b/cpp/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards-tests -version: 2.41.0-dev +version: 2.42.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/misra/src/qlpack.yml b/cpp/misra/src/qlpack.yml index a6ac09f1b1..fc3162ffb4 100644 --- a/cpp/misra/src/qlpack.yml +++ b/cpp/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards -version: 2.41.0-dev +version: 2.42.0-dev description: MISRA C++ 2023 default-suite: codeql-suites/misra-cpp-default.qls license: MIT diff --git a/cpp/misra/test/qlpack.yml b/cpp/misra/test/qlpack.yml index 0265144f4f..d0bd3a8b5a 100644 --- a/cpp/misra/test/qlpack.yml +++ b/cpp/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards-tests -version: 2.41.0-dev +version: 2.42.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/report/src/qlpack.yml b/cpp/report/src/qlpack.yml index d1c854206c..1a8ea75e77 100644 --- a/cpp/report/src/qlpack.yml +++ b/cpp/report/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/report-cpp-coding-standards -version: 2.41.0-dev +version: 2.42.0-dev license: MIT dependencies: codeql/cpp-all: 1.4.2 diff --git a/docs/user_manual.md b/docs/user_manual.md index b45b32639a..df3ce9a6b8 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -34,14 +34,14 @@ ## Release information -This user manual documents release `2.41.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). +This user manual documents release `2.42.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). The release page documents the release notes and contains the following artifacts part of the release: - `coding-standards-codeql-packs-2.37.0-dev.zip`: CodeQL packs that can be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `code-scanning-cpp-query-pack-2.41.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `supported_rules_list_2.41.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. -- `supported_rules_list_2.41.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. -- `user_manual_2.41.0-dev.md`: This user manual. +- `code-scanning-cpp-query-pack-2.42.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. +- `supported_rules_list_2.42.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. +- `supported_rules_list_2.42.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. +- `user_manual_2.42.0-dev.md`: This user manual. - `Source Code (zip)`: A zip archive containing the contents of https://github.com/github/codeql-coding-standards - `Source Code (tar.gz)`: A GZip compressed tar archive containing the contents of https://github.com/github/codeql-coding-standards - `checksums.txt`: A text file containing sha256 checksums for the aforementioned artifacts. @@ -583,7 +583,7 @@ This section describes known failure modes for "CodeQL Coding Standards" and des | | Out of space | Less output. Some files may be only be partially analyzed, or not analyzed at all. | Error reported on the command line. | Increase space. If it remains an issue report space consumption issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False positives | More output. Results are reported which are not violations of the guidelines. | All reported results must be reviewed. | Report false positive issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False negatives | Less output. Violations of the guidelines are not reported. | Other validation and verification processes during software development should be used to complement the analysis performed by CodeQL Coding Standards. | Report false negative issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.41.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | +| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.42.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | | | Incorrect deviation record specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation records with a reason. Ensure that all deviation records are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Incorrect deviation permit specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation permits with a reason. Ensure that all deviation permits are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Unapproved use of a deviation record | Less output. Results for guideline violations are not reported. | Validate that the deviation record use is approved by verifying the approved-by attribute of the deviation record specification. | Ensure that each raised deviation record is approved by an independent approver through an auditable process. | From d26d960cda7d843cef8d8f5b326246b6051e7e89 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 27 Jan 2025 15:56:52 -0800 Subject: [PATCH 160/370] Address feedback --- c/misra/src/codeql-suites/misra-c-audit.qls | 8 ++++ .../rules/DIR-5-3/ThreadCreatedByThread.ql | 29 +++++------- .../AtomicAggregateObjectDirectlyAccessed.ql | 4 +- .../RULE-21-25/InvalidMemoryOrderArgument.ql | 46 ++++++------------- ...icAggregateObjectDirectlyAccessed.expected | 9 ++++ c/misra/test/rules/RULE-12-6/test.c | 28 +++++++++++ .../InvalidMemoryOrderArgument.expected | 13 ++++-- c/misra/test/rules/RULE-21-25/test.c | 2 +- 8 files changed, 84 insertions(+), 55 deletions(-) create mode 100644 c/misra/src/codeql-suites/misra-c-audit.qls diff --git a/c/misra/src/codeql-suites/misra-c-audit.qls b/c/misra/src/codeql-suites/misra-c-audit.qls new file mode 100644 index 0000000000..ce1b9fed68 --- /dev/null +++ b/c/misra/src/codeql-suites/misra-c-audit.qls @@ -0,0 +1,8 @@ +- description: MISRA C 2012 (Audit) +- qlpack: codeql/misra-c-coding-standards +- include: + kind: + - problem + - path-problem + tags contain: + - external/misra/c/audit diff --git a/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql b/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql index 25b8b4cb9f..355b30808d 100644 --- a/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql +++ b/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql @@ -19,27 +19,22 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.Concurrency -Function callers(Function f) { result = f.getACallToThisFunction().getEnclosingFunction() } +class CThreadRoot extends Function { + CThreadCreateCall threadCreate; -class ThreadReachableFunction extends Function { - /* The root threaded function from which this function is reachable */ - Function threadRoot; - - ThreadReachableFunction() { - exists(CThreadCreateCall tc | - tc.getFunction() = callers*(this) and - threadRoot = tc.getFunction() - ) + CThreadRoot() { + threadCreate.getFunction() = this } - /* Get the root threaded function from which this function is reachable */ - Function getThreadRoot() { result = threadRoot } + /* Get a function which is reachable from this function */ + Function getAReachableFunction() { calls*(result) } + + CThreadCreateCall getCThreadCreateCall() { result = threadCreate } } -from CThreadCreateCall tc, ThreadReachableFunction enclosingFunction, Function threadRoot + from CThreadCreateCall tc, CThreadRoot threadRoot where not isExcluded(tc, Concurrency6Package::threadCreatedByThreadQuery()) and - enclosingFunction = tc.getEnclosingFunction() and - threadRoot = enclosingFunction.getThreadRoot() -select tc, "Thread creation call reachable from threaded function '$@'.", threadRoot, - threadRoot.toString() + tc.getEnclosingFunction() = threadRoot.getAReachableFunction() +select tc, "Thread creation call reachable from function '$@', which may also be $@.", threadRoot, + threadRoot.toString(), threadRoot.getCThreadCreateCall(), "started as a thread" diff --git a/c/misra/src/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.ql b/c/misra/src/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.ql index 4e65fa3f91..7478bb2787 100644 --- a/c/misra/src/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.ql +++ b/c/misra/src/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.ql @@ -22,13 +22,13 @@ where ( exists(FieldAccess fa | expr = fa and - fa.getQualifier().getUnderlyingType().hasSpecifier("atomic") and + fa.getQualifier().getType().hasSpecifier("atomic") and field = fa.getTarget() ) or exists(PointerFieldAccess fa | expr = fa and - fa.getQualifier().getUnderlyingType().(PointerType).getBaseType().hasSpecifier("atomic") and + fa.getQualifier().getType().stripTopLevelSpecifiers().(PointerType).getBaseType().hasSpecifier("atomic") and field = fa.getTarget() ) ) diff --git a/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql b/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql index 6c03d32dab..92ec2694b3 100644 --- a/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql +++ b/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql @@ -46,7 +46,7 @@ class MemoryOrderConstantExpr extends Expr { } /* Get the name of the `MemoryOrder` this expression is valued as. */ - string getMemoryOrderString() { result = ord.toString() } + string getMemoryOrderString() { result = ord.getName() } } /** @@ -56,26 +56,26 @@ class MemoryOrderedStdAtomicFunction extends Function { int orderParamIdx; MemoryOrderedStdAtomicFunction() { - exists(int baseParamIdx, int baseParams, string prefix, string suffix | - prefix = ["__", "__c11_"] and - suffix = ["", ".*", "_explicit"] and + exists(int baseParamIdx, int baseParams, string prefix, string regex, string basename | + regex = "__(c11_)?atomic_([a-z_]+)" and + prefix = getName().regexpCapture(regex, 1) and + basename = "atomic_" + getName().regexpCapture(regex, 2) + ["", "_explicit"] and ( - getName().regexpMatch(prefix + ["atomic_thread_fence", "atomic_signal_fence"] + suffix) and + basename in ["atomic_thread_fence", "atomic_signal_fence"] and baseParamIdx = 0 and baseParams = 1 or - getName() - .regexpMatch(prefix + ["atomic_load", "atomic_flag_clear", "atomic_flag_test_and_set"] + - suffix) and + basename in ["atomic_load", "atomic_flag_clear", "atomic_flag_test_and_set"] and baseParamIdx = 1 and baseParams = 2 or - getName() - .regexpMatch(prefix + ["atomic_store", "atomic_fetch_.*", "atomic_exchange"] + suffix) and + basename in [ + "atomic_store", "atomic_fetch_" + ["add", "sub", "or", "xor", "and"], "atomic_exchange" + ] and baseParamIdx = 2 and baseParams = 3 or - getName().regexpMatch(prefix + "atomic_compare_exchange_.*" + suffix) and + basename in ["atomic_compare_exchange_" + ["strong", "weak"]] and baseParamIdx = [3, 4] and baseParams = 5 ) and @@ -84,8 +84,7 @@ class MemoryOrderedStdAtomicFunction extends Function { // __atomic_load(8, &repr->a, &desired, order) // or // __atomic_load_8(&repr->a, &desired, order) - prefix = "__" and - suffix = ".*" and + prefix = "" and exists(int extraParams | extraParams = getNumberOfParameters() - baseParams and extraParams >= 0 and @@ -94,13 +93,7 @@ class MemoryOrderedStdAtomicFunction extends Function { or // Clang case, no inserted parameters: // __c11_atomic_load(object, order) - suffix = "" and - prefix = "__c11_" and - orderParamIdx = baseParamIdx - or - // Non-macro case, may occur in a subset of gcc/clang functions: - prefix = "" and - suffix = "_explicit" and + prefix = "c11_" and orderParamIdx = baseParamIdx ) ) @@ -122,17 +115,6 @@ module MemoryOrderFlowConfig implements DataFlow::ConfigSig { node.asExpr() = literal and not literal.getValue().toInt() = any(AllowedMemoryOrder a).getValue().toInt() ) - or - // Everything else: not a memory order constant or an integer valued literal, also exclude - // variables and functions, things that flow further back. - exists(Expr e | - node.asExpr() = e and - not e instanceof MemoryOrderConstantAccess and - not e instanceof Literal and - not e instanceof VariableAccess and - not e instanceof FunctionCall and - not DataFlow::localFlowStep(_, node) - ) } predicate isSink(DataFlow::Node node) { @@ -169,4 +151,4 @@ where not value = any(AllowedMemoryOrder e).getName() and function.getACallToThisFunction().getAnArgument() = argument select argument, source, sink, "Invalid memory order '$@' in call to function '$@'.", value, value, - function, function.toString() + function, function.getName() diff --git a/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.expected b/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.expected index df7f149fcc..5a92fc72fd 100644 --- a/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.expected +++ b/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.expected @@ -2,3 +2,12 @@ | test.c:44:18:44:18 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | | test.c:45:13:45:13 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | | test.c:46:18:46:18 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | +| test.c:65:6:65:6 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | +| test.c:71:9:71:9 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | +| test.c:82:18:82:18 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | +| test.c:83:3:83:31 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | +| test.c:84:3:84:39 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | +| test.c:85:3:85:19 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | +| test.c:86:3:86:23 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | +| test.c:87:3:87:19 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | +| test.c:88:3:88:23 | x | Invalid access to member '$@' on atomic struct or union. | test.c:5:7:5:7 | x | x | diff --git a/c/misra/test/rules/RULE-12-6/test.c b/c/misra/test/rules/RULE-12-6/test.c index ae6125da96..0281e6b0d8 100644 --- a/c/misra/test/rules/RULE-12-6/test.c +++ b/c/misra/test/rules/RULE-12-6/test.c @@ -58,4 +58,32 @@ void f1() { *s1_atomic_ptr = (s1){0}; // COMPLIANT s1_atomic_ptr = l2; // COMPLIANT s1_atomic_ptr->x; // COMPLIANT + + // Atomic specifier hidden behind a typedef, still atomic: + typedef _Atomic s1 atomic_s1; + atomic_s1 l3; + l3.x; // NON_COMPLIANT + + // Worst case scenario: a typedef of a volatile const pointer to an atomic + // typedef type. + typedef atomic_s1 *volatile const atomic_s1_specified_ptr; + atomic_s1_specified_ptr l4; + (l4)->x; // NON_COMPLIANT +} + +#define NOOP(x) (x) +#define DOT_FIELD_ACCESS_X(v) (v).x +#define POINTER_FIELD_ACCESS_X(v) (v)->x +#define GET_X_ATOMIC_S1() atomic_s1.x +#define GET_X_PTR_ATOMIC_S1() atomic_s1.x + +void f2() { + // Banned UB with user macros: + NOOP(atomic_s1.x); // NON-COMPLIANT + DOT_FIELD_ACCESS_X(atomic_s1); // NON-COMPLIANT + POINTER_FIELD_ACCESS_X(ptr_atomic_s1); // NON-COMPLIANT + GET_X_ATOMIC_S1(); // NON-COMPLIANT + GET_X_PTR_ATOMIC_S1(); // NON-COMPLIANT + GET_X_ATOMIC_S1() = 0; // NON-COMPLIANT + GET_X_PTR_ATOMIC_S1() = 0; // NON-COMPLIANT } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected b/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected index 07229ff975..967621d71f 100644 --- a/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected +++ b/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected @@ -17,25 +17,35 @@ edges | test.c:4:5:4:6 | *g2 | test.c:68:23:68:24 | g2 | provenance | | | test.c:4:5:4:6 | *g2 | test.c:71:23:71:24 | g2 | provenance | | | test.c:4:10:4:29 | memory_order_relaxed | test.c:4:5:4:6 | *g2 | provenance | | +| test.c:4:10:4:29 | memory_order_relaxed | test.c:4:10:4:29 | memory_order_relaxed | provenance | | | test.c:5:5:5:6 | *g3 | test.c:72:23:72:24 | g3 | provenance | | | test.c:5:10:5:29 | memory_order_acquire | test.c:5:5:5:6 | *g3 | provenance | | +| test.c:5:10:5:29 | memory_order_acquire | test.c:5:10:5:29 | memory_order_acquire | provenance | | | test.c:6:5:6:6 | *g4 | test.c:73:23:73:24 | g4 | provenance | | | test.c:6:10:6:29 | memory_order_consume | test.c:6:5:6:6 | *g4 | provenance | | +| test.c:6:10:6:29 | memory_order_consume | test.c:6:10:6:29 | memory_order_consume | provenance | | | test.c:7:5:7:6 | *g5 | test.c:74:23:74:24 | g5 | provenance | | | test.c:7:10:7:29 | memory_order_acq_rel | test.c:7:5:7:6 | *g5 | provenance | | +| test.c:7:10:7:29 | memory_order_acq_rel | test.c:7:10:7:29 | memory_order_acq_rel | provenance | | | test.c:8:5:8:6 | *g6 | test.c:75:23:75:24 | g6 | provenance | | | test.c:8:10:8:29 | memory_order_release | test.c:8:5:8:6 | *g6 | provenance | | +| test.c:8:10:8:29 | memory_order_release | test.c:8:10:8:29 | memory_order_release | provenance | | nodes | test.c:4:5:4:6 | *g2 | semmle.label | *g2 | | test.c:4:10:4:29 | memory_order_relaxed | semmle.label | memory_order_relaxed | +| test.c:4:10:4:29 | memory_order_relaxed | semmle.label | memory_order_relaxed | | test.c:5:5:5:6 | *g3 | semmle.label | *g3 | | test.c:5:10:5:29 | memory_order_acquire | semmle.label | memory_order_acquire | +| test.c:5:10:5:29 | memory_order_acquire | semmle.label | memory_order_acquire | | test.c:6:5:6:6 | *g4 | semmle.label | *g4 | | test.c:6:10:6:29 | memory_order_consume | semmle.label | memory_order_consume | +| test.c:6:10:6:29 | memory_order_consume | semmle.label | memory_order_consume | | test.c:7:5:7:6 | *g5 | semmle.label | *g5 | | test.c:7:10:7:29 | memory_order_acq_rel | semmle.label | memory_order_acq_rel | +| test.c:7:10:7:29 | memory_order_acq_rel | semmle.label | memory_order_acq_rel | | test.c:8:5:8:6 | *g6 | semmle.label | *g6 | | test.c:8:10:8:29 | memory_order_release | semmle.label | memory_order_release | +| test.c:8:10:8:29 | memory_order_release | semmle.label | memory_order_release | | test.c:16:29:16:48 | memory_order_relaxed | semmle.label | memory_order_relaxed | | test.c:17:29:17:48 | memory_order_acquire | semmle.label | memory_order_acquire | | test.c:18:29:18:48 | memory_order_consume | semmle.label | memory_order_consume | @@ -62,10 +72,8 @@ nodes | test.c:73:23:73:24 | g4 | semmle.label | g4 | | test.c:74:23:74:24 | g5 | semmle.label | g5 | | test.c:75:23:75:24 | g6 | semmle.label | g6 | -| test.c:78:23:78:46 | ... * ... | semmle.label | ... * ... | | test.c:79:23:79:23 | 1 | semmle.label | 1 | | test.c:80:23:80:25 | 100 | semmle.label | 100 | -| test.c:81:23:81:28 | ... + ... | semmle.label | ... + ... | subpaths #select | test.c:16:29:16:48 | memory_order_relaxed | test.c:16:29:16:48 | memory_order_relaxed | test.c:16:29:16:48 | memory_order_relaxed | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_load | __c11_atomic_load | @@ -96,4 +104,3 @@ subpaths | test.c:75:23:75:24 | g6 | test.c:8:10:8:29 | memory_order_release | test.c:75:23:75:24 | g6 | Invalid memory order '$@' in call to function '$@'. | memory_order_release | memory_order_release | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | | test.c:79:23:79:23 | 1 | test.c:79:23:79:23 | 1 | test.c:79:23:79:23 | 1 | Invalid memory order '$@' in call to function '$@'. | memory_order_consume | memory_order_consume | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | | test.c:80:23:80:25 | 100 | test.c:80:23:80:25 | 100 | test.c:80:23:80:25 | 100 | Invalid memory order '$@' in call to function '$@'. | 100 | 100 | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | -| test.c:81:23:81:28 | ... + ... | test.c:81:23:81:28 | ... + ... | test.c:81:23:81:28 | ... + ... | Invalid memory order '$@' in call to function '$@'. | ... + ... | ... + ... | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | diff --git a/c/misra/test/rules/RULE-21-25/test.c b/c/misra/test/rules/RULE-21-25/test.c index 51df24555c..2e8c641032 100644 --- a/c/misra/test/rules/RULE-21-25/test.c +++ b/c/misra/test/rules/RULE-21-25/test.c @@ -78,7 +78,7 @@ void f(int p) { atomic_thread_fence(memory_order_seq_cst * 1); // COMPLIANT atomic_thread_fence(1); // NON-COMPLIANT atomic_thread_fence(100); // NON-COMPLIANT - atomic_thread_fence(g1 + 1); // NON-COMPLIANT + atomic_thread_fence(g1 + 1); // NON_COMPLIANT[FALSE_NEGATIVE] // No unsafe flow, currently accepted: atomic_thread_fence(p); // COMPLIANT From 763f4c1fa710055290a137c15ed8dc8290f7f10c Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 27 Jan 2025 16:06:01 -0800 Subject: [PATCH 161/370] Fix formatting --- c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql | 6 ++---- .../RULE-12-6/AtomicAggregateObjectDirectlyAccessed.ql | 7 ++++++- c/misra/test/rules/RULE-21-25/test.c | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql b/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql index 355b30808d..d780437141 100644 --- a/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql +++ b/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql @@ -22,9 +22,7 @@ import codingstandards.cpp.Concurrency class CThreadRoot extends Function { CThreadCreateCall threadCreate; - CThreadRoot() { - threadCreate.getFunction() = this - } + CThreadRoot() { threadCreate.getFunction() = this } /* Get a function which is reachable from this function */ Function getAReachableFunction() { calls*(result) } @@ -32,7 +30,7 @@ class CThreadRoot extends Function { CThreadCreateCall getCThreadCreateCall() { result = threadCreate } } - from CThreadCreateCall tc, CThreadRoot threadRoot +from CThreadCreateCall tc, CThreadRoot threadRoot where not isExcluded(tc, Concurrency6Package::threadCreatedByThreadQuery()) and tc.getEnclosingFunction() = threadRoot.getAReachableFunction() diff --git a/c/misra/src/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.ql b/c/misra/src/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.ql index 7478bb2787..5085e5dc7b 100644 --- a/c/misra/src/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.ql +++ b/c/misra/src/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.ql @@ -28,7 +28,12 @@ where or exists(PointerFieldAccess fa | expr = fa and - fa.getQualifier().getType().stripTopLevelSpecifiers().(PointerType).getBaseType().hasSpecifier("atomic") and + fa.getQualifier() + .getType() + .stripTopLevelSpecifiers() + .(PointerType) + .getBaseType() + .hasSpecifier("atomic") and field = fa.getTarget() ) ) diff --git a/c/misra/test/rules/RULE-21-25/test.c b/c/misra/test/rules/RULE-21-25/test.c index 2e8c641032..d1831785ba 100644 --- a/c/misra/test/rules/RULE-21-25/test.c +++ b/c/misra/test/rules/RULE-21-25/test.c @@ -78,7 +78,7 @@ void f(int p) { atomic_thread_fence(memory_order_seq_cst * 1); // COMPLIANT atomic_thread_fence(1); // NON-COMPLIANT atomic_thread_fence(100); // NON-COMPLIANT - atomic_thread_fence(g1 + 1); // NON_COMPLIANT[FALSE_NEGATIVE] + atomic_thread_fence(g1 + 1); // NON_COMPLIANT[FALSE_NEGATIVE] // No unsafe flow, currently accepted: atomic_thread_fence(p); // COMPLIANT From 1a2454165d16e8babd686b19727c6c7b6f77674b Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 28 Jan 2025 13:17:02 +0000 Subject: [PATCH 162/370] Deviations: Support C/C++ attributes This commit adds support for C/C++ attributes to specify deviations with code identifiers in the code. Attributes are inherited from parents, and support multiple code identifiers in a single definition. --- .../deviations/CodeIdentifierDeviation.qll | 49 +++++++++++++++++++ .../TypeLongDoubleUsed.expected | 4 ++ .../UnusedReturnValue.expected | 12 +++++ .../attribute_syntax.cpp | 44 +++++++++++++++++ docs/user_manual.md | 47 ++++++++++++++++-- 5 files changed, 151 insertions(+), 5 deletions(-) create mode 100644 cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll index 94587dca34..bd7100021a 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll @@ -177,6 +177,40 @@ private predicate isDeviationRangePaired( ) } +/** + * A standard attribute that either deviates a result. + */ +class DeviationAttribute extends StdAttribute { + DeviationRecord record; + + DeviationAttribute() { + this.hasQualifiedName("codingstandards", "deviation") and + // Support multiple argument deviations + "\"" + record.getCodeIdentifier() + "\"" = this.getAnArgument().getValueText() + } + + DeviationRecord getDeviationRecord() { result = record } + + pragma[nomagic] + Element getASuppressedElement() { + result.(Type).getAnAttribute() = this + or + result.(Stmt).getAnAttribute() = this + or + result.(Variable).getAnAttribute() = this + or + result.(Function).getAnAttribute() = this + or + result.(Expr).getEnclosingStmt() = this.getASuppressedElement() + or + result.(Stmt).getParentStmt() = this.getASuppressedElement() + or + result.(Stmt).getEnclosingFunction() = this.getASuppressedElement() + or + result.(LocalVariable) = this.getASuppressedElement().(DeclStmt).getADeclaration() + } +} + newtype TCodeIndentifierDeviation = TSingleLineDeviation(DeviationRecord record, Comment comment, string filepath, int suppressedLine) { ( @@ -195,6 +229,9 @@ newtype TCodeIndentifierDeviation = isDeviationRangePaired(record, beginComment, endComment) and beginComment.getLocation().hasLocationInfo(filepath, suppressedStartLine, _, _, _) and endComment.getLocation().hasLocationInfo(filepath, suppressedEndLine, _, _, _) + } or + TCodeIdentifierDeviation(DeviationRecord record, DeviationAttribute attribute) { + attribute.getDeviationRecord() = record } class CodeIdentifierDeviation extends TCodeIndentifierDeviation { @@ -203,6 +240,8 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation { this = TSingleLineDeviation(result, _, _, _) or this = TMultiLineDeviation(result, _, _, _, _, _) + or + this = TCodeIdentifierDeviation(result, _) } /** @@ -225,6 +264,11 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation { suppressedEndLine > elementLocationStart ) ) + or + exists(DeviationAttribute attribute | + this = TCodeIdentifierDeviation(_, attribute) and + attribute.getASuppressedElement() = e + ) } string toString() { @@ -243,5 +287,10 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation { suppressedStartLine + ":" + suppressedEndLine ) ) + or + exists(DeviationAttribute attribute | + this = TCodeIdentifierDeviation(_, attribute) and + result = "Deviation record " + getDeviationRecord() + " applied to " + attribute + ) } } diff --git a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected index a4e045edcf..99b3c89bfb 100644 --- a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected +++ b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected @@ -1,3 +1,7 @@ +| attribute_syntax.cpp:6:15:6:17 | dd1 | Use of long double type. | +| attribute_syntax.cpp:22:15:22:17 | d10 | Use of long double type. | +| attribute_syntax.cpp:30:15:30:17 | d14 | Use of long double type. | +| attribute_syntax.cpp:34:20:34:22 | d16 | Use of long double type. | | main.cpp:13:15:13:16 | d1 | Use of long double type. | | main.cpp:18:15:18:16 | d4 | Use of long double type. | | main.cpp:21:15:21:16 | d6 | Use of long double type. | diff --git a/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected b/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected index 7cc5d2e1ab..7538df2195 100644 --- a/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected +++ b/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected @@ -1,3 +1,15 @@ +| attribute_syntax.cpp:5:3:5:6 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | +| attribute_syntax.cpp:17:5:17:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | +| attribute_syntax.cpp:19:5:19:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | +| attribute_syntax.cpp:25:5:25:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | +| attribute_syntax.cpp:27:5:27:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | +| attribute_syntax.cpp:31:3:31:6 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | +| attribute_syntax.cpp:42:3:42:6 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | | main.cpp:12:3:12:6 | call to getX | Return value from call to $@ is unused. | main.cpp:8:5:8:8 | getX | getX | +| main.cpp:25:3:25:6 | call to getX | Return value from call to $@ is unused. | main.cpp:8:5:8:8 | getX | getX | +| main.cpp:27:3:27:6 | call to getX | Return value from call to $@ is unused. | main.cpp:8:5:8:8 | getX | getX | +| main.cpp:33:3:33:6 | call to getX | Return value from call to $@ is unused. | main.cpp:8:5:8:8 | getX | getX | +| main.cpp:35:3:35:6 | call to getX | Return value from call to $@ is unused. | main.cpp:8:5:8:8 | getX | getX | +| main.cpp:39:3:39:6 | call to getX | Return value from call to $@ is unused. | main.cpp:8:5:8:8 | getX | getX | | nested/nested3/test3.h:5:3:5:7 | call to getZ3 | Return value from call to $@ is unused. | nested/nested3/test3.h:1:5:1:9 | getZ3 | getZ3 | | nested/test.h:5:3:5:6 | call to getY | Return value from call to $@ is unused. | nested/test.h:1:5:1:8 | getY | getY | diff --git a/cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp b/cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp new file mode 100644 index 0000000000..97b4ba987d --- /dev/null +++ b/cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp @@ -0,0 +1,44 @@ +int getZ() { return 5; } + +int alt() { + int x = 0; // COMPLIANT[DEVIATED] + getZ(); // NON_COMPLIANT + long double dd1; // NON_COMPLIANT (A0-4-2) + + long double [[codingstandards::deviation( + "a-0-4-2-deviation")]] dd3; // COMPLIANT[DEVIATED] + long double [[codingstandards::deviation("a")]] dd3a; // NON_COMPLIAT + + [[codingstandards::deviation( + "a-0-4-2-deviation")]] long double dd4; // COMPLIANT[DEVIATED] + + [[codingstandards::deviation("a-0-4-2-deviation")]] { + long double d7; // COMPLIANT[DEVIATED] + getZ(); // NON_COMPLIANT (A0-1-2) + long double d8; // COMPLIANT[DEVIATED] + getZ(); // NON_COMPLIANT (A0-1-2) + long double d9; // COMPLIANT[DEVIATED] + } + long double d10; // NON_COMPLIANT (A0-4-2) + [[codingstandards::deviation("a-0-4-2-deviation")]] { + long double d11; // COMPLIANT[DEVIATED] + getZ(); // NON_COMPLIANT (A0-1-2) + long double d12; // COMPLIANT[DEVIATED] + getZ(); // NON_COMPLIANT (A0-1-2) + long double d13; // COMPLIANT[DEVIATED] + } + long double d14; // NON_COMPLIANT (A0-4-2) + getZ(); // NON_COMPLIANT (A0-1-2) + [[codingstandards::deviation("a-0-4-2-deviation")]] + for (long double d15 = 0.0; true;) {} // COMPLIANT[DEVIATED] + for (long double d16 = 0.0; true;) { // NON_COMPLIANT (A0-4-2) + } + return 0; +} + +[[codingstandards::deviation("a-0-4-2-deviation")]] +int alt2() { + int x = 0; // COMPLIANT[DEVIATED] + getZ(); // NON_COMPLIANT + long double dd1; // COMPLIANT[DEVIATED] +} \ No newline at end of file diff --git a/docs/user_manual.md b/docs/user_manual.md index a936118758..5d2236ed10 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -421,15 +421,50 @@ The `process_coding_standards_config.py` has a dependency on the package `pyyaml `pip3 install -r path/to/codeql-coding-standards/scripts/configuration/requirements.txt` -##### Deviation code identifiers +##### Deviation code identifier attributes -A code identifier specified in a deviation record can be applied to certain results in the code by adding a comment marker consisting of a `code-identifier` with some optional annotations. The supported marker annotation formats are: +A code identifier specified in a deviation record can be applied to certain results in the code by adding a C or C++ attribute of the following format: + +``` +[[codingstandards::deviation("code-identifier")]] +``` + +This attribute may be added to the following program elements: + * Functions + * Statements + * Variables + * Type declarations + +Deviation attributes are inherited from parents in the code structure. For example, a deviation attribute applied to a function will apply the deviation to all code within the function. Note: deviations are not inherited by lambda expressions. + +Multiple code identifiers may be passed in a single attribute to apply multiple deviations, for example: + +``` +[[codingstandards::deviation("code-identifier-1", "code-identifier-2")]] +``` + +Note - considation should be taken to ensure the use of custom attributes for deviations is compatible with your chosen language version, compiler, compiler configuration and coding standard. + +**Use of attributes in C Coding Standards**: The C Standard introduces attributes in C23, however some compilers support attributes as a language extension in prior versions. You should: + * Confirm that your compiler supports attributes for your chosen compiler configuration, if necessary as a language extension. + * Confirm that unknown attributes are ignored by the compiler. + * For MISRA C, add a project deviation against "Rule 1.2: Language extensions should not be used", if attribute support is a language extension in your language version. + +**Use of attributes in C++ Coding Standards**: The C++ Standard supports attributes in C++14, however the handling of unknown attributes is implementation defined. From C++17 onwards, unknown attributes are mandated to be ignored. Unknown attributes will usually raise an "unknown attribute" warning. You should: + * If using C++14, confirm that your compiler ignores unknown attributes. + * If using AUTOSAR and a compiler which produces warnings on unknown attributes, the compiler warning should be disabled (as per `A1-1-2: A warning level of the compilation process shall be set in compliance with project policies`), to ensure compliance with `A1-4-3: All code should compiler free of compiler warnings`. + +If you cannot satisfy these condition, please use the deviation code identifier comment format instead. + +##### Deviation code identifier comments + +As an alternative to attributes, a code identifier specified in a deviation record can be applied to certain results in the code by adding a comment marker consisting of a `code-identifier` with some optional annotations. The supported marker annotation formats are: - `` - the deviation applies to results on the current line. - `codingstandards::deviation()` - the deviation applies to results on the current line. - `codingstandards::deviation_next_line()` - this deviation applies to results on the next line. - - `DEVIATION_BEGIN()` - marks the beginning of a range of lines where the deviation applies. - - `DEVIATION_END()` - marks the end of a range of lines where the deviation applies. + - `codingstandards::deviation_begin()` - marks the beginning of a range of lines where the deviation applies. + - `codingstandards::deviation_end()` - marks the end of a range of lines where the deviation applies. Here are some examples, using the deviation record with the `a-0-4-2-deviation` code-identifier specified above: ```cpp @@ -465,7 +500,9 @@ A `codingstandards::deviation_end` without a matching `codingstandards::deviatio `codingstandards::deviation_begin` and `codingstandards::deviation_end` markers only apply within a single file. Markers cannot be paired across files, and deviations do not apply to included files. -##### Deviation permit +Note: deviation markers cannot be applied to the body of a macro. Please apply the deviation to macro expansion, or use the attribute deviation format. + +##### Deviation permits The current implementation supports _deviation permits_ as described in the [MISRA Compliance:2020](https://www.misra.org.uk/app/uploads/2021/06/MISRA-Compliance-2020.pdf) section _4.3 Deviation permits_. From 5ad258842d90afd1d10ca1ef3b1227f518ebca45 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 28 Jan 2025 10:30:15 -0800 Subject: [PATCH 163/370] fix test --- .../rules/DIR-5-3/ThreadCreatedByThread.ql | 4 +- .../DIR-5-3/ThreadCreatedByThread.expected | 28 +++++++------- c/misra/test/rules/DIR-5-3/test.c | 38 ++++++++++--------- 3 files changed, 36 insertions(+), 34 deletions(-) diff --git a/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql b/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql index d780437141..207e763fa7 100644 --- a/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql +++ b/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql @@ -27,7 +27,7 @@ class CThreadRoot extends Function { /* Get a function which is reachable from this function */ Function getAReachableFunction() { calls*(result) } - CThreadCreateCall getCThreadCreateCall() { result = threadCreate } + CThreadCreateCall getACThreadCreateCall() { result = threadCreate } } from CThreadCreateCall tc, CThreadRoot threadRoot @@ -35,4 +35,4 @@ where not isExcluded(tc, Concurrency6Package::threadCreatedByThreadQuery()) and tc.getEnclosingFunction() = threadRoot.getAReachableFunction() select tc, "Thread creation call reachable from function '$@', which may also be $@.", threadRoot, - threadRoot.toString(), threadRoot.getCThreadCreateCall(), "started as a thread" + threadRoot.toString(), threadRoot.getACThreadCreateCall(), "started as a thread" diff --git a/c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.expected b/c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.expected index 5b73fd97aa..b8dc2bfe4b 100644 --- a/c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.expected +++ b/c/misra/test/rules/DIR-5-3/ThreadCreatedByThread.expected @@ -1,14 +1,14 @@ -| test.c:47:3:47:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | -| test.c:48:3:48:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | -| test.c:56:3:56:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | -| test.c:57:3:57:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | -| test.c:65:3:65:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | -| test.c:66:3:66:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | -| test.c:74:3:74:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | -| test.c:74:3:74:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | -| test.c:75:3:75:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | -| test.c:75:3:75:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | -| test.c:79:3:79:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | -| test.c:79:3:79:13 | call to thrd_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | -| test.c:80:3:80:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | -| test.c:80:3:80:16 | call to pthread_create | Thread creation call reachable from threaded function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | +| test.c:49:3:49:13 | call to thrd_create | Thread creation call reachable from function '$@', which may also be $@. | test.c:48:7:48:18 | pthread_func | pthread_func | test.c:19:3:19:16 | call to pthread_create | started as a thread | +| test.c:50:3:50:16 | call to pthread_create | Thread creation call reachable from function '$@', which may also be $@. | test.c:48:7:48:18 | pthread_func | pthread_func | test.c:19:3:19:16 | call to pthread_create | started as a thread | +| test.c:58:3:58:13 | call to thrd_create | Thread creation call reachable from function '$@', which may also be $@. | test.c:57:5:57:13 | thrd_func | thrd_func | test.c:18:3:18:13 | call to thrd_create | started as a thread | +| test.c:59:3:59:16 | call to pthread_create | Thread creation call reachable from function '$@', which may also be $@. | test.c:57:5:57:13 | thrd_func | thrd_func | test.c:18:3:18:13 | call to thrd_create | started as a thread | +| test.c:67:3:67:13 | call to thrd_create | Thread creation call reachable from function '$@', which may also be $@. | test.c:57:5:57:13 | thrd_func | thrd_func | test.c:18:3:18:13 | call to thrd_create | started as a thread | +| test.c:68:3:68:16 | call to pthread_create | Thread creation call reachable from function '$@', which may also be $@. | test.c:57:5:57:13 | thrd_func | thrd_func | test.c:18:3:18:13 | call to thrd_create | started as a thread | +| test.c:76:3:76:13 | call to thrd_create | Thread creation call reachable from function '$@', which may also be $@. | test.c:48:7:48:18 | pthread_func | pthread_func | test.c:19:3:19:16 | call to pthread_create | started as a thread | +| test.c:76:3:76:13 | call to thrd_create | Thread creation call reachable from function '$@', which may also be $@. | test.c:57:5:57:13 | thrd_func | thrd_func | test.c:18:3:18:13 | call to thrd_create | started as a thread | +| test.c:77:3:77:16 | call to pthread_create | Thread creation call reachable from function '$@', which may also be $@. | test.c:48:7:48:18 | pthread_func | pthread_func | test.c:19:3:19:16 | call to pthread_create | started as a thread | +| test.c:77:3:77:16 | call to pthread_create | Thread creation call reachable from function '$@', which may also be $@. | test.c:57:5:57:13 | thrd_func | thrd_func | test.c:18:3:18:13 | call to thrd_create | started as a thread | +| test.c:81:3:81:13 | call to thrd_create | Thread creation call reachable from function '$@', which may also be $@. | test.c:48:7:48:18 | pthread_func | pthread_func | test.c:19:3:19:16 | call to pthread_create | started as a thread | +| test.c:81:3:81:13 | call to thrd_create | Thread creation call reachable from function '$@', which may also be $@. | test.c:57:5:57:13 | thrd_func | thrd_func | test.c:18:3:18:13 | call to thrd_create | started as a thread | +| test.c:82:3:82:16 | call to pthread_create | Thread creation call reachable from function '$@', which may also be $@. | test.c:48:7:48:18 | pthread_func | pthread_func | test.c:19:3:19:16 | call to pthread_create | started as a thread | +| test.c:82:3:82:16 | call to pthread_create | Thread creation call reachable from function '$@', which may also be $@. | test.c:57:5:57:13 | thrd_func | thrd_func | test.c:18:3:18:13 | call to thrd_create | started as a thread | diff --git a/c/misra/test/rules/DIR-5-3/test.c b/c/misra/test/rules/DIR-5-3/test.c index 24e03d9a33..ebdf53cfb4 100644 --- a/c/misra/test/rules/DIR-5-3/test.c +++ b/c/misra/test/rules/DIR-5-3/test.c @@ -5,7 +5,9 @@ thrd_t g1; // COMPLIANT pthread_t g2; // COMPLIANT void *pthread_func(void *arg); +void *pthread_func_inner(void *arg); int thrd_func(void *arg); +int thrd_func_inner(void *arg); void make_threads_called_from_main(void); void func_called_from_main(void); @@ -16,8 +18,8 @@ void main() { thrd_create(&g1, &thrd_func, NULL); // COMPLIANT pthread_create(&g2, NULL, &pthread_func, NULL); // COMPLIANT - thrd_create(&g1, &thrd_func, NULL); // COMPLIANT - pthread_create(&g2, NULL, &pthread_func, NULL); // COMPLIANT + thrd_create(&g1, &thrd_func_inner, NULL); // COMPLIANT + pthread_create(&g2, NULL, &pthread_func_inner, NULL); // COMPLIANT make_threads_called_from_main(); func_called_from_main(); @@ -25,8 +27,8 @@ void main() { } void make_threads_called_from_main() { - thrd_create(&g1, &thrd_func, NULL); // COMPLIANT - pthread_create(&g2, NULL, &pthread_func, NULL); // COMPLIANT + thrd_create(&g1, &thrd_func_inner, NULL); // COMPLIANT + pthread_create(&g2, NULL, &pthread_func_inner, NULL); // COMPLIANT } void func_called_from_main() { @@ -34,8 +36,8 @@ void func_called_from_main() { } void make_threads_called_from_func_called_from_main() { - thrd_create(&g1, &thrd_func, NULL); // COMPLIANT - pthread_create(&g2, NULL, &pthread_func, NULL); // COMPLIANT + thrd_create(&g1, &thrd_func_inner, NULL); // COMPLIANT + pthread_create(&g2, NULL, &pthread_func_inner, NULL); // COMPLIANT } void make_threads_called_from_pthread_func(void); @@ -44,8 +46,8 @@ void func_called_from_pthread_thrd(void); void make_threads_called_from_func_called_from_pthread_thrd(void); void *pthread_func(void *arg) { - thrd_create(&g1, &thrd_func, NULL); // NON-COMPLIANT - pthread_create(&g2, NULL, &pthread_func, NULL); // NON-COMPLIANT + thrd_create(&g1, &thrd_func_inner, NULL); // NON-COMPLIANT + pthread_create(&g2, NULL, &pthread_func_inner, NULL); // NON-COMPLIANT make_threads_called_from_pthread_func(); func_called_from_pthread_thrd(); @@ -53,8 +55,8 @@ void *pthread_func(void *arg) { } int thrd_func(void *arg) { - thrd_create(&g1, &thrd_func, NULL); // NON-COMPLIANT - pthread_create(&g2, NULL, &pthread_func, NULL); // NON-COMPLIANT + thrd_create(&g1, &thrd_func_inner, NULL); // NON-COMPLIANT + pthread_create(&g2, NULL, &pthread_func_inner, NULL); // NON-COMPLIANT make_threads_called_from_thrd_func(); func_called_from_pthread_thrd(); @@ -62,8 +64,8 @@ int thrd_func(void *arg) { } void make_threads_called_from_thrd_func(void) { - thrd_create(&g1, &thrd_func, NULL); // NON-COMPLIANT - pthread_create(&g2, NULL, &pthread_func, NULL); // NON-COMPLIANT + thrd_create(&g1, &thrd_func_inner, NULL); // NON-COMPLIANT + pthread_create(&g2, NULL, &pthread_func_inner, NULL); // NON-COMPLIANT } void func_called_from_pthread_thrd(void) { @@ -71,16 +73,16 @@ void func_called_from_pthread_thrd(void) { } void make_threads_called_from_func_called_from_pthread_thrd(void) { - thrd_create(&g1, &thrd_func, NULL); // NON-COMPLIANT - pthread_create(&g2, NULL, &pthread_func, NULL); // NON-COMPLIANT + thrd_create(&g1, &thrd_func_inner, NULL); // NON-COMPLIANT + pthread_create(&g2, NULL, &pthread_func_inner, NULL); // NON-COMPLIANT } void make_threads_called_from_main_pthread_thrd() { - thrd_create(&g1, &thrd_func, NULL); // NON-COMPLIANT - pthread_create(&g2, NULL, &pthread_func, NULL); // NON-COMPLIANT + thrd_create(&g1, &thrd_func_inner, NULL); // NON-COMPLIANT + pthread_create(&g2, NULL, &pthread_func_inner, NULL); // NON-COMPLIANT } void make_threads_not_called_by_anyone() { - thrd_create(&g1, &thrd_func, NULL); // COMPLIANT - pthread_create(&g2, NULL, &pthread_func, NULL); // COMPLIANT + thrd_create(&g1, &thrd_func_inner, NULL); // COMPLIANT + pthread_create(&g2, NULL, &pthread_func_inner, NULL); // COMPLIANT } From 22e4fd3e0775f3aa17ee57c199b73cf5bd72f8f4 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 28 Jan 2025 14:07:32 -0800 Subject: [PATCH 164/370] fix test affected by changes in test.c --- .../BannedDynamicThreadCreation.expected | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.expected b/c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.expected index fa12a62f41..3bc3ab579a 100644 --- a/c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.expected +++ b/c/misra/test/rules/DIR-5-3/BannedDynamicThreadCreation.expected @@ -1,16 +1,16 @@ -| test.c:28:3:28:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:27:6:27:34 | make_threads_called_from_main | make_threads_called_from_main | -| test.c:29:3:29:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:27:6:27:34 | make_threads_called_from_main | make_threads_called_from_main | -| test.c:37:3:37:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:36:6:36:51 | make_threads_called_from_func_called_from_main | make_threads_called_from_func_called_from_main | -| test.c:38:3:38:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:36:6:36:51 | make_threads_called_from_func_called_from_main | make_threads_called_from_func_called_from_main | -| test.c:47:3:47:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | -| test.c:48:3:48:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:46:7:46:18 | pthread_func | pthread_func | -| test.c:56:3:56:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | -| test.c:57:3:57:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:55:5:55:13 | thrd_func | thrd_func | -| test.c:65:3:65:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:64:6:64:39 | make_threads_called_from_thrd_func | make_threads_called_from_thrd_func | -| test.c:66:3:66:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:64:6:64:39 | make_threads_called_from_thrd_func | make_threads_called_from_thrd_func | -| test.c:74:3:74:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:73:6:73:59 | make_threads_called_from_func_called_from_pthread_thrd | make_threads_called_from_func_called_from_pthread_thrd | -| test.c:75:3:75:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:73:6:73:59 | make_threads_called_from_func_called_from_pthread_thrd | make_threads_called_from_func_called_from_pthread_thrd | -| test.c:79:3:79:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:78:6:78:47 | make_threads_called_from_main_pthread_thrd | make_threads_called_from_main_pthread_thrd | -| test.c:80:3:80:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:78:6:78:47 | make_threads_called_from_main_pthread_thrd | make_threads_called_from_main_pthread_thrd | -| test.c:84:3:84:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:83:6:83:38 | make_threads_not_called_by_anyone | make_threads_not_called_by_anyone | -| test.c:85:3:85:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:83:6:83:38 | make_threads_not_called_by_anyone | make_threads_not_called_by_anyone | +| test.c:30:3:30:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:29:6:29:34 | make_threads_called_from_main | make_threads_called_from_main | +| test.c:31:3:31:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:29:6:29:34 | make_threads_called_from_main | make_threads_called_from_main | +| test.c:39:3:39:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:38:6:38:51 | make_threads_called_from_func_called_from_main | make_threads_called_from_func_called_from_main | +| test.c:40:3:40:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:38:6:38:51 | make_threads_called_from_func_called_from_main | make_threads_called_from_func_called_from_main | +| test.c:49:3:49:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:48:7:48:18 | pthread_func | pthread_func | +| test.c:50:3:50:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:48:7:48:18 | pthread_func | pthread_func | +| test.c:58:3:58:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:57:5:57:13 | thrd_func | thrd_func | +| test.c:59:3:59:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:57:5:57:13 | thrd_func | thrd_func | +| test.c:67:3:67:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:66:6:66:39 | make_threads_called_from_thrd_func | make_threads_called_from_thrd_func | +| test.c:68:3:68:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:66:6:66:39 | make_threads_called_from_thrd_func | make_threads_called_from_thrd_func | +| test.c:76:3:76:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:75:6:75:59 | make_threads_called_from_func_called_from_pthread_thrd | make_threads_called_from_func_called_from_pthread_thrd | +| test.c:77:3:77:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:75:6:75:59 | make_threads_called_from_func_called_from_pthread_thrd | make_threads_called_from_func_called_from_pthread_thrd | +| test.c:81:3:81:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:80:6:80:47 | make_threads_called_from_main_pthread_thrd | make_threads_called_from_main_pthread_thrd | +| test.c:82:3:82:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:80:6:80:47 | make_threads_called_from_main_pthread_thrd | make_threads_called_from_main_pthread_thrd | +| test.c:86:3:86:13 | call to thrd_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:85:6:85:38 | make_threads_not_called_by_anyone | make_threads_not_called_by_anyone | +| test.c:87:3:87:16 | call to pthread_create | Possible dynamic creation of thread outside initialization in function '$@'. | test.c:85:6:85:38 | make_threads_not_called_by_anyone | make_threads_not_called_by_anyone | From 93a773c00482a8b25d933759830cdda8684212c9 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 28 Jan 2025 19:51:11 -0800 Subject: [PATCH 165/370] Add comments where intention was unclear --- .../CON34-C/AppropriateThreadObjectStorageDurations.ql | 6 +++++- c/common/src/codingstandards/c/Objects.qll | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql index 5a1dd3c461..4115a801e6 100644 --- a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql +++ b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql @@ -39,7 +39,11 @@ where ) ) or - // TODO: Remove/replace with tss_t type check, see #801. + // TODO: This case is handling threadlocals in a useful way that's not intended to be covered + // by the rule. See issue #801. The actual rule should expect no tss_t objects is used, and + // this check that this is initialized doesn't seem to belong here. However, it is a useful + // check in and of itself, so we should figure out if this is part of an optional rule we + // haven't yet implemented and move this behavior there. exists(TSSGetFunctionCall tsg | TaintTracking::localTaint(DataFlow::exprNode(tsg), DataFlow::exprNode(arg)) and not exists(TSSSetFunctionCall tss, DataFlow::Node src | diff --git a/c/common/src/codingstandards/c/Objects.qll b/c/common/src/codingstandards/c/Objects.qll index 105291c688..9a0206771b 100644 --- a/c/common/src/codingstandards/c/Objects.qll +++ b/c/common/src/codingstandards/c/Objects.qll @@ -106,9 +106,14 @@ abstract class ObjectIdentityBase extends Element { exists(Expr subobject | subobject = getASubobjectAccess() and ( + // Holds for address-of expressions. result = any(AddressOfExpr e | e.getOperand() = subobject) or + // Holds for array-to-pointer conversions, which evaluate to a usable subobject address. exists(ArrayToPointerConversion c | c.getExpr() = subobject) and + // Note that `arr[x]` has an array-to-pointer conversion, and returns the `x`th item by + // value, not the address of the `x`th item. Therefore, exclude `arr` if `arr` is part of + // an expression `arr[x]`. not exists(ArrayExpr a | a.getArrayBase() = subobject) and result = subobject ) From 22f95addf5d7fcfbcc850480b266fb8577c01459 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Wed, 29 Jan 2025 11:12:40 +0000 Subject: [PATCH 166/370] Add deviation file --- cpp/autosar/test/rules/A15-4-4/coding-standards.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 cpp/autosar/test/rules/A15-4-4/coding-standards.xml diff --git a/cpp/autosar/test/rules/A15-4-4/coding-standards.xml b/cpp/autosar/test/rules/A15-4-4/coding-standards.xml new file mode 100644 index 0000000000..6ae9c299fa --- /dev/null +++ b/cpp/autosar/test/rules/A15-4-4/coding-standards.xml @@ -0,0 +1,11 @@ + + + + + + A15-4-4 + Suppress entry. + a-15-4-4-deviation + + + From d307ab3db791b689f6664ff6bc33d4b1a84efeda Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 29 Jan 2025 12:41:31 -0800 Subject: [PATCH 167/370] Fix DataFlow imports --- .../AppropriateStorageDurationsFunctionReturn.ql | 1 + .../AppropriateStorageDurationsFunctionReturn.expected | 10 +++++----- .../cpp/resources/ResourceLeakAnalysis.qll | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql b/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql index 773d71acca..e4f5341014 100644 --- a/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql +++ b/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql @@ -14,6 +14,7 @@ import cpp import codingstandards.c.cert import codingstandards.c.Objects +import semmle.code.cpp.dataflow.DataFlow class Source extends Expr { ObjectIdentity rootObject; diff --git a/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected b/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected index 905c9cc22b..f60689dbb1 100644 --- a/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected +++ b/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected @@ -1,7 +1,7 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:22,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:26,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:39,6-14) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:39,26-34) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:45,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:28,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:32,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:45,6-14) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:45,26-34) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:51,3-11) | test.c:3:10:3:10 | a | $@ with automatic storage may be accessible outside of its lifetime. | test.c:3:10:3:10 | a | a | | test.c:15:4:15:8 | param [inner post update] | $@ with automatic storage may be accessible outside of its lifetime. | test.c:15:12:15:13 | a2 | a2 | diff --git a/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll b/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll index 2f932870b3..7d767b5cb4 100644 --- a/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll +++ b/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll @@ -1,5 +1,5 @@ import cpp -import codingstandards.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.valuenumbering.GlobalValueNumbering import semmle.code.cpp.controlflow.Dominance import codeql.util.Boolean From 127c6045f10de0895116dc17ee22107780291eac Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 29 Jan 2025 13:07:47 -0800 Subject: [PATCH 168/370] Address feedback --- ...1-29-implement-misra-clarifications-change-categories.md | 6 ++++++ rules.csv | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 change_notes/2025-01-29-implement-misra-clarifications-change-categories.md diff --git a/change_notes/2025-01-29-implement-misra-clarifications-change-categories.md b/change_notes/2025-01-29-implement-misra-clarifications-change-categories.md new file mode 100644 index 0000000000..04ef636392 --- /dev/null +++ b/change_notes/2025-01-29-implement-misra-clarifications-change-categories.md @@ -0,0 +1,6 @@ + - `RULE-13-6` - `SizeofOperandWithSideEffect.ql`: + - Changed from Mandatory to Required in implementation of Technical Corrigenda 2. + - `RULE-17-5` - `ArrayFunctionArgumentNumberOfElements.ql`: + - Changed from Advisory to Required in implementation of Technical Corrigenda 2. + - `RULE-21-11` - `StandardHeaderFileTgmathhUsed.ql`: + - Changed from Required to Advisory in implementation of Amendment 3. \ No newline at end of file diff --git a/rules.csv b/rules.csv index 475ea1d66c..ec3f80dab3 100644 --- a/rules.csv +++ b/rules.csv @@ -708,7 +708,7 @@ c,MISRA-C-2012,RULE-13-2,Yes,Required,,,The value of an expression and its persi c,MISRA-C-2012,RULE-13-3,Yes,Advisory,,,A full expression containing an increment (++) or decrement (--) operator should have no other potential side effects other than that caused by the increment or decrement operator,,SideEffects2,Medium, c,MISRA-C-2012,RULE-13-4,Yes,Advisory,,,The result of an assignment operator should not be used,M6-2-1,SideEffects1,Easy, c,MISRA-C-2012,RULE-13-5,Yes,Required,,,The right hand operand of a logical && or || operator shall not contain persistent side effects,M5-14-1,SideEffects1,Import, -c,MISRA-C-2012,RULE-13-6,Yes,Mandatory,,,The operand of the sizeof operator shall not contain any expressiosn which has potential side effects,M5-3-4,SideEffects1,Import, +c,MISRA-C-2012,RULE-13-6,Yes,Required,,,The operand of the sizeof operator shall not contain any expressiosn which has potential side effects,M5-3-4,SideEffects1,Import, c,MISRA-C-2012,RULE-14-1,Yes,Required,,,A loop counter shall not have essentially floating type,FLP30-C A6-5-2,EssentialTypes,Hard, c,MISRA-C-2012,RULE-14-2,Yes,Required,,,A for loop shall be well-formed,M6-5-1...M6-5-6,Statements4,Medium, c,MISRA-C-2012,RULE-14-3,Yes,Required,,,Controlling expressions shall not be invariant,,Statements5,Medium, @@ -731,7 +731,7 @@ c,MISRA-C-2012,RULE-17-1,Yes,Required,,,The features of shall not be c,MISRA-C-2012,RULE-17-2,Yes,Required,,,"Functions shall not call themselves, either directly or indirectly",A7-5-2,Statements3,Import, c,MISRA-C-2012,RULE-17-3,Yes,Mandatory,,,A function shall not be declared implicitly,,Declarations6,Medium, c,MISRA-C-2012,RULE-17-4,Yes,Mandatory,,,All exit paths from a function with non-void return type shall have an explicit return statement with an expression,MSC52-CPP,Statements5,Medium, -c,MISRA-C-2012,RULE-17-5,Yes,Advisory,,,The function argument corresponding to a parameter declared to have an array type shall have an appropriate number of elements,,Contracts6,Hard, +c,MISRA-C-2012,RULE-17-5,Yes,Required,,,The function argument corresponding to a parameter declared to have an array type shall have an appropriate number of elements,,Contracts6,Hard, c,MISRA-C-2012,RULE-17-6,Yes,Mandatory,,,The declaration of an array parameter shall not contain the static keyword between the [ ],,Static,Easy, c,MISRA-C-2012,RULE-17-7,Yes,Required,,,The value returned by a function having non-void return type shall be used,A0-1-2,Contracts6,Easy, c,MISRA-C-2012,RULE-17-8,Yes,Advisory,,,A function parameter should not be modified,,SideEffects2,Medium, @@ -776,7 +776,7 @@ c,MISRA-C-2012,RULE-21-7,Yes,Required,,,"The Standard Library functions atof, at c,MISRA-C-2012,RULE-21-8,Yes,Required,,,The Standard Library termination functions of shall not be used,ERR50-CPP,Banned,Easy, c,MISRA-C-2012,RULE-21-9,Yes,Required,,,The Standard Library functions bsearch and qsort of shall not be used,,Banned,Easy, c,MISRA-C-2012,RULE-21-10,Yes,Required,,,The Standard Library time and date functions shall not be used,,Banned,Easy, -c,MISRA-C-2012,RULE-21-11,Yes,Required,,,The standard header file shall not be used,,Banned,Easy, +c,MISRA-C-2012,RULE-21-11,Yes,Advisory,,,The standard header file shall not be used,,Banned,Easy, c,MISRA-C-2012,RULE-21-12,Yes,Advisory,,,The exception handling features of should not be used,,Banned,Easy, c,MISRA-C-2012,RULE-21-13,Yes,Mandatory,,,Any value passed to a function in shall be representable as an unsigned char or be the value EOF,,StandardLibraryFunctionTypes,Medium, c,MISRA-C-2012,RULE-21-14,Yes,Required,,,The Standard Library function memcmp shall not be used to compare null terminated strings,,EssentialTypes,Hard, From 963ba5c41638ad33cc548f7ad2e3a1ade5463a1b Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 29 Jan 2025 15:59:33 -0800 Subject: [PATCH 169/370] Fix broken test expectation --- .../rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.expected | 2 ++ 1 file changed, 2 insertions(+) diff --git a/c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.expected b/c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.expected index 126e75bca7..dbee52ed58 100644 --- a/c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.expected +++ b/c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.expected @@ -1,3 +1,5 @@ +WARNING: module 'DataFlow' has been deprecated and may be removed in future (MutexObjectsNotAlwaysUnlocked.ql:22,52-60) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (MutexObjectsNotAlwaysUnlocked.ql:30,42-50) | test.c:16:3:16:10 | call to mtx_lock | Mutex 'm' is locked here and may not always be subsequently unlocked. | | test.c:21:3:21:10 | call to mtx_lock | Mutex 'm' is locked here and may not always be subsequently unlocked. | | test.c:39:3:39:10 | call to mtx_lock | Mutex 'm' is locked here and may not always be subsequently unlocked. | From a26959808c685f011b7356bafc778562b8e1dddb Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 29 Jan 2025 18:48:02 -0800 Subject: [PATCH 170/370] Fix another set of test expectations --- ...riateThreadObjectStorageDurations.expected | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected b/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected index 25cb74d7fa..085083228b 100644 --- a/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected +++ b/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected @@ -1,11 +1,16 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:28,29-37) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:28,54-62) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:35,62-70) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:40,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:40,30-38) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:41,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:41,30-38) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:28,3-16) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:31,14-22) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:33,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:35,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:38,45-53) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:48,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:48,58-66) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:49,42-50) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:52,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:52,34-42) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:53,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:53,34-42) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:38,9-22) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:48,7-20) | test.c:23:3:23:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:23:24:23:29 | & ... | Shared object | | test.c:74:3:74:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:74:24:74:24 | p | Shared object | | test.c:85:3:85:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:85:24:85:24 | p | Shared object | From 3a20ccca17259b3a5597f637cd9cce5156f5bd75 Mon Sep 17 00:00:00 2001 From: Luke Cartey <5377966+lcartey@users.noreply.github.com> Date: Thu, 30 Jan 2025 22:43:18 +0000 Subject: [PATCH 171/370] Update cpp/autosar/test/rules/A7-1-1/test.cpp --- cpp/autosar/test/rules/A7-1-1/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/autosar/test/rules/A7-1-1/test.cpp b/cpp/autosar/test/rules/A7-1-1/test.cpp index 5e47b9c0bf..1fdc0d66eb 100644 --- a/cpp/autosar/test/rules/A7-1-1/test.cpp +++ b/cpp/autosar/test/rules/A7-1-1/test.cpp @@ -90,7 +90,7 @@ void fp_621() { recurse_var; } void variadic_forwarding() {} template -void variadic_forwarding(T &&first, Args &&... rest) { +void variadic_forwarding(T &&first, Args &&...rest) { first; variadic_forwarding(std::forward(rest)...); } From 638c083b3b55c790a3b588d9bc70ba02a0ced449 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 29 Oct 2024 14:48:44 -0700 Subject: [PATCH 172/370] save work for draft PR --- .../PossibleMisuseOfUndetectedInfinity.ql | 104 + .../DIR-4-15/PossibleMisuseOfUndetectedNaN.ql | 157 ++ .../PossibleUndetectedNaNorInfinity.ql | 223 ++ ...ossibleMisuseOfUndetectedInfinity.expected | 48 + .../PossibleMisuseOfUndetectedInfinity.qlref | 1 + .../PossibleMisuseOfUndetectedNaN.expected | 63 + .../PossibleMisuseOfUndetectedNaN.qlref | 1 + .../PossibleUndetectedNaNorInfinity.expected | 1 + .../PossibleUndetectedNaNorInfinity.qlref | 1 + c/misra/test/rules/DIR-4-15/test.c | 76 + .../src/codingstandards/cpp/FloatingPoint.qll | 61 + .../cpp/RestrictedRangeAnalysis.qll | 1903 +++++++++++++++++ .../cpp/SimpleRangeAnalysisCustomizations.qll | 39 + .../cpp/exclusions/c/FloatingTypes2.qll | 44 + .../cpp/exclusions/c/RuleMetadata.qll | 3 + rule_packages/c/FloatingTypes2.json | 36 + 16 files changed, 2761 insertions(+) create mode 100644 c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql create mode 100644 c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql create mode 100644 c/misra/src/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.ql create mode 100644 c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected create mode 100644 c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.qlref create mode 100644 c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected create mode 100644 c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.qlref create mode 100644 c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.expected create mode 100644 c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.qlref create mode 100644 c/misra/test/rules/DIR-4-15/test.c create mode 100644 cpp/common/src/codingstandards/cpp/FloatingPoint.qll create mode 100644 cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/c/FloatingTypes2.qll create mode 100644 rule_packages/c/FloatingTypes2.json diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql new file mode 100644 index 0000000000..84a3fbfd3c --- /dev/null +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql @@ -0,0 +1,104 @@ +/** + * @id c/misra/possible-misuse-of-undetected-infinity + * @name DIR-4-15: Evaluation of floating-point expressions shall not lead to the undetected generation of infinities + * @description Evaluation of floating-point expressions shall not lead to the undetected generation + * of infinities. + * @kind path-problem + * @precision high + * @problem.severity error + * @tags external/misra/id/dir-4-15 + * correctness + * external/misra/c/2012/amendment3 + * external/misra/obligation/required + */ + +import cpp +import codeql.util.Boolean +import codingstandards.c.misra +import codingstandards.cpp.RestrictedRangeAnalysis +import codingstandards.cpp.FloatingPoint +import codingstandards.cpp.AlertReporting +import semmle.code.cpp.controlflow.Guards +import semmle.code.cpp.dataflow.new.DataFlow +import semmle.code.cpp.dataflow.new.TaintTracking +import semmle.code.cpp.controlflow.Dominance + +module InvalidInfinityUsage implements DataFlow::ConfigSig { + /** + * An operation which does not have Infinity as an input, but may produce Infinity, according + * to the `RestrictedRangeAnalysis` module. + */ + predicate isSource(DataFlow::Node node) { + potentialSource(node) and + not exists(DataFlow::Node prior | + isAdditionalFlowStep(prior, node) and + potentialSource(prior) + ) + } + + /** + * An operation which may produce Infinity acconding to the `RestrictedRangeAnalysis` module. + */ + additional predicate potentialSource(DataFlow::Node node) { + node.asExpr() instanceof Operation and + exprMayEqualInfinity(node.asExpr(), _) + } + + /** + * An additional flow step to handle operations which propagate Infinity. + * + * This double checks that an Infinity may propagate by checking the `RestrictedRangeAnalysis` + * value estimate. This is conservative, since `RestrictedRangeAnalysis` is performed locally + * in scope with unanalyzable values in a finite range. However, this conservative approach + * leverages analysis of guards and other local conditions to avoid false positives. + */ + predicate isAdditionalFlowStep(DataFlow::Node source, DataFlow::Node sink) { + exists(Operation o | + o.getAnOperand() = source.asExpr() and + o = sink.asExpr() and + potentialSource(sink) + ) + } + + predicate isSink(DataFlow::Node node) { + ( + // Require that range analysis finds this value potentially infinite, to avoid false positives + // in the presence of guards. This may induce false negatives. + exprMayEqualInfinity(node.asExpr(), _) or + // Unanalyzable expressions are not checked against range analysis, which assumes a finite + // range. + not RestrictedRangeAnalysis::analyzableExpr(node.asExpr()) + ) and + ( + // Case 2: NaNs and infinities shall not be cast to integers + exists(Conversion c | + node.asExpr() = c.getUnconverted() and + c.getExpr().getType() instanceof FloatingPointType and + c.getType() instanceof IntegralType + ) + or + // Case 3: Infinities shall not underflow or otherwise produce finite values + exists(BinaryOperation op | + node.asExpr() = op.getRightOperand() and + op.getOperator() = ["/", "%"] + ) + ) + } +} + +module InvalidInfinityFlow = DataFlow::Global; + +import InvalidInfinityFlow::PathGraph + +from + Element elem, InvalidInfinityFlow::PathNode source, InvalidInfinityFlow::PathNode sink, + string msg, string sourceString +where + elem = MacroUnwrapper::unwrapElement(sink.getNode().asExpr()) and + not isExcluded(elem, FloatingTypes2Package::possibleMisuseOfUndetectedInfinityQuery()) and + ( + InvalidInfinityFlow::flow(source.getNode(), sink.getNode()) and + msg = "Invalid usage of possible $@." and + sourceString = "infinity" + ) +select elem, source, sink, msg, source, sourceString diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql new file mode 100644 index 0000000000..6962a1c36d --- /dev/null +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql @@ -0,0 +1,157 @@ +/** + * @id c/misra/possible-misuse-of-undetected-na-n + * @name DIR-4-15: Evaluation of floating-point expressions shall not lead to the undetected generation of NaNs + * @description Evaluation of floating-point expressions shall not lead to the undetected generation + * of NaNs. + * @kind path-problem + * @precision high + * @problem.severity error + * @tags external/misra/id/dir-4-15 + * correctness + * external/misra/c/2012/amendment3 + * external/misra/obligation/required + */ + +import cpp +import codeql.util.Boolean +import codingstandards.c.misra +import codingstandards.cpp.RestrictedRangeAnalysis +import codingstandards.cpp.FloatingPoint +import codingstandards.cpp.AlertReporting +import semmle.code.cpp.controlflow.Guards +import semmle.code.cpp.dataflow.new.DataFlow +import semmle.code.cpp.dataflow.new.TaintTracking +import semmle.code.cpp.controlflow.Dominance + +// IEEE 754-1985 Section 7.1 invalid operations +class InvalidOperationExpr extends BinaryOperation { + string reason; + + InvalidOperationExpr() { + // Usual arithmetic conversions in both languages mean that if either operand is a floating + // type, the other one is converted to a floating type as well. + getAnOperand().getFullyConverted().getType() instanceof FloatingPointType and + ( + // 7.1.1 propagates signaling NaNs, we rely on flow analysis and/or assume quiet NaNs, so we + // intentionally do not cover this case. + // 7.1.2: magnitude subtraction of infinities, such as +Inf + -Inf + getOperator() = "+" and + exists(Boolean sign | + exprMayEqualInfinity(getLeftOperand(), sign) and + exprMayEqualInfinity(getRightOperand(), sign.booleanNot()) + ) and + reason = "possible addition of infinity and negative infinity" + or + // 7.1.2 continued + getOperator() = "-" and + exists(Boolean sign | + exprMayEqualInfinity(getLeftOperand(), sign) and + exprMayEqualInfinity(getRightOperand(), sign) + ) and + reason = "possible subtraction of an infinity from itself" + or + // 7.1.3: multiplication of zero by infinity + getOperator() = "*" and + exprMayEqualZero(getAnOperand()) and + exprMayEqualInfinity(getAnOperand(), _) and + reason = "possible multiplication of zero by infinity" + or + // 7.1.4: Division of zero by zero, or infinity by infinity + getOperator() = "/" and + exprMayEqualZero(getLeftOperand()) and + exprMayEqualZero(getRightOperand()) and + reason = "possible division of zero by zero" + or + // 7.1.4 continued + getOperator() = "/" and + exprMayEqualInfinity(getLeftOperand(), _) and + exprMayEqualInfinity(getRightOperand(), _) and + reason = "possible division of infinity by infinity" + or + // 7.1.5: x % y where y is zero or x is infinite + getOperator() = "%" and + exprMayEqualInfinity(getLeftOperand(), _) and + reason = "possible modulus of infinity" + or + // 7.1.5 continued + getOperator() = "%" and + exprMayEqualZero(getRightOperand()) and + reason = "possible modulus by zero" + // 7.1.6 handles the sqrt function, not covered here. + // 7.1.7 declares exceptions during invalid conversions, which we catch as sinks in our flow + // analysis. + // 7.1.8 declares exceptions for unordered comparisons, which we catch as sinks in our flow + // analysis. + ) + } + + string getReason() { result = reason } +} + +module InvalidNaNUsage implements DataFlow::ConfigSig { + + /** + * An expression which has non-NaN inputs and may produce a NaN output. + */ + predicate isSource(DataFlow::Node node) { + potentialSource(node) and + not exists(DataFlow::Node prior | + isAdditionalFlowStep(prior, node) and + potentialSource(prior) + ) + } + + /** + * An expression which may produce a NaN output. + */ + additional predicate potentialSource(DataFlow::Node node) { + node.asExpr() instanceof InvalidOperationExpr + } + + /** + * Add an additional flow step to handle NaN propagation through floating point operations. + */ + predicate isAdditionalFlowStep(DataFlow::Node source, DataFlow::Node sink) { + exists(Operation o | + o.getAnOperand() = source.asExpr() and + o = sink.asExpr() and + o.getType() instanceof FloatingPointType + ) + } + + predicate isSink(DataFlow::Node node) { + // Case 1: NaNs shall not be compared, except to themselves + exists(ComparisonOperation cmp | + node.asExpr() = cmp.getAnOperand() and + not hashCons(cmp.getLeftOperand()) = hashCons(cmp.getRightOperand()) + ) + or + // Case 2: NaNs and infinities shall not be cast to integers + exists(Conversion c | + node.asExpr() = c.getUnconverted() and + c.getExpr().getType() instanceof FloatingPointType and + c.getType() instanceof IntegralType + ) + //or + //// Case 4: Functions shall not return NaNs or infinities + //exists(ReturnStmt ret | node.asExpr() = ret.getExpr()) + } +} + +module InvalidNaNFlow = DataFlow::Global; + +import InvalidNaNFlow::PathGraph + +from + Element elem, InvalidNaNFlow::PathNode source, InvalidNaNFlow::PathNode sink, string msg, + string sourceString +where + elem = MacroUnwrapper::unwrapElement(sink.getNode().asExpr()) and + not isExcluded(elem, FloatingTypes2Package::possibleMisuseOfUndetectedNaNQuery()) and + ( + InvalidNaNFlow::flow(source.getNode(), sink.getNode()) and + msg = "Invalid usage of possible $@." and + sourceString = + "NaN resulting from " + source.getNode().asExpr().(InvalidOperationExpr).getReason() + ) +select elem, source, sink, msg, source, sourceString diff --git a/c/misra/src/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.ql b/c/misra/src/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.ql new file mode 100644 index 0000000000..94888a95e6 --- /dev/null +++ b/c/misra/src/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.ql @@ -0,0 +1,223 @@ +/** + * @id c/misra/possible-undetected-na-nor-infinity + * @name DIR-4-15: Evaluation of floating-point expressions shall not lead to the undetected generation of infinities + * @description Evaluation of floating-point expressions shall not lead to the undetected generation + * of infinities and NaNs. + * @kind path-problem + * @precision high + * @problem.severity error + * @tags external/misra/id/dir-4-15 + * correctness + * external/misra/c/2012/amendment3 + * external/misra/obligation/required + */ + +import cpp +import codeql.util.Boolean +import codingstandards.c.misra +import codingstandards.cpp.RestrictedRangeAnalysis +import codingstandards.cpp.FloatingPoint +import codingstandards.cpp.AlertReporting +import semmle.code.cpp.controlflow.Guards +import semmle.code.cpp.dataflow.new.DataFlow +import semmle.code.cpp.dataflow.new.TaintTracking +import semmle.code.cpp.controlflow.Dominance + +class CantHandleInfinityFunction extends Function { + CantHandleInfinityFunction() { not hasDefinition() and not getName() = "__fpclassifyl" } +} + +class InfinityCheckedExpr extends Expr { + InfinityCheckedExpr() { + exists(MacroInvocation mi | + mi.getMacroName() = ["isfinite", "isinf"] and + mi.getExpr() = this + ) + } + + Expr getCheckedExpr() { + result = + this.(ConditionalExpr) + .getThen() + .(LTExpr) + .getLesserOperand() + .(BitwiseAndExpr) + .getLeftOperand() + .(FunctionCall) + .getArgument(0) + } +} + +/* +signature module ResourceLeakConfigSig { + predicate isResource(DataFlow::Node node); + + predicate isFree(DataFlow::Node node, DataFlow::Node resource); + + default ControlFlowNode outOfScope(DataFlow::Node resource) { + result = resource.asExpr().getEnclosingFunction().getBlock().getLastStmt() + } + + default predicate isAlias(DataFlow::Node alias, DataFlow::Node resource) { + isResource(resource) and + DataFlow::localFlow(resource, alias) + } +} + +module ResourceLeak { + predicate isLeaked(DataFlow::Node resource, ControlFlowNode cfgNode) { + resource.asExpr() = cfgNode + or + isLeaked(resource, cfgNode.getAPredecessor()) and + not exists(DataFlow::Node free, DataFlow::Node freed | + free.asExpr() = cfgNode and + Config::isFree(free, freed) and + Config::isAlias(freed, resource) + ) + } + + private ControlFlowNode getARawLeak(DataFlow::Node resource) { + Config::isResource(resource) and + result = Config::outOfScope(resource) and + isLeaked(resource, result) + } + + ControlFlowNode getALeak(DataFlow::Node resource) { + result = getARawLeak(resource) and + not exists(DataFlow::Node dealiased | + Config::isResource(dealiased) and + Config::isAlias(resource, dealiased) and + not resource = dealiased and + result = getARawLeak(dealiased) + ) and + not exists(ControlFlowNode dominator | + dominator = getARawLeak(resource) and + strictlyDominates(dominator, result) + ) + } +} + +module MissedInfinityConfig implements ResourceLeakConfigSig { + predicate isResource(DataFlow::Node node) { + //exists(BinaryOperation expr | + // expr = node.asExpr() and + // expr.getOperator() = "/" and + // RestrictedRangeAnalysis::upperBound(expr.getRightOperand()) <= 0 and + // RestrictedRangeAnalysis::lowerBound(expr.getRightOperand()) >= 0 + //) + [ + RestrictedRangeAnalysis::upperBound(node.asExpr()), + RestrictedRangeAnalysis::lowerBound(node.asExpr()) + ].toString() = "Infinity" + //and not node.asExpr() instanceof VariableAccess + //and not node.asExpr() instanceof ArrayExpr + } + + predicate test(Expr expr, string lowerBound, string upperBound) { + //expr.getType() instanceof FloatingPointType + //and + lowerBound = RestrictedRangeAnalysis::lowerBound(expr).toString() and + upperBound = RestrictedRangeAnalysis::upperBound(expr).toString() and + [lowerBound, upperBound] = "Infinity" + } + + additional predicate testDiv( + DivExpr div, string lbDiv, string ubDiv, string lbNum, string ubNum, string lbDenom, + string ubDenom + ) { + lbDiv = RestrictedRangeAnalysis::lowerBound(div).toString() and + ubDiv = RestrictedRangeAnalysis::upperBound(div).toString() and + lbNum = RestrictedRangeAnalysis::lowerBound(div.getLeftOperand()).toString() and + ubNum = RestrictedRangeAnalysis::upperBound(div.getLeftOperand()).toString() and + lbDenom = RestrictedRangeAnalysis::lowerBound(div.getRightOperand()).toString() and + ubDenom = RestrictedRangeAnalysis::upperBound(div.getRightOperand()).toString() and + not lbDiv = ubDiv and + InvalidNaNUsage::isSource(DataFlow::exprNode(div)) + } + + predicate isFree(DataFlow::Node node, DataFlow::Node resource) { + isResource(resource) and + ( + node.asExpr().(InfinityCheckedExpr).getCheckedExpr() = resource.asExpr() + or + not [ + RestrictedRangeAnalysis::lowerBound(node.asExpr()), + RestrictedRangeAnalysis::upperBound(node.asExpr()) + ].toString() = "Infinity" and + isMove(node, resource) + ) + } + + predicate isMove(DataFlow::Node node, DataFlow::Node moved) { + isResource(moved) and + isAlias(node, moved) and + not exists(DataFlow::Node laterUse, ControlFlowNode later | + later = laterUse.asExpr() and + later = node.asExpr().getASuccessor+() and + hashCons(laterUse.asExpr()) = hashCons(moved.asExpr()) + ) + } + + ControlFlowNode outOfScope(DataFlow::Node resource) { + result = resource.asExpr().getEnclosingFunction().getBlock().getLastStmt() + or + exists(AssignExpr assign, DataFlow::Node alias | + assign.getRValue() = alias.asExpr() and + isAlias(alias, resource) and + not assign.getRValue().(VariableAccess).getTarget() instanceof StackVariable and + result = assign + ) + or + exists(FunctionCall fc | + fc.getArgument(_) = resource.asExpr() and + result = fc + ) + } + + predicate isAlias(DataFlow::Node alias, DataFlow::Node resource) { + TaintTracking::localTaint(resource, alias) + } +} + +import ResourceLeak as MissedInfinity +*/ + +//from Expr value, FunctionCall fc +//where +// not isExcluded(value, FloatingTypes2Package::possibleUndetectedNaNorInfinityQuery()) and +// [RestrictedRangeAnalysis::lowerBound(value), RestrictedRangeAnalysis::upperBound(value)].toString() = "Infinity" and +// value = fc.getAnArgument() and +// fc.getTarget() instanceof CantHandleInfinityFunction and +// not value instanceof InfinityCheckedExpr and +// not exists (GuardCondition g | +// g.controls(fc.getBasicBlock(), true) and +// g instanceof InfinityCheckedExpr +// // TODO check we check the right expr +// ) +//select +// value, "possible use of unchecked infinity as arg to " + fc.getTarget().getName() +//from DataFlow::Node node, ControlFlowNode leakPoint +//where +// not isExcluded(node.asExpr(), FloatingTypes2Package::possibleUndetectedNaNorInfinityQuery()) and +// leakPoint = MissedInfinity::getALeak(node) +// select node, "Expression generates an infinity which is not checked before $@.", leakPoint, "external leak point" + + +//import InvalidNaNFlow::PathGraph +//from Element elem, DataFlow::Node source, DataFlow::Node sink, string msg, string sourceString +from + Element elem, InvalidInfinityFlow::PathNode source, InvalidInfinityFlow::PathNode sink, + string msg, string sourceString +where + elem = MacroUnwrapper::unwrapElement(sink.getNode().asExpr()) and + not isExcluded(elem, FloatingTypes2Package::possibleUndetectedNaNorInfinityQuery()) and + ( + InvalidInfinityFlow::flow(source.getNode(), sink.getNode()) and + msg = "Invalid usage of possible $@." and + sourceString = "infinity" + //or + //InvalidNaNFlow::flow(source, sink) and + //msg = "Invalid usage of possible $@." and + //sourceString = "NaN resulting from " + source.asExpr().(InvalidOperationExpr).getReason() + ) +select elem, source, sink, msg, source, sourceString diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected new file mode 100644 index 0000000000..78f4c6baec --- /dev/null +++ b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected @@ -0,0 +1,48 @@ +edges +| test.c:8:14:8:20 | ... / ... | test.c:8:14:8:20 | ... / ... | provenance | | +| test.c:8:14:8:20 | ... / ... | test.c:12:8:12:9 | l2 | provenance | | +| test.c:8:14:8:20 | ... / ... | test.c:18:3:18:9 | l2 | provenance | | +| test.c:8:14:8:20 | ... / ... | test.c:27:19:27:20 | l2 | provenance | | +| test.c:9:14:9:16 | - ... | test.c:9:14:9:16 | - ... | provenance | | +| test.c:9:14:9:16 | - ... | test.c:13:8:13:9 | l3 | provenance | | +| test.c:9:14:9:16 | - ... | test.c:19:3:19:9 | l3 | provenance | | +| test.c:9:14:9:16 | - ... | test.c:28:19:28:20 | l3 | provenance | | +| test.c:31:14:32:15 | ... / ... | test.c:31:14:32:15 | ... / ... | provenance | | +| test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | provenance | | +| test.c:33:14:33:22 | ... / ... | test.c:33:14:33:22 | ... / ... | provenance | | +| test.c:33:14:33:22 | ... / ... | test.c:39:3:39:9 | l8 | provenance | | +nodes +| test.c:8:14:8:20 | ... / ... | semmle.label | ... / ... | +| test.c:8:14:8:20 | ... / ... | semmle.label | ... / ... | +| test.c:9:14:9:16 | - ... | semmle.label | - ... | +| test.c:9:14:9:16 | - ... | semmle.label | - ... | +| test.c:12:8:12:9 | l2 | semmle.label | l2 | +| test.c:13:8:13:9 | l3 | semmle.label | l3 | +| test.c:18:3:18:9 | l2 | semmle.label | l2 | +| test.c:19:3:19:9 | l3 | semmle.label | l3 | +| test.c:27:19:27:20 | l2 | semmle.label | l2 | +| test.c:28:19:28:20 | l3 | semmle.label | l3 | +| test.c:31:14:32:15 | ... / ... | semmle.label | ... / ... | +| test.c:31:14:32:15 | ... / ... | semmle.label | ... / ... | +| test.c:33:14:33:22 | ... / ... | semmle.label | ... / ... | +| test.c:33:14:33:22 | ... / ... | semmle.label | ... / ... | +| test.c:38:3:38:9 | l7 | semmle.label | l7 | +| test.c:39:3:39:9 | l8 | semmle.label | l8 | +| test.c:61:5:61:19 | ... / ... | semmle.label | ... / ... | +| test.c:66:5:66:21 | ... / ... | semmle.label | ... / ... | +| test.c:72:14:72:30 | ... / ... | semmle.label | ... / ... | +| test.c:75:18:75:34 | ... / ... | semmle.label | ... / ... | +subpaths +#select +| test.c:12:8:12:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:12:8:12:9 | l2 | Invalid usage of possible $@. | test.c:8:14:8:20 | ... / ... | infinity | +| test.c:13:8:13:9 | l3 | test.c:9:14:9:16 | - ... | test.c:13:8:13:9 | l3 | Invalid usage of possible $@. | test.c:9:14:9:16 | - ... | infinity | +| test.c:18:8:18:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:18:3:18:9 | l2 | Invalid usage of possible $@. | test.c:8:14:8:20 | ... / ... | infinity | +| test.c:19:8:19:9 | l3 | test.c:9:14:9:16 | - ... | test.c:19:3:19:9 | l3 | Invalid usage of possible $@. | test.c:9:14:9:16 | - ... | infinity | +| test.c:27:19:27:20 | l2 | test.c:8:14:8:20 | ... / ... | test.c:27:19:27:20 | l2 | Invalid usage of possible $@. | test.c:8:14:8:20 | ... / ... | infinity | +| test.c:28:19:28:20 | l3 | test.c:9:14:9:16 | - ... | test.c:28:19:28:20 | l3 | Invalid usage of possible $@. | test.c:9:14:9:16 | - ... | infinity | +| test.c:38:8:38:9 | l7 | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | Invalid usage of possible $@. | test.c:31:14:32:15 | ... / ... | infinity | +| test.c:39:8:39:9 | l8 | test.c:33:14:33:22 | ... / ... | test.c:39:3:39:9 | l8 | Invalid usage of possible $@. | test.c:33:14:33:22 | ... / ... | infinity | +| test.c:61:12:61:18 | ... / ... | test.c:61:5:61:19 | ... / ... | test.c:61:5:61:19 | ... / ... | Invalid usage of possible $@. | test.c:61:5:61:19 | ... / ... | infinity | +| test.c:66:12:66:20 | ... / ... | test.c:66:5:66:21 | ... / ... | test.c:66:5:66:21 | ... / ... | Invalid usage of possible $@. | test.c:66:5:66:21 | ... / ... | infinity | +| test.c:72:21:72:29 | ... / ... | test.c:72:14:72:30 | ... / ... | test.c:72:14:72:30 | ... / ... | Invalid usage of possible $@. | test.c:72:14:72:30 | ... / ... | infinity | +| test.c:75:25:75:33 | ... / ... | test.c:75:18:75:34 | ... / ... | test.c:75:18:75:34 | ... / ... | Invalid usage of possible $@. | test.c:75:18:75:34 | ... / ... | infinity | diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.qlref b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.qlref new file mode 100644 index 0000000000..dccac37c5f --- /dev/null +++ b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.qlref @@ -0,0 +1 @@ +rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql \ No newline at end of file diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected new file mode 100644 index 0000000000..f317f236ef --- /dev/null +++ b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected @@ -0,0 +1,63 @@ +edges +| test.c:27:14:27:20 | ... / ... | test.c:27:14:27:20 | ... / ... | provenance | | +| test.c:27:14:27:20 | ... / ... | test.c:36:3:36:9 | l5 | provenance | | +| test.c:27:14:27:20 | ... / ... | test.c:46:3:46:4 | l5 | provenance | | +| test.c:27:14:27:20 | ... / ... | test.c:47:3:47:4 | l5 | provenance | | +| test.c:27:14:27:20 | ... / ... | test.c:48:3:48:4 | l5 | provenance | | +| test.c:27:14:27:20 | ... / ... | test.c:49:3:49:4 | l5 | provenance | | +| test.c:27:14:27:20 | ... / ... | test.c:50:3:50:4 | l5 | provenance | | +| test.c:27:14:27:20 | ... / ... | test.c:51:3:51:4 | l5 | provenance | | +| test.c:28:14:28:20 | ... / ... | test.c:28:14:28:20 | ... / ... | provenance | | +| test.c:28:14:28:20 | ... / ... | test.c:37:3:37:9 | l6 | provenance | | +| test.c:28:14:28:20 | ... / ... | test.c:52:3:52:4 | l6 | provenance | | +| test.c:31:14:32:15 | ... / ... | test.c:31:14:32:15 | ... / ... | provenance | | +| test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | provenance | | +| test.c:31:14:32:15 | ... / ... | test.c:53:3:53:4 | l7 | provenance | | +| test.c:33:14:33:22 | ... / ... | test.c:33:14:33:22 | ... / ... | provenance | | +| test.c:33:14:33:22 | ... / ... | test.c:39:3:39:9 | l8 | provenance | | +| test.c:33:14:33:22 | ... / ... | test.c:54:3:54:4 | l8 | provenance | | +nodes +| test.c:27:14:27:20 | ... / ... | semmle.label | ... / ... | +| test.c:27:14:27:20 | ... / ... | semmle.label | ... / ... | +| test.c:28:14:28:20 | ... / ... | semmle.label | ... / ... | +| test.c:28:14:28:20 | ... / ... | semmle.label | ... / ... | +| test.c:31:14:32:15 | ... / ... | semmle.label | ... / ... | +| test.c:31:14:32:15 | ... / ... | semmle.label | ... / ... | +| test.c:33:14:33:22 | ... / ... | semmle.label | ... / ... | +| test.c:33:14:33:22 | ... / ... | semmle.label | ... / ... | +| test.c:36:3:36:9 | l5 | semmle.label | l5 | +| test.c:37:3:37:9 | l6 | semmle.label | l6 | +| test.c:38:3:38:9 | l7 | semmle.label | l7 | +| test.c:39:3:39:9 | l8 | semmle.label | l8 | +| test.c:46:3:46:4 | l5 | semmle.label | l5 | +| test.c:47:3:47:4 | l5 | semmle.label | l5 | +| test.c:48:3:48:4 | l5 | semmle.label | l5 | +| test.c:49:3:49:4 | l5 | semmle.label | l5 | +| test.c:50:3:50:4 | l5 | semmle.label | l5 | +| test.c:51:3:51:4 | l5 | semmle.label | l5 | +| test.c:52:3:52:4 | l6 | semmle.label | l6 | +| test.c:53:3:53:4 | l7 | semmle.label | l7 | +| test.c:54:3:54:4 | l8 | semmle.label | l8 | +| test.c:61:5:61:19 | ... / ... | semmle.label | ... / ... | +| test.c:66:5:66:21 | ... / ... | semmle.label | ... / ... | +| test.c:72:14:72:30 | ... / ... | semmle.label | ... / ... | +| test.c:75:18:75:34 | ... / ... | semmle.label | ... / ... | +subpaths +#select +| test.c:36:8:36:9 | l5 | test.c:27:14:27:20 | ... / ... | test.c:36:3:36:9 | l5 | Invalid usage of possible $@. | test.c:27:14:27:20 | ... / ... | NaN resulting from possible division of infinity by infinity | +| test.c:37:8:37:9 | l6 | test.c:28:14:28:20 | ... / ... | test.c:37:3:37:9 | l6 | Invalid usage of possible $@. | test.c:28:14:28:20 | ... / ... | NaN resulting from possible division of infinity by infinity | +| test.c:38:8:38:9 | l7 | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | Invalid usage of possible $@. | test.c:31:14:32:15 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:39:8:39:9 | l8 | test.c:33:14:33:22 | ... / ... | test.c:39:3:39:9 | l8 | Invalid usage of possible $@. | test.c:33:14:33:22 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:46:3:46:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:46:3:46:4 | l5 | Invalid usage of possible $@. | test.c:27:14:27:20 | ... / ... | NaN resulting from possible division of infinity by infinity | +| test.c:47:3:47:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:47:3:47:4 | l5 | Invalid usage of possible $@. | test.c:27:14:27:20 | ... / ... | NaN resulting from possible division of infinity by infinity | +| test.c:48:3:48:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:48:3:48:4 | l5 | Invalid usage of possible $@. | test.c:27:14:27:20 | ... / ... | NaN resulting from possible division of infinity by infinity | +| test.c:49:3:49:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:49:3:49:4 | l5 | Invalid usage of possible $@. | test.c:27:14:27:20 | ... / ... | NaN resulting from possible division of infinity by infinity | +| test.c:50:3:50:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:50:3:50:4 | l5 | Invalid usage of possible $@. | test.c:27:14:27:20 | ... / ... | NaN resulting from possible division of infinity by infinity | +| test.c:51:3:51:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:51:3:51:4 | l5 | Invalid usage of possible $@. | test.c:27:14:27:20 | ... / ... | NaN resulting from possible division of infinity by infinity | +| test.c:52:3:52:4 | l6 | test.c:28:14:28:20 | ... / ... | test.c:52:3:52:4 | l6 | Invalid usage of possible $@. | test.c:28:14:28:20 | ... / ... | NaN resulting from possible division of infinity by infinity | +| test.c:53:3:53:4 | l7 | test.c:31:14:32:15 | ... / ... | test.c:53:3:53:4 | l7 | Invalid usage of possible $@. | test.c:31:14:32:15 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:54:3:54:4 | l8 | test.c:33:14:33:22 | ... / ... | test.c:54:3:54:4 | l8 | Invalid usage of possible $@. | test.c:33:14:33:22 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:61:12:61:18 | ... / ... | test.c:61:5:61:19 | ... / ... | test.c:61:5:61:19 | ... / ... | Invalid usage of possible $@. | test.c:61:5:61:19 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:66:12:66:20 | ... / ... | test.c:66:5:66:21 | ... / ... | test.c:66:5:66:21 | ... / ... | Invalid usage of possible $@. | test.c:66:5:66:21 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:72:21:72:29 | ... / ... | test.c:72:14:72:30 | ... / ... | test.c:72:14:72:30 | ... / ... | Invalid usage of possible $@. | test.c:72:14:72:30 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:75:25:75:33 | ... / ... | test.c:75:18:75:34 | ... / ... | test.c:75:18:75:34 | ... / ... | Invalid usage of possible $@. | test.c:75:18:75:34 | ... / ... | NaN resulting from possible division of zero by zero | diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.qlref b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.qlref new file mode 100644 index 0000000000..d88c172bd5 --- /dev/null +++ b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.qlref @@ -0,0 +1 @@ +rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql \ No newline at end of file diff --git a/c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.expected b/c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.expected new file mode 100644 index 0000000000..2ec1a0ac6c --- /dev/null +++ b/c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.expected @@ -0,0 +1 @@ +No expected results have yet been specified \ No newline at end of file diff --git a/c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.qlref b/c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.qlref new file mode 100644 index 0000000000..1ffb7ad071 --- /dev/null +++ b/c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.qlref @@ -0,0 +1 @@ +rules/DIR-4-15/PossibleUndetectedNaNorInfinity.ql \ No newline at end of file diff --git a/c/misra/test/rules/DIR-4-15/test.c b/c/misra/test/rules/DIR-4-15/test.c new file mode 100644 index 0000000000..d634a6e594 --- /dev/null +++ b/c/misra/test/rules/DIR-4-15/test.c @@ -0,0 +1,76 @@ +#include "math.h" + +float getFloat() { return 1.0; } + +// Parameter could be infinity +void f1(float p1) { + float l1 = 1; + float l2 = 1.0 / 0; + float l3 = -l2; + + 10 / l1; // COMPLIANT + 10 / l2; // NON_COMPLIANT: Underflows to zero + 10 / l3; // NON_COMPLIANT: Underflow to negative zero + 10 / p1; // COMPLIANT: Reduce false positives by assuming not infinity + 10 / getFloat(); // COMPLIANT: Reduce false positives by assuming not infinity + + (int)l1; // COMPLIANT + (int)l2; // NON_COMPLIANT + (int)l3; // NON_COMPLIANT + (int)p1; // COMPLIANT: Reduce false positives by assuming not infinity + (int)getFloat(); // COMPLIANT: Reduce false positives by assuming not infinity + + // Not NaN: + float l4 = l1 / l1; // COMPLIANT + + // NaN because of infinity divided by itself: + float l5 = l2 / l2; // NON_COMPLIANT: Division by infinity not allowed. + float l6 = l3 / l3; // NON_COMPLIANT: Division by infinity not allowed. + + // NaN because of zero divided by itself: + float l7 = getFloat() / + p1; // COMPLIANT: Reduce false positives by assuming not infinity + float l8 = 0.0 / 0.0; + + (int)l4; // COMPLIANT + (int)l5; // NON_COMPLIANT: Casting NaN to int + (int)l6; // NON_COMPLIANT: Casting NaN to int + (int)l7; // NON_COMPLIANT: Casting NaN to int + (int)l8; // NON_COMPLIANT: Casting NaN to int + + l4 == 0; // COMPLIANT + l4 != 0; // COMPLIANT + l4 <= 0; // COMPLIANT + l4 < 0; // COMPLIANT + l4 >= 0; // COMPLIANT + l5 == 0; // NON_COMPLIANT: Comparison with NaN always false + l5 != 0; // NON_COMPLIANT: Comparison with NaN always false + l5 < 0; // NON_COMPLIANT: Comparison with NaN always false + l5 <= 0; // NON_COMPLIANT: Comparison with NaN always false + l5 > 0; // NON_COMPLIANT: Comparison with NaN always false + l5 >= 0; // NON_COMPLIANT: Comparison with NaN always false + l6 == 0; // NON_COMPLIANT: Comparison with NaN always false + l7 == 0; // NON_COMPLIANT: Comparison with NaN always false + l8 == 0; // NON_COMPLIANT: Comparison with NaN always false + + // Guards + float l9 = 0; + if (l9 != 0) { + (int) (l9 / l9); // COMPLIANT: l9 is not zero + } else { + (int) (l9 / l9); // NON_COMPLIANT: Casting NaN to integer + } + + float l10 = 0; + if (l10 == 0) { + (int) (l10 / l10); // NON_COMPLIANT: Casting NaN to integer + } else { + (int) (l10 / l10); // COMPLIANT: l10 is not zero + } + + float l11 = 0; + l11 == 0 ? (int) (l11 / l11) : 0; // NON_COMPLIANT + l11 == 0 ? 0 : (int) (l11 / l11); // COMPLIANT + l11 != 0 ? (int) (l11 / l11) : 0; // COMPLIANT + l11 != 0 ? 0 : (int) (l11 / l11); // NON_COMPLIANT +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/FloatingPoint.qll b/cpp/common/src/codingstandards/cpp/FloatingPoint.qll new file mode 100644 index 0000000000..d143f81418 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/FloatingPoint.qll @@ -0,0 +1,61 @@ +import codeql.util.Boolean +import codingstandards.cpp.RestrictedRangeAnalysis + +predicate exprMayEqualZero(Expr e) { + RestrictedRangeAnalysis::upperBound(e) >= 0 and + RestrictedRangeAnalysis::lowerBound(e) <= 0 and + not guardedNotEqualZero(e) +} + +predicate guardedNotEqualZero(Expr e) { + /* Note Boolean cmpEq, false means cmpNeq */ + exists(Expr checked, GuardCondition guard, boolean cmpEq, BooleanValue value | + hashCons(checked) = hashCons(e) and + guard.controls(e.getBasicBlock(), cmpEq) and + value.getValue() = cmpEq and + guard.comparesEq(checked, 0, false, value) + ) + or + exists(Expr checked, Expr val, int valVal, GuardCondition guard, boolean cmpEq | + hashCons(checked) = hashCons(e) and + forex(float v | + v = [RestrictedRangeAnalysis::lowerBound(val), RestrictedRangeAnalysis::upperBound(val)] + | + valVal = v + ) and + guard.controls(e.getBasicBlock(), cmpEq) and + guard.comparesEq(checked, val, -valVal, false, cmpEq) + ) +} + +predicate guardedNotInfinite(Expr e) { + /* Note Boolean cmpEq, false means cmpNeq */ + exists(Expr c, GuardCondition guard, boolean cmpEq | + hashCons(c) = hashCons(e) and + guard.controls(e, cmpEq) and + guard.comparesEq(c, 0, cmpEq.booleanNot(), _) + ) +} + +predicate test(Expr e, Expr v, int k, boolean areEqual, Boolean value, Expr gce, BasicBlock bb) { + exists(GuardCondition gc | gce = gc | + gc.controls(bb, _) and + gc.comparesEq(e, v, k, areEqual, value) and + ( + //gc.getAChild+().toString().matches("%dfYRes%") or + e.getAChild*().toString().matches("%dfPseudoPanchro%") or + v.getAChild*().toString().matches("%dfPseudoPanchro%") + ) + ) +} + +predicate exprMayEqualInfinity(Expr e, Boolean positive) { + exists(float target | + positive = true and target = 1.0 / 0.0 + or + positive = false and target = -1.0 / 0.0 + | + RestrictedRangeAnalysis::upperBound(e.getUnconverted()) = target or + RestrictedRangeAnalysis::lowerBound(e.getUnconverted()) = target + ) +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll new file mode 100644 index 0000000000..79ae2f367a --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll @@ -0,0 +1,1903 @@ +import semmle.code.cpp.controlflow.Guards +import semmle.code.cpp.valuenumbering.HashCons +/** + * A fork of SimpleRangeAnalysis.qll, which is intended to only give + * results with a conservative basis. + * + * For instance, since range analysis is local, a function call (e.g. + * `f()`) is given the widest possible range in the original library. In + * this fork, we do not provide any result. + * + * Original library level doc comment from SimpleRangeAnalysis.qll: + * + * Simple range analysis library. Range analysis is usually done as an + * abstract interpretation over the lattice of range values. (A range is a + * pair, containing a lower and upper bound for the value.) The problem + * with this approach is that the lattice is very tall, which means it can + * take an extremely large number of iterations to find the least fixed + * point. This example illustrates the problem: + * + * int count = 0; + * for (; p; p = p->next) { + * count = count+1; + * } + * + * The range of 'count' is initially (0,0), then (0,1) on the second + * iteration, (0,2) on the third iteration, and so on until we eventually + * reach maxInt. + * + * This library uses a crude solution to the problem described above: if + * the upper (or lower) bound of an expression might depend recursively on + * itself then we round it up (down for lower bounds) to one of a fixed set + * of values, such as 0, 1, 2, 256, and +Inf. This limits the height of the + * lattice which ensures that the analysis will terminate in a reasonable + * amount of time. This solution is similar to the abstract interpretation + * technique known as 'widening', but it is less precise because we are + * unable to inspect the bounds from the previous iteration of the fixed + * point computation. For example, widening might be able to deduce that + * the lower bound is -11 but we would approximate it to -16. + * + * QL does not allow us to compute an aggregate over a recursive + * sub-expression, so we cannot compute the minimum lower bound and maximum + * upper bound during the recursive phase of the query. Instead, the + * recursive phase computes a set of lower bounds and a set of upper bounds + * for each expression. We compute the minimum lower bound and maximum + * upper bound after the recursion is finished. This is another reason why + * we need to limit the number of bounds per expression, because they will + * all be stored until the recursive phase is finished. + * + * The ranges are represented using a pair of floating point numbers. This + * is simpler than using integers because floating point numbers cannot + * overflow and wrap. It is also convenient because we can detect overflow + * and negative overflow by looking for bounds that are outside the range + * of the type. + */ +module RestrictedRangeAnalysis { + import cpp + private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils as Util + import semmle.code.cpp.rangeanalysis.RangeSSA + import SimpleRangeAnalysisCached + private import semmle.code.cpp.rangeanalysis.NanAnalysis + + float largeValue() { result = 1000000000000000.0 } + + /** + * This fixed set of lower bounds is used when the lower bounds of an + * expression are recursively defined. The inferred lower bound is rounded + * down to the nearest lower bound in the fixed set. This restricts the + * height of the lattice, which prevents the analysis from exploding. + * + * Note: these bounds were chosen fairly arbitrarily. Feel free to add more + * bounds to the set if it helps on specific examples and does not make + * performance dramatically worse on large codebases, such as libreoffice. + */ + private float wideningLowerBounds(ArithmeticType t) { + result = 2.0 or + result = 1.0 or + result = 0.0 or + result = -1.0 or + result = -2.0 or + result = -8.0 or + result = -16.0 or + result = -128.0 or + result = -256.0 or + result = -32768.0 or + result = -65536.0 or + result = max(float v | v = Util::typeLowerBound(t) or v = -largeValue()) + } + + /** See comment for `wideningLowerBounds`, above. */ + private float wideningUpperBounds(ArithmeticType t) { + result = -2.0 or + result = -1.0 or + result = 0.0 or + result = 1.0 or + result = 2.0 or + result = 7.0 or + result = 15.0 or + result = 127.0 or + result = 255.0 or + result = 32767.0 or + result = 65535.0 or + result = min(float v | v = Util::typeLowerBound(t) or v = largeValue()) + } + + /** + * Gets the value of the expression `e`, if it is a constant. + * This predicate also handles the case of constant variables initialized in different + * compilation units, which doesn't necessarily have a getValue() result from the extractor. + */ + private string getValue(Expr e) { + if exists(e.getValue()) + then result = e.getValue() + else + /* + * It should be safe to propagate the initialization value to a variable if: + * The type of v is const, and + * The type of v is not volatile, and + * Either: + * v is a local/global variable, or + * v is a static member variable + */ + + exists(VariableAccess access, StaticStorageDurationVariable v | + not v.getUnderlyingType().isVolatile() and + v.getUnderlyingType().isConst() and + e = access and + v = access.getTarget() and + result = getValue(v.getAnAssignedValue()) + ) + } + + private float varMaxVal(Variable v) { + result = min(float f | f = Util::varMaxVal(v) or f = largeValue()) + } + + private float varMinVal(Variable v) { + result = max(float f | f = Util::varMinVal(v) or f = -largeValue()) + } + + private float exprMaxVal(Expr e) { + result = min(float f | f = Util::exprMaxVal(e) or f = largeValue()) + } + + private float exprMinVal(Expr e) { + result = max(float f | f = Util::exprMinVal(e) or f = -largeValue()) + } + + /** + * A bitwise `&` expression in which both operands are unsigned, or are effectively + * unsigned due to being a non-negative constant. + */ + private class UnsignedBitwiseAndExpr extends BitwiseAndExpr { + UnsignedBitwiseAndExpr() { + ( + this.getLeftOperand() + .getFullyConverted() + .getType() + .getUnderlyingType() + .(IntegralType) + .isUnsigned() or + getValue(this.getLeftOperand().getFullyConverted()).toInt() >= 0 + ) and + ( + this.getRightOperand() + .getFullyConverted() + .getType() + .getUnderlyingType() + .(IntegralType) + .isUnsigned() or + getValue(this.getRightOperand().getFullyConverted()).toInt() >= 0 + ) + } + } + + /** + * Gets the floor of `v`, with additional logic to work around issues with + * large numbers. + */ + bindingset[v] + float safeFloor(float v) { + // return the floor of v + v.abs() < 2.pow(31) and + result = v.floor() + or + // `floor()` doesn't work correctly on large numbers (since it returns an integer), + // so fall back to unrounded numbers at this scale. + not v.abs() < 2.pow(31) and + result = v + } + + /** A `MulExpr` where exactly one operand is constant. */ + private class MulByConstantExpr extends MulExpr { + float constant; + Expr operand; + + MulByConstantExpr() { + exists(Expr constantExpr | + this.hasOperands(constantExpr, operand) and + constant = getValue(constantExpr.getFullyConverted()).toFloat() and + not exists(getValue(operand.getFullyConverted()).toFloat()) + ) + } + + /** Gets the value of the constant operand. */ + float getConstant() { result = constant } + + /** Gets the non-constant operand. */ + Expr getOperand() { result = operand } + } + + private class UnsignedMulExpr extends MulExpr { + UnsignedMulExpr() { + this.getType().(IntegralType).isUnsigned() and + // Avoid overlap. It should be slightly cheaper to analyze + // `MulByConstantExpr`. + not this instanceof MulByConstantExpr + } + } + + /** + * Holds if `expr` is effectively a multiplication of `operand` with the + * positive constant `positive`. + */ + private predicate effectivelyMultipliesByPositive(Expr expr, Expr operand, float positive) { + operand = expr.(MulByConstantExpr).getOperand() and + positive = expr.(MulByConstantExpr).getConstant() and + positive >= 0.0 // includes positive zero + or + operand = expr.(UnaryPlusExpr).getOperand() and + positive = 1.0 + or + operand = expr.(CommaExpr).getRightOperand() and + positive = 1.0 + or + operand = expr.(StmtExpr).getResultExpr() and + positive = 1.0 + } + + /** + * Holds if `expr` is effectively a multiplication of `operand` with the + * negative constant `negative`. + */ + private predicate effectivelyMultipliesByNegative(Expr expr, Expr operand, float negative) { + operand = expr.(MulByConstantExpr).getOperand() and + negative = expr.(MulByConstantExpr).getConstant() and + negative < 0.0 // includes negative zero + or + operand = expr.(UnaryMinusExpr).getOperand() and + negative = -1.0 + } + + private class AssignMulByConstantExpr extends AssignMulExpr { + float constant; + + AssignMulByConstantExpr() { + constant = getValue(this.getRValue().getFullyConverted()).toFloat() + } + + float getConstant() { result = constant } + } + + private class AssignMulByPositiveConstantExpr extends AssignMulByConstantExpr { + AssignMulByPositiveConstantExpr() { constant >= 0.0 } + } + + private class AssignMulByNegativeConstantExpr extends AssignMulByConstantExpr { + AssignMulByNegativeConstantExpr() { constant < 0.0 } + } + + private class UnsignedAssignMulExpr extends AssignMulExpr { + UnsignedAssignMulExpr() { + this.getType().(IntegralType).isUnsigned() and + // Avoid overlap. It should be slightly cheaper to analyze + // `AssignMulByConstantExpr`. + not this instanceof AssignMulByConstantExpr + } + } + + /** + * Holds if `expr` is effectively a division of `operand` with the + * positive constant `positive`. + */ + private predicate dividesByPositive(DivExpr expr, Expr operand, float positive) { + operand = expr.(DivExpr).getLeftOperand() and + positive = expr.(DivExpr).getRightOperand().getValue().toFloat() and + positive > 0.0 // doesn't include zero + } + + /** + * Holds if `expr` is effectively a division of `operand` with the + * negative constant `negative`. + */ + private predicate dividesByNegative(Expr expr, Expr operand, float negative) { + operand = expr.(DivExpr).getLeftOperand() and + negative = getValue(expr.(DivExpr).getRightOperand().getFullyConverted()).toFloat() and + negative < 0.0 // doesn't include zero + } + + /** + * Holds if `expr` may divide by zero. + */ + predicate dividesByZero(Expr expr) { + exists(Expr divisor | + divisor = expr.(DivExpr).getRightOperand() and + getTruncatedLowerBounds(divisor) <= 0.0 and + getTruncatedUpperBounds(divisor) >= 0.0 and + not isCheckedNotZero(divisor) + ) + } + + /** + * Holds if `expr` is checked with a guard to not be zero. + * + * Since our range analysis only tracks an upper and lower bound, that means if a variable has + * range [-10, 10], its range includes zero. In the body of an if statement that checks it's not + * equal to zero, we cannot update the range to reflect that as the upper and lower bounds are + * not changed. This problem is not the case for gt, lt, gte, lte, or ==, as these can be used to + * create a new subset range that does not include zero. + * + * It is important to know if an expr may be zero to avoid division by zero creating infinities. + */ + predicate isCheckedNotZero(Expr expr) { + exists(RangeSsaDefinition def, StackVariable v, VariableAccess guardVa, Expr guard | + // This is copied from getGuardedUpperBound, which says its only an approximation. This is + // indeed wrong in many cases. + def.isGuardPhi(v, guardVa, guard, _) and + exists(unique(BasicBlock b | b = def.(BasicBlock).getAPredecessor())) and + expr = def.getAUse(v) and + isNEPhi(v, def, guardVa, 0) + ) + or guardedHashConsNotEqualZero(expr) + } + + predicate guardedHashConsNotEqualZero(Expr e) { + /* Note Boolean cmpEq, false means cmpNeq */ + exists(Expr check, Expr val, int valVal, GuardCondition guard, boolean cmpEq | + hashCons(check) = hashCons(e) and + valVal = getValue(val).toFloat() and + guard.controls(e.getBasicBlock(), cmpEq) and + ( + guard.comparesEq(check, val, -valVal, false, cmpEq) or + guard.comparesEq(val, check, -valVal, false, cmpEq) + ) + ) + } + + /** Set of expressions which we know how to analyze. */ + predicate analyzableExpr(Expr e) { + // The type of the expression must be arithmetic. We reuse the logic in + // `exprMinVal` to check this. + exists(Util::exprMinVal(e)) and + ( + exists(getValue(e).toFloat()) + or + effectivelyMultipliesByPositive(e, _, _) + or + effectivelyMultipliesByNegative(e, _, _) + or + dividesByPositive(e, _, _) + or + dividesByNegative(e, _, _) + // Introduces non-monotonic recursion. However, analysis mostly works with this + // commented out. + // or + // dividesByZero(e) + or + e instanceof DivExpr // TODO: confirm this is OK + or + e instanceof MinExpr + or + e instanceof MaxExpr + or + e instanceof ConditionalExpr + or + e instanceof AddExpr + or + e instanceof SubExpr + or + e instanceof UnsignedMulExpr + or + e instanceof AssignExpr + or + e instanceof AssignAddExpr + or + e instanceof AssignSubExpr + or + e instanceof UnsignedAssignMulExpr + or + e instanceof AssignMulByConstantExpr + or + e instanceof CrementOperation + or + e instanceof RemExpr + or + // A conversion is analyzable, provided that its child has an arithmetic + // type. (Sometimes the child is a reference type, and so does not get + // any bounds.) Rather than checking whether the type of the child is + // arithmetic, we reuse the logic that is already encoded in + // `exprMinVal`. + exists(Util::exprMinVal(e.(Conversion).getExpr())) + or + // Also allow variable accesses, provided that they have SSA + // information. + exists(RangeSsaDefinition def | e = def.getAUse(_)) + or + e instanceof UnsignedBitwiseAndExpr + or + // `>>` by a constant + exists(getValue(e.(RShiftExpr).getRightOperand())) + ) + } + + /** + * Set of definitions that this definition depends on. The transitive + * closure of this relation is used to detect definitions which are + * recursively defined, so that we can prevent the analysis from exploding. + * + * The structure of `defDependsOnDef` and its helper predicates matches the + * structure of `getDefLowerBoundsImpl` and + * `getDefUpperBoundsImpl`. Therefore, if changes are made to the structure + * of the main analysis algorithm then matching changes need to be made + * here. + */ + private predicate defDependsOnDef( + RangeSsaDefinition def, StackVariable v, RangeSsaDefinition srcDef, StackVariable srcVar + ) { + // Definitions with a defining value. + exists(Expr expr | assignmentDef(def, v, expr) | exprDependsOnDef(expr, srcDef, srcVar)) + or + // Assignment operations with a defining value + exists(AssignOperation assignOp | + analyzableExpr(assignOp) and + def = assignOp and + def.getAVariable() = v and + exprDependsOnDef(assignOp, srcDef, srcVar) + ) + or + exists(CrementOperation crem | + def = crem and + def.getAVariable() = v and + exprDependsOnDef(crem.getOperand(), srcDef, srcVar) + ) + or + // Phi nodes. + phiDependsOnDef(def, v, srcDef, srcVar) + } + + /** + * Helper predicate for `defDependsOnDef`. This predicate matches + * the structure of `getLowerBoundsImpl` and `getUpperBoundsImpl`. + */ + private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVariable srcVar) { + exists(Expr operand | + effectivelyMultipliesByNegative(e, operand, _) and + exprDependsOnDef(operand, srcDef, srcVar) + ) + or + exists(Expr operand | + effectivelyMultipliesByPositive(e, operand, _) and + exprDependsOnDef(operand, srcDef, srcVar) + ) + or + exists(Expr operand | + (dividesByPositive(e, operand, _) or dividesByNegative(e, operand, _)) and + exprDependsOnDef(operand, srcDef, srcVar) + ) + or + exists(MinExpr minExpr | e = minExpr | exprDependsOnDef(minExpr.getAnOperand(), srcDef, srcVar)) + or + exists(MaxExpr maxExpr | e = maxExpr | exprDependsOnDef(maxExpr.getAnOperand(), srcDef, srcVar)) + or + exists(ConditionalExpr condExpr | e = condExpr | + exprDependsOnDef(condExpr.getAnOperand(), srcDef, srcVar) + ) + or + exists(AddExpr addExpr | e = addExpr | exprDependsOnDef(addExpr.getAnOperand(), srcDef, srcVar)) + or + exists(SubExpr subExpr | e = subExpr | exprDependsOnDef(subExpr.getAnOperand(), srcDef, srcVar)) + or + exists(UnsignedMulExpr mulExpr | e = mulExpr | + exprDependsOnDef(mulExpr.getAnOperand(), srcDef, srcVar) + ) + or + exists(AssignExpr addExpr | e = addExpr | exprDependsOnDef(addExpr.getRValue(), srcDef, srcVar)) + or + exists(AssignAddExpr addExpr | e = addExpr | + exprDependsOnDef(addExpr.getAnOperand(), srcDef, srcVar) + ) + or + exists(AssignSubExpr subExpr | e = subExpr | + exprDependsOnDef(subExpr.getAnOperand(), srcDef, srcVar) + ) + or + exists(UnsignedAssignMulExpr mulExpr | e = mulExpr | + exprDependsOnDef(mulExpr.getAnOperand(), srcDef, srcVar) + ) + or + exists(AssignMulByConstantExpr mulExpr | e = mulExpr | + exprDependsOnDef(mulExpr.getLValue(), srcDef, srcVar) + ) + or + exists(CrementOperation crementExpr | e = crementExpr | + exprDependsOnDef(crementExpr.getOperand(), srcDef, srcVar) + ) + or + exists(RemExpr remExpr | e = remExpr | exprDependsOnDef(remExpr.getAnOperand(), srcDef, srcVar)) + or + exists(Conversion convExpr | e = convExpr | + exprDependsOnDef(convExpr.getExpr(), srcDef, srcVar) + ) + or + // unsigned `&` + exists(UnsignedBitwiseAndExpr andExpr | + andExpr = e and + exprDependsOnDef(andExpr.getAnOperand(), srcDef, srcVar) + ) + or + // `>>` by a constant + exists(RShiftExpr rs | + rs = e and + exists(getValue(rs.getRightOperand())) and + exprDependsOnDef(rs.getLeftOperand(), srcDef, srcVar) + ) + or + e = srcDef.getAUse(srcVar) + } + + /** + * Helper predicate for `defDependsOnDef`. This predicate matches + * the structure of `getPhiLowerBounds` and `getPhiUpperBounds`. + */ + private predicate phiDependsOnDef( + RangeSsaDefinition phi, StackVariable v, RangeSsaDefinition srcDef, StackVariable srcVar + ) { + exists(VariableAccess access, Expr guard | phi.isGuardPhi(v, access, guard, _) | + exprDependsOnDef(guard.(ComparisonOperation).getAnOperand(), srcDef, srcVar) or + exprDependsOnDef(access, srcDef, srcVar) + ) + or + srcDef = phi.getAPhiInput(v) and srcVar = v + } + + /** The transitive closure of `defDependsOnDef`. */ + private predicate defDependsOnDefTransitively( + RangeSsaDefinition def, StackVariable v, RangeSsaDefinition srcDef, StackVariable srcVar + ) { + defDependsOnDef(def, v, srcDef, srcVar) + or + exists(RangeSsaDefinition midDef, StackVariable midVar | + defDependsOnDef(def, v, midDef, midVar) + | + defDependsOnDefTransitively(midDef, midVar, srcDef, srcVar) + ) + } + + /** The set of definitions that depend recursively on themselves. */ + private predicate isRecursiveDef(RangeSsaDefinition def, StackVariable v) { + defDependsOnDefTransitively(def, v, def, v) + } + + /** + * Holds if the bounds of `e` depend on a recursive definition, meaning that + * `e` is likely to have many candidate bounds during the main recursion. + */ + private predicate isRecursiveExpr(Expr e) { + exists(RangeSsaDefinition def, StackVariable v | exprDependsOnDef(e, def, v) | + isRecursiveDef(def, v) + ) + } + + /** + * Holds if `binop` is a binary operation that's likely to be assigned a + * quadratic (or more) number of candidate bounds during the analysis. This can + * happen when two conditions are satisfied: + * 1. It is likely there are many more candidate bounds for `binop` than for + * its operands. For example, the number of candidate bounds for `x + y`, + * denoted here nbounds(`x + y`), will be O(nbounds(`x`) * nbounds(`y`)). + * In contrast, nbounds(`b ? x : y`) is only O(nbounds(`x`) + nbounds(`y`)). + * 2. Both operands of `binop` are recursively determined and are therefore + * likely to have a large number of candidate bounds. + */ + private predicate isRecursiveBinary(BinaryOperation binop) { + ( + binop instanceof UnsignedMulExpr + or + binop instanceof AddExpr + or + binop instanceof SubExpr + ) and + isRecursiveExpr(binop.getLeftOperand()) and + isRecursiveExpr(binop.getRightOperand()) + } + + /** + * We distinguish 3 kinds of RangeSsaDefinition: + * + * 1. Definitions with a defining value. + * For example: x = y+3 is a definition of x with defining value y+3. + * + * 2. Phi nodes: x3 = phi(x0,x1,x2) + * + * 3. Unanalyzable definitions. + * For example: a parameter is unanalyzable because we know nothing + * about its value. We assign these range [-largeValue(), largeValue()] + * + * This predicate finds all the definitions in the first set. + */ + private predicate assignmentDef(RangeSsaDefinition def, StackVariable v, Expr expr) { + Util::getVariableRangeType(v) instanceof ArithmeticType and + ( + def = v.getInitializer().getExpr() and def = expr + or + exists(AssignExpr assign | + def = assign and + assign.getLValue() = v.getAnAccess() and + expr = assign.getRValue() + ) + ) + } + + /** See comment above assignmentDef. */ + private predicate analyzableDef(RangeSsaDefinition def, StackVariable v) { + assignmentDef(def, v, _) + or + analyzableExpr(def.(AssignOperation)) and + v = def.getAVariable() + or + analyzableExpr(def.(CrementOperation)) and + v = def.getAVariable() + or + phiDependsOnDef(def, v, _, _) + } + + /** + * Computes a normal form of `x` where -0.0 has changed to +0.0. This can be + * needed on the lesser side of a floating-point comparison or on both sides of + * a floating point equality because QL does not follow IEEE in floating-point + * comparisons but instead defines -0.0 to be less than and distinct from 0.0. + */ + bindingset[x] + private float normalizeFloatUp(float x) { result = x + 0.0 } + + /** + * Computes `x + y`, rounded towards +Inf. This is the general case where both + * `x` and `y` may be large numbers. + */ + bindingset[x, y] + private float addRoundingUp(float x, float y) { + if normalizeFloatUp((x + y) - x) < y or normalizeFloatUp((x + y) - y) < x + then result = (x + y).nextUp() + else result = (x + y) + } + + /** + * Computes `x + y`, rounded towards -Inf. This is the general case where both + * `x` and `y` may be large numbers. + */ + bindingset[x, y] + private float addRoundingDown(float x, float y) { + if (x + y) - x > normalizeFloatUp(y) or (x + y) - y > normalizeFloatUp(x) + then result = (x + y).nextDown() + else result = (x + y) + } + + /** + * Computes `x + small`, rounded towards +Inf, where `small` is a small + * constant. + */ + bindingset[x, small] + private float addRoundingUpSmall(float x, float small) { + if (x + small) - x < small then result = (x + small).nextUp() else result = (x + small) + } + + /** + * Computes `x + small`, rounded towards -Inf, where `small` is a small + * constant. + */ + bindingset[x, small] + private float addRoundingDownSmall(float x, float small) { + if (x + small) - x > small then result = (x + small).nextDown() else result = (x + small) + } + + private predicate lowerBoundableExpr(Expr expr) { + (analyzableExpr(expr) or dividesByZero(expr)) and + getUpperBoundsImpl(expr) <= Util::exprMaxVal(expr) and + not exists(getValue(expr).toFloat()) + } + + /** + * Gets the lower bounds of the expression. + * + * Most of the work of computing the lower bounds is done by + * `getLowerBoundsImpl`. However, the lower bounds computed by + * `getLowerBoundsImpl` may not be representable by the result type of the + * expression. For example, if `x` and `y` are of type `int32` and each + * have lower bound -2147483648, then getLowerBoundsImpl` will compute a + * lower bound -4294967296 for the expression `x+y`, even though + * -4294967296 cannot be represented as an `int32`. Such unrepresentable + * bounds are replaced with `exprMinVal(expr)`. This predicate also adds + * `exprMinVal(expr)` as a lower bound if the expression might overflow + * positively, or if it is unanalyzable. + * + * Note: most callers should use `getFullyConvertedLowerBounds` rather than + * this predicate. + */ + private float getTruncatedLowerBounds(Expr expr) { + // If the expression evaluates to a constant, then there is no + // need to call getLowerBoundsImpl. + analyzableExpr(expr) and + result = getValue(expr).toFloat() + or + // Some of the bounds computed by getLowerBoundsImpl might + // overflow, so we replace invalid bounds with exprMinVal. + exists(float newLB | newLB = normalizeFloatUp(getLowerBoundsImpl(expr)) | + if Util::exprMinVal(expr) <= newLB and newLB <= Util::exprMaxVal(expr) + then + // Apply widening where we might get a combinatorial explosion. + if isRecursiveBinary(expr) + then + result = + max(float widenLB | + widenLB = wideningLowerBounds(expr.getUnspecifiedType()) and + not widenLB > newLB + ) + else result = newLB + else result = Util::exprMinVal(expr) + ) and + lowerBoundableExpr(expr) + or + // The expression might overflow and wrap. If so, the + // lower bound is exprMinVal. + analyzableExpr(expr) and + exprMightOverflowPositively(expr) and + not result = getValue(expr).toFloat() and + result = Util::exprMinVal(expr) + or + // The expression is not analyzable, so its lower bound is + // unknown. Note that the call to exprMinVal restricts the + // expressions to just those with arithmetic types. There is no + // need to return results for non-arithmetic expressions. + not analyzableExpr(expr) and + result = exprMinVal(expr) + } + + /** + * Gets the upper bounds of the expression. + * + * Most of the work of computing the upper bounds is done by + * `getUpperBoundsImpl`. However, the upper bounds computed by + * `getUpperBoundsImpl` may not be representable by the result type of the + * expression. For example, if `x` and `y` are of type `int32` and each + * have upper bound 2147483647, then getUpperBoundsImpl` will compute an + * upper bound 4294967294 for the expression `x+y`, even though 4294967294 + * cannot be represented as an `int32`. Such unrepresentable bounds are + * replaced with `exprMaxVal(expr)`. This predicate also adds + * `exprMaxVal(expr)` as an upper bound if the expression might overflow + * negatively, or if it is unanalyzable. + * + * Note: most callers should use `getFullyConvertedUpperBounds` rather than + * this predicate. + */ + private float getTruncatedUpperBounds(Expr expr) { + (analyzableExpr(expr) or dividesByZero(expr)) + and ( + // If the expression evaluates to a constant, then there is no + // need to call getUpperBoundsImpl. + if exists(getValue(expr).toFloat()) + then result = getValue(expr).toFloat() + else ( + // Some of the bounds computed by `getUpperBoundsImpl` + // might overflow, so we replace invalid bounds with + // `exprMaxVal`. + exists(float newUB | newUB = normalizeFloatUp(getUpperBoundsImpl(expr)) | + if Util::exprMinVal(expr) <= newUB and newUB <= Util::exprMaxVal(expr) + then + // Apply widening where we might get a combinatorial explosion. + if isRecursiveBinary(expr) + then + result = + min(float widenUB | + widenUB = wideningUpperBounds(expr.getUnspecifiedType()) and + not widenUB < newUB + ) + else result = newUB + else result = Util::exprMaxVal(expr) + ) + or + // The expression might overflow negatively and wrap. If so, + // the upper bound is `exprMaxVal`. + exprMightOverflowNegatively(expr) and + result = Util::exprMaxVal(expr) + ) + ) or + not analyzableExpr(expr) and + // The expression is not analyzable, so its upper bound is + // unknown. Note that the call to exprMaxVal restricts the + // expressions to just those with arithmetic types. There is no + // need to return results for non-arithmetic expressions. + result = exprMaxVal(expr) + } + + /** Only to be called by `getTruncatedLowerBounds`. */ + private float getLowerBoundsImpl(Expr expr) { + ( + exists(Expr operand, float operandLow, float positive | + effectivelyMultipliesByPositive(expr, operand, positive) and + operandLow = getFullyConvertedLowerBounds(operand) and + result = positive * operandLow + ) + or + exists(Expr operand, float operandHigh, float negative | + effectivelyMultipliesByNegative(expr, operand, negative) and + operandHigh = getFullyConvertedUpperBounds(operand) and + result = negative * operandHigh + ) + or + exists(Expr operand, float operandLow, float positive | + dividesByPositive(expr, operand, positive) and + operandLow = getFullyConvertedLowerBounds(operand) and + result = operandLow / positive + ) + or + exists(Expr operand, float operandLow, float negative | + dividesByNegative(expr, operand, negative) and + operandLow = getFullyConvertedUpperBounds(operand) and + result = operandLow / negative + ) + or + exists(DivExpr div | expr = div | + dividesByZero(expr) and + result = getFullyConvertedLowerBounds(div.getLeftOperand()) / 0 + ) + or + exists(MinExpr minExpr | + expr = minExpr and + // Return the union of the lower bounds from both children. + result = getFullyConvertedLowerBounds(minExpr.getAnOperand()) + ) + or + exists(MaxExpr maxExpr | + expr = maxExpr and + // Compute the cross product of the bounds from both children. We are + // using this mathematical property: + // + // max (minimum{X}, minimum{Y}) + // = minimum { max(x,y) | x in X, y in Y } + exists(float x, float y | + x = getFullyConvertedLowerBounds(maxExpr.getLeftOperand()) and + y = getFullyConvertedLowerBounds(maxExpr.getRightOperand()) and + if x >= y then result = x else result = y + ) + ) + or + // ConditionalExpr (true branch) + exists(ConditionalExpr condExpr | + expr = condExpr and + // Use `boolConversionUpperBound` to determine whether the condition + // might evaluate to `true`. + boolConversionUpperBound(condExpr.getCondition().getFullyConverted()) = 1 and + result = getFullyConvertedLowerBounds(condExpr.getThen()) + ) + or + // ConditionalExpr (false branch) + exists(ConditionalExpr condExpr | + expr = condExpr and + // Use `boolConversionLowerBound` to determine whether the condition + // might evaluate to `false`. + boolConversionLowerBound(condExpr.getCondition().getFullyConverted()) = 0 and + result = getFullyConvertedLowerBounds(condExpr.getElse()) + ) + or + exists(AddExpr addExpr, float xLow, float yLow | + expr = addExpr and + xLow = getFullyConvertedLowerBounds(addExpr.getLeftOperand()) and + yLow = getFullyConvertedLowerBounds(addExpr.getRightOperand()) and + result = addRoundingDown(xLow, yLow) + ) + or + exists(SubExpr subExpr, float xLow, float yHigh | + expr = subExpr and + xLow = getFullyConvertedLowerBounds(subExpr.getLeftOperand()) and + yHigh = getFullyConvertedUpperBounds(subExpr.getRightOperand()) and + result = addRoundingDown(xLow, -yHigh) + ) + or + exists(UnsignedMulExpr mulExpr, float xLow, float yLow | + expr = mulExpr and + xLow = getFullyConvertedLowerBounds(mulExpr.getLeftOperand()) and + yLow = getFullyConvertedLowerBounds(mulExpr.getRightOperand()) and + result = xLow * yLow + ) + or + exists(AssignExpr assign | + expr = assign and + result = getFullyConvertedLowerBounds(assign.getRValue()) + ) + or + exists(AssignAddExpr addExpr, float xLow, float yLow | + expr = addExpr and + xLow = getFullyConvertedLowerBounds(addExpr.getLValue()) and + yLow = getFullyConvertedLowerBounds(addExpr.getRValue()) and + result = addRoundingDown(xLow, yLow) + ) + or + exists(AssignSubExpr subExpr, float xLow, float yHigh | + expr = subExpr and + xLow = getFullyConvertedLowerBounds(subExpr.getLValue()) and + yHigh = getFullyConvertedUpperBounds(subExpr.getRValue()) and + result = addRoundingDown(xLow, -yHigh) + ) + or + exists(UnsignedAssignMulExpr mulExpr, float xLow, float yLow | + expr = mulExpr and + xLow = getFullyConvertedLowerBounds(mulExpr.getLValue()) and + yLow = getFullyConvertedLowerBounds(mulExpr.getRValue()) and + result = xLow * yLow + ) + or + exists(AssignMulByPositiveConstantExpr mulExpr, float xLow | + expr = mulExpr and + xLow = getFullyConvertedLowerBounds(mulExpr.getLValue()) and + result = xLow * mulExpr.getConstant() + ) + or + exists(AssignMulByNegativeConstantExpr mulExpr, float xHigh | + expr = mulExpr and + xHigh = getFullyConvertedUpperBounds(mulExpr.getLValue()) and + result = xHigh * mulExpr.getConstant() + ) + or + exists(PrefixIncrExpr incrExpr, float xLow | + expr = incrExpr and + xLow = getFullyConvertedLowerBounds(incrExpr.getOperand()) and + result = xLow + 1 + ) + or + exists(PrefixDecrExpr decrExpr, float xLow | + expr = decrExpr and + xLow = getFullyConvertedLowerBounds(decrExpr.getOperand()) and + result = addRoundingDownSmall(xLow, -1) + ) + or + // `PostfixIncrExpr` and `PostfixDecrExpr` return the value of their + // operand. The incrementing/decrementing behavior is handled in + // `getDefLowerBoundsImpl`. + exists(PostfixIncrExpr incrExpr | + expr = incrExpr and + result = getFullyConvertedLowerBounds(incrExpr.getOperand()) + ) + or + exists(PostfixDecrExpr decrExpr | + expr = decrExpr and + result = getFullyConvertedLowerBounds(decrExpr.getOperand()) + ) + or + exists(RemExpr remExpr | expr = remExpr | + // If both inputs are positive then the lower bound is zero. + result = 0 + or + // If either input could be negative then the output could be + // negative. If so, the lower bound of `x%y` is `-abs(y) + 1`, which is + // equal to `min(-y + 1,y - 1)`. + exists(float childLB | + childLB = getFullyConvertedLowerBounds(remExpr.getAnOperand()) and + not childLB >= 0 + | + result = getFullyConvertedLowerBounds(remExpr.getRightOperand()) - 1 + or + exists(float rhsUB | rhsUB = getFullyConvertedUpperBounds(remExpr.getRightOperand()) | + result = -rhsUB + 1 + ) + ) + ) + or + // If the conversion is to an arithmetic type then we just return the + // lower bound of the child. We do not need to handle truncation and + // overflow here, because that is done in `getTruncatedLowerBounds`. + // Conversions to `bool` need to be handled specially because they test + // whether the value of the expression is equal to 0. + exists(Conversion convExpr | expr = convExpr | + if convExpr.getUnspecifiedType() instanceof BoolType + then result = boolConversionLowerBound(convExpr.getExpr()) + else result = getTruncatedLowerBounds(convExpr.getExpr()) + ) + or + // Use SSA to get the lower bounds for a variable use. + exists(RangeSsaDefinition def, StackVariable v | expr = def.getAUse(v) | + result = getDefLowerBounds(def, v) + ) + or + // unsigned `&` (tighter bounds may exist) + exists(UnsignedBitwiseAndExpr andExpr | + andExpr = expr and + result = 0.0 + ) + or + // `>>` by a constant + exists(RShiftExpr rsExpr, float left, int right | + rsExpr = expr and + left = getFullyConvertedLowerBounds(rsExpr.getLeftOperand()) and + right = getValue(rsExpr.getRightOperand().getFullyConverted()).toInt() and + result = safeFloor(left / 2.pow(right)) + ) + ) + } + + /** Only to be called by `getTruncatedUpperBounds`. */ + private float getUpperBoundsImpl(Expr expr) { + ( + exists(Expr operand, float operandHigh, float positive | + effectivelyMultipliesByPositive(expr, operand, positive) and + operandHigh = getFullyConvertedUpperBounds(operand) and + result = positive * operandHigh + ) + or + exists(Expr operand, float operandLow, float negative | + effectivelyMultipliesByNegative(expr, operand, negative) and + operandLow = getFullyConvertedLowerBounds(operand) and + result = negative * operandLow + ) + or + exists(Expr operand, float operandHigh, float positive | + dividesByPositive(expr, operand, positive) and + operandHigh = getFullyConvertedUpperBounds(operand) and + result = operandHigh / positive + ) + or + exists(Expr operand, float operandHigh, float negative | + dividesByNegative(expr, operand, negative) and + operandHigh = getFullyConvertedLowerBounds(operand) and + result = operandHigh / negative + ) + or + exists(DivExpr div | expr = div | + dividesByZero(expr) and + result = getFullyConvertedUpperBounds(div.getLeftOperand()) / 0 + ) + or + exists(MaxExpr maxExpr | + expr = maxExpr and + // Return the union of the upper bounds from both children. + result = getFullyConvertedUpperBounds(maxExpr.getAnOperand()) + ) + or + exists(MinExpr minExpr | + expr = minExpr and + // Compute the cross product of the bounds from both children. We are + // using this mathematical property: + // + // min (maximum{X}, maximum{Y}) + // = maximum { min(x,y) | x in X, y in Y } + exists(float x, float y | + x = getFullyConvertedUpperBounds(minExpr.getLeftOperand()) and + y = getFullyConvertedUpperBounds(minExpr.getRightOperand()) and + if x <= y then result = x else result = y + ) + ) + or + // ConditionalExpr (true branch) + exists(ConditionalExpr condExpr | + expr = condExpr and + // Use `boolConversionUpperBound` to determine whether the condition + // might evaluate to `true`. + boolConversionUpperBound(condExpr.getCondition().getFullyConverted()) = 1 and + result = getFullyConvertedUpperBounds(condExpr.getThen()) + ) + or + // ConditionalExpr (false branch) + exists(ConditionalExpr condExpr | + expr = condExpr and + // Use `boolConversionLowerBound` to determine whether the condition + // might evaluate to `false`. + boolConversionLowerBound(condExpr.getCondition().getFullyConverted()) = 0 and + result = getFullyConvertedUpperBounds(condExpr.getElse()) + ) + or + exists(AddExpr addExpr, float xHigh, float yHigh | + expr = addExpr and + xHigh = getFullyConvertedUpperBounds(addExpr.getLeftOperand()) and + yHigh = getFullyConvertedUpperBounds(addExpr.getRightOperand()) and + result = addRoundingUp(xHigh, yHigh) + ) + or + exists(SubExpr subExpr, float xHigh, float yLow | + expr = subExpr and + xHigh = getFullyConvertedUpperBounds(subExpr.getLeftOperand()) and + yLow = getFullyConvertedLowerBounds(subExpr.getRightOperand()) and + result = addRoundingUp(xHigh, -yLow) + ) + or + exists(UnsignedMulExpr mulExpr, float xHigh, float yHigh | + expr = mulExpr and + xHigh = getFullyConvertedUpperBounds(mulExpr.getLeftOperand()) and + yHigh = getFullyConvertedUpperBounds(mulExpr.getRightOperand()) and + result = xHigh * yHigh + ) + or + exists(AssignExpr assign | + expr = assign and + result = getFullyConvertedUpperBounds(assign.getRValue()) + ) + or + exists(AssignAddExpr addExpr, float xHigh, float yHigh | + expr = addExpr and + xHigh = getFullyConvertedUpperBounds(addExpr.getLValue()) and + yHigh = getFullyConvertedUpperBounds(addExpr.getRValue()) and + result = addRoundingUp(xHigh, yHigh) + ) + or + exists(AssignSubExpr subExpr, float xHigh, float yLow | + expr = subExpr and + xHigh = getFullyConvertedUpperBounds(subExpr.getLValue()) and + yLow = getFullyConvertedLowerBounds(subExpr.getRValue()) and + result = addRoundingUp(xHigh, -yLow) + ) + or + exists(UnsignedAssignMulExpr mulExpr, float xHigh, float yHigh | + expr = mulExpr and + xHigh = getFullyConvertedUpperBounds(mulExpr.getLValue()) and + yHigh = getFullyConvertedUpperBounds(mulExpr.getRValue()) and + result = xHigh * yHigh + ) + or + exists(AssignMulByPositiveConstantExpr mulExpr, float xHigh | + expr = mulExpr and + xHigh = getFullyConvertedUpperBounds(mulExpr.getLValue()) and + result = xHigh * mulExpr.getConstant() + ) + or + exists(AssignMulByNegativeConstantExpr mulExpr, float xLow | + expr = mulExpr and + xLow = getFullyConvertedLowerBounds(mulExpr.getLValue()) and + result = xLow * mulExpr.getConstant() + ) + or + exists(PrefixIncrExpr incrExpr, float xHigh | + expr = incrExpr and + xHigh = getFullyConvertedUpperBounds(incrExpr.getOperand()) and + result = addRoundingUpSmall(xHigh, 1) + ) + or + exists(PrefixDecrExpr decrExpr, float xHigh | + expr = decrExpr and + xHigh = getFullyConvertedUpperBounds(decrExpr.getOperand()) and + result = xHigh - 1 + ) + or + // `PostfixIncrExpr` and `PostfixDecrExpr` return the value of their operand. + // The incrementing/decrementing behavior is handled in + // `getDefUpperBoundsImpl`. + exists(PostfixIncrExpr incrExpr | + expr = incrExpr and + result = getFullyConvertedUpperBounds(incrExpr.getOperand()) + ) + or + exists(PostfixDecrExpr decrExpr | + expr = decrExpr and + result = getFullyConvertedUpperBounds(decrExpr.getOperand()) + ) + or + exists(RemExpr remExpr, float rhsUB | + expr = remExpr and + rhsUB = getFullyConvertedUpperBounds(remExpr.getRightOperand()) + | + result = rhsUB - 1 + or + // If the right hand side could be negative then we need to take its + // absolute value. Since `abs(x) = max(-x,x)` this is equivalent to + // adding `-rhsLB` to the set of upper bounds. + exists(float rhsLB | + rhsLB = getFullyConvertedLowerBounds(remExpr.getRightOperand()) and + not rhsLB >= 0 + | + result = -rhsLB + 1 + ) + ) + or + // If the conversion is to an arithmetic type then we just return the + // upper bound of the child. We do not need to handle truncation and + // overflow here, because that is done in `getTruncatedUpperBounds`. + // Conversions to `bool` need to be handled specially because they test + // whether the value of the expression is equal to 0. + exists(Conversion convExpr | expr = convExpr | + if convExpr.getUnspecifiedType() instanceof BoolType + then result = boolConversionUpperBound(convExpr.getExpr()) + else result = getTruncatedUpperBounds(convExpr.getExpr()) + ) + or + // Use SSA to get the upper bounds for a variable use. + exists(RangeSsaDefinition def, StackVariable v | expr = def.getAUse(v) | + result = getDefUpperBounds(def, v) + ) + or + // unsigned `&` (tighter bounds may exist) + exists(UnsignedBitwiseAndExpr andExpr, float left, float right | + andExpr = expr and + left = getFullyConvertedUpperBounds(andExpr.getLeftOperand()) and + right = getFullyConvertedUpperBounds(andExpr.getRightOperand()) and + result = left.minimum(right) + ) + or + // `>>` by a constant + exists(RShiftExpr rsExpr, float left, int right | + rsExpr = expr and + left = getFullyConvertedUpperBounds(rsExpr.getLeftOperand()) and + right = getValue(rsExpr.getRightOperand().getFullyConverted()).toInt() and + result = safeFloor(left / 2.pow(right)) + ) + ) + } + + /** + * Holds if `expr` is converted to `bool` or if it is the child of a + * logical operation. + * + * The purpose of this predicate is to optimize `boolConversionLowerBound` + * and `boolConversionUpperBound` by preventing them from computing + * unnecessary results. In other words, `exprIsUsedAsBool(expr)` holds if + * `expr` is an expression that might be passed as an argument to + * `boolConversionLowerBound` or `boolConversionUpperBound`. + */ + private predicate exprIsUsedAsBool(Expr expr) { + expr = any(BinaryLogicalOperation op).getAnOperand().getFullyConverted() + or + expr = any(UnaryLogicalOperation op).getOperand().getFullyConverted() + or + expr = any(ConditionalExpr c).getCondition().getFullyConverted() + or + exists(Conversion cast | cast.getUnspecifiedType() instanceof BoolType | expr = cast.getExpr()) + } + + /** + * Gets the lower bound of the conversion `(bool)expr`. If we can prove that + * the value of `expr` is never 0 then `lb = 1`. Otherwise `lb = 0`. + */ + private float boolConversionLowerBound(Expr expr) { + // Case 1: if the range for `expr` includes the value 0, + // then `result = 0`. + exprIsUsedAsBool(expr) and + exists(float lb | lb = getTruncatedLowerBounds(expr) and not lb > 0) and + exists(float ub | ub = getTruncatedUpperBounds(expr) and not ub < 0) and + result = 0 + or + // Case 2a: if the range for `expr` does not include the value 0, + // then `result = 1`. + exprIsUsedAsBool(expr) and getTruncatedLowerBounds(expr) > 0 and result = 1 + or + // Case 2b: if the range for `expr` does not include the value 0, + // then `result = 1`. + exprIsUsedAsBool(expr) and getTruncatedUpperBounds(expr) < 0 and result = 1 + or + // Case 3: the type of `expr` is not arithmetic. For example, it might + // be a pointer. + exprIsUsedAsBool(expr) and not exists(Util::exprMinVal(expr)) and result = 0 + } + + /** + * Gets the upper bound of the conversion `(bool)expr`. If we can prove that + * the value of `expr` is always 0 then `ub = 0`. Otherwise `ub = 1`. + */ + private float boolConversionUpperBound(Expr expr) { + // Case 1a: if the upper bound of the operand is <= 0, then the upper + // bound might be 0. + exprIsUsedAsBool(expr) and getTruncatedUpperBounds(expr) <= 0 and result = 0 + or + // Case 1b: if the upper bound of the operand is not <= 0, then the upper + // bound is 1. + exprIsUsedAsBool(expr) and + exists(float ub | ub = getTruncatedUpperBounds(expr) and not ub <= 0) and + result = 1 + or + // Case 2a: if the lower bound of the operand is >= 0, then the upper + // bound might be 0. + exprIsUsedAsBool(expr) and getTruncatedLowerBounds(expr) >= 0 and result = 0 + or + // Case 2b: if the lower bound of the operand is not >= 0, then the upper + // bound is 1. + exprIsUsedAsBool(expr) and + exists(float lb | lb = getTruncatedLowerBounds(expr) and not lb >= 0) and + result = 1 + or + // Case 3: the type of `expr` is not arithmetic. For example, it might + // be a pointer. + exprIsUsedAsBool(expr) and not exists(Util::exprMaxVal(expr)) and result = 1 + } + + /** + * This predicate computes the lower bounds of a phi definition. If the + * phi definition corresponds to a guard, then the guard is used to + * deduce a better lower bound. + * For example: + * + * def: x = y % 10; + * guard: if (x >= 2) { + * block: f(x) + * } + * + * In this example, the lower bound of x is 0, but we can + * use the guard to deduce that the lower bound is 2 inside the block. + */ + private float getPhiLowerBounds(StackVariable v, RangeSsaDefinition phi) { + exists(VariableAccess access, Expr guard, boolean branch, float defLB, float guardLB | + phi.isGuardPhi(v, access, guard, branch) and + lowerBoundFromGuard(guard, access, guardLB, branch) and + defLB = getFullyConvertedLowerBounds(access) + | + // Compute the maximum of `guardLB` and `defLB`. + if guardLB > defLB then result = guardLB else result = defLB + ) + or + exists(VariableAccess access, float neConstant, float lower | + isNEPhi(v, phi, access, neConstant) and + lower = getTruncatedLowerBounds(access) and + if lower = neConstant then result = lower + 1 else result = lower + ) + or + exists(VariableAccess access | + isUnsupportedGuardPhi(v, phi, access) and + result = getTruncatedLowerBounds(access) + ) + or + result = getDefLowerBounds(phi.getAPhiInput(v), v) + } + + /** See comment for `getPhiLowerBounds`, above. */ + private float getPhiUpperBounds(StackVariable v, RangeSsaDefinition phi) { + exists(VariableAccess access, Expr guard, boolean branch, float defUB, float guardUB | + phi.isGuardPhi(v, access, guard, branch) and + upperBoundFromGuard(guard, access, guardUB, branch) and + defUB = getFullyConvertedUpperBounds(access) + | + // Compute the minimum of `guardUB` and `defUB`. + if guardUB < defUB then result = guardUB else result = defUB + ) + or + exists(VariableAccess access, float neConstant, float upper | + isNEPhi(v, phi, access, neConstant) and + upper = getTruncatedUpperBounds(access) and + if upper = neConstant then result = upper - 1 else result = upper + ) + or + exists(VariableAccess access | + isUnsupportedGuardPhi(v, phi, access) and + result = getTruncatedUpperBounds(access) + ) + or + result = getDefUpperBounds(phi.getAPhiInput(v), v) + } + + /** Only to be called by `getDefLowerBounds`. */ + private float getDefLowerBoundsImpl(RangeSsaDefinition def, StackVariable v) { + // Definitions with a defining value. + exists(Expr expr | assignmentDef(def, v, expr) | result = getFullyConvertedLowerBounds(expr)) + or + // Assignment operations with a defining value + exists(AssignOperation assignOp | + def = assignOp and + assignOp.getLValue() = v.getAnAccess() and + result = getTruncatedLowerBounds(assignOp) + ) + or + exists(IncrementOperation incr, float newLB | + def = incr and + incr.getOperand() = v.getAnAccess() and + newLB = getFullyConvertedLowerBounds(incr.getOperand()) and + result = newLB + 1 + ) + or + exists(DecrementOperation decr, float newLB | + def = decr and + decr.getOperand() = v.getAnAccess() and + newLB = getFullyConvertedLowerBounds(decr.getOperand()) and + result = addRoundingDownSmall(newLB, -1) + ) + or + // Phi nodes. + result = getPhiLowerBounds(v, def) + or + // Unanalyzable definitions. + unanalyzableDefBounds(def, v, result, _) + } + + /** Only to be called by `getDefUpperBounds`. */ + private float getDefUpperBoundsImpl(RangeSsaDefinition def, StackVariable v) { + // Definitions with a defining value. + exists(Expr expr | assignmentDef(def, v, expr) | result = getFullyConvertedUpperBounds(expr)) + or + // Assignment operations with a defining value + exists(AssignOperation assignOp | + def = assignOp and + assignOp.getLValue() = v.getAnAccess() and + result = getTruncatedUpperBounds(assignOp) + ) + or + exists(IncrementOperation incr, float newUB | + def = incr and + incr.getOperand() = v.getAnAccess() and + newUB = getFullyConvertedUpperBounds(incr.getOperand()) and + result = addRoundingUpSmall(newUB, 1) + ) + or + exists(DecrementOperation decr, float newUB | + def = decr and + decr.getOperand() = v.getAnAccess() and + newUB = getFullyConvertedUpperBounds(decr.getOperand()) and + result = newUB - 1 + ) + or + // Phi nodes. + result = getPhiUpperBounds(v, def) + or + // Unanalyzable definitions. + unanalyzableDefBounds(def, v, _, result) + } + + /** + * Helper for `getDefLowerBounds` and `getDefUpperBounds`. Find the set of + * unanalyzable definitions (such as function parameters) and make their + * bounds unknown. + */ + private predicate unanalyzableDefBounds( + RangeSsaDefinition def, StackVariable v, float lb, float ub + ) { + v = def.getAVariable() and + not analyzableDef(def, v) and + lb = varMinVal(v) and + ub = varMaxVal(v) + } + + /** + * Holds if in the `branch` branch of a guard `guard` involving `v`, + * we know that `v` is not NaN, and therefore it is safe to make range + * inferences about `v`. + */ + bindingset[guard, v, branch] + predicate nonNanGuardedVariable(Expr guard, VariableAccess v, boolean branch) { + Util::getVariableRangeType(v.getTarget()) instanceof IntegralType + or + Util::getVariableRangeType(v.getTarget()) instanceof FloatingPointType and + v instanceof NonNanVariableAccess + or + // The reason the following case is here is to ensure that when we say + // `if (x > 5) { ...then... } else { ...else... }` + // it is ok to conclude that `x > 5` in the `then`, (though not safe + // to conclude that x <= 5 in `else`) even if we had no prior + // knowledge of `x` not being `NaN`. + nanExcludingComparison(guard, branch) + } + + /** + * If the guard is a comparison of the form `p*v + q r`, then this + * predicate uses the bounds information for `r` to compute a lower bound + * for `v`. + */ + private predicate lowerBoundFromGuard(Expr guard, VariableAccess v, float lb, boolean branch) { + exists(float childLB, Util::RelationStrictness strictness | + boundFromGuard(guard, v, childLB, true, strictness, branch) + | + if nonNanGuardedVariable(guard, v, branch) + then + if + strictness = Util::Nonstrict() or + not Util::getVariableRangeType(v.getTarget()) instanceof IntegralType + then lb = childLB + else lb = childLB + 1 + else lb = varMinVal(v.getTarget()) + ) + } + + /** + * If the guard is a comparison of the form `p*v + q r`, then this + * predicate uses the bounds information for `r` to compute a upper bound + * for `v`. + */ + private predicate upperBoundFromGuard(Expr guard, VariableAccess v, float ub, boolean branch) { + exists(float childUB, Util::RelationStrictness strictness | + boundFromGuard(guard, v, childUB, false, strictness, branch) + | + if nonNanGuardedVariable(guard, v, branch) + then + if + strictness = Util::Nonstrict() or + not Util::getVariableRangeType(v.getTarget()) instanceof IntegralType + then ub = childUB + else ub = childUB - 1 + else ub = varMaxVal(v.getTarget()) + ) + } + + /** + * This predicate simplifies the results returned by + * `linearBoundFromGuard`. + */ + private predicate boundFromGuard( + Expr guard, VariableAccess v, float boundValue, boolean isLowerBound, + Util::RelationStrictness strictness, boolean branch + ) { + exists(float p, float q, float r, boolean isLB | + linearBoundFromGuard(guard, v, p, q, r, isLB, strictness, branch) and + boundValue = (r - q) / p + | + // If the multiplier is negative then the direction of the comparison + // needs to be flipped. + p > 0 and isLowerBound = isLB + or + p < 0 and isLowerBound = isLB.booleanNot() + ) + or + // When `!e` is true, we know that `0 <= e <= 0` + exists(float p, float q, Expr e | + Util::linearAccess(e, v, p, q) and + Util::eqZeroWithNegate(guard, e, true, branch) and + boundValue = (0.0 - q) / p and + isLowerBound = [false, true] and + strictness = Util::Nonstrict() + ) + } + + /** + * This predicate finds guards of the form `p*v + q < r or p*v + q == r` + * and decomposes them into a tuple of values which can be used to deduce a + * lower or upper bound for `v`. + */ + private predicate linearBoundFromGuard( + ComparisonOperation guard, VariableAccess v, float p, float q, float boundValue, + boolean isLowerBound, // Is this a lower or an upper bound? + Util::RelationStrictness strictness, boolean branch // Which control-flow branch is this bound valid on? + ) { + // For the comparison x < RHS, we create two bounds: + // + // 1. x < upperbound(RHS) + // 2. x >= typeLowerBound(RHS.getUnspecifiedType()) + // + exists(Expr lhs, Expr rhs, Util::RelationDirection dir, Util::RelationStrictness st | + Util::linearAccess(lhs, v, p, q) and + Util::relOpWithSwapAndNegate(guard, lhs, rhs, dir, st, branch) + | + isLowerBound = Util::directionIsGreater(dir) and + strictness = st and + getBounds(rhs, boundValue, isLowerBound) + or + isLowerBound = Util::directionIsLesser(dir) and + strictness = Util::Nonstrict() and + exprTypeBounds(rhs, boundValue, isLowerBound) + ) + or + // For x == RHS, we create the following bounds: + // + // 1. x <= upperbound(RHS) + // 2. x >= lowerbound(RHS) + // + exists(Expr lhs, Expr rhs | + Util::linearAccess(lhs, v, p, q) and + Util::eqOpWithSwapAndNegate(guard, lhs, rhs, true, branch) and + getBounds(rhs, boundValue, isLowerBound) and + strictness = Util::Nonstrict() + ) + // x != RHS and !x are handled elsewhere + } + + /** Utility for `linearBoundFromGuard`. */ + private predicate getBounds(Expr expr, float boundValue, boolean isLowerBound) { + isLowerBound = true and boundValue = getFullyConvertedLowerBounds(expr) + or + isLowerBound = false and boundValue = getFullyConvertedUpperBounds(expr) + } + + /** Utility for `linearBoundFromGuard`. */ + private predicate exprTypeBounds(Expr expr, float boundValue, boolean isLowerBound) { + isLowerBound = true and boundValue = exprMinVal(expr.getFullyConverted()) + or + isLowerBound = false and boundValue = exprMaxVal(expr.getFullyConverted()) + } + + /** + * Holds if `(v, phi)` ensures that `access` is not equal to `neConstant`. For + * example, the condition `if (x + 1 != 3)` ensures that `x` is not equal to 2. + * Only integral types are supported. + */ + private predicate isNEPhi( + Variable v, RangeSsaDefinition phi, VariableAccess access, float neConstant + ) { + exists( + ComparisonOperation cmp, boolean branch, Expr linearExpr, Expr rExpr, float p, float q, + float r + | + phi.isGuardPhi(v, access, cmp, branch) and + Util::eqOpWithSwapAndNegate(cmp, linearExpr, rExpr, false, branch) and + v.getUnspecifiedType() instanceof IntegralOrEnumType and // Float `!=` is too imprecise + r = getValue(rExpr).toFloat() and + Util::linearAccess(linearExpr, access, p, q) and + neConstant = (r - q) / p + ) + or + exists(Expr op, boolean branch, Expr linearExpr, float p, float q | + phi.isGuardPhi(v, access, op, branch) and + Util::eqZeroWithNegate(op, linearExpr, false, branch) and + v.getUnspecifiedType() instanceof IntegralOrEnumType and // Float `!` is too imprecise + Util::linearAccess(linearExpr, access, p, q) and + neConstant = (0.0 - q) / p + ) + } + + /** + * Holds if `(v, phi)` constrains the value of `access` but in a way that + * doesn't allow this library to constrain the upper or lower bounds of + * `access`. An example is `if (x != y)` if neither `x` nor `y` is a + * compile-time constant. + */ + private predicate isUnsupportedGuardPhi(Variable v, RangeSsaDefinition phi, VariableAccess access) { + exists(Expr cmp, boolean branch | + Util::eqOpWithSwapAndNegate(cmp, _, _, false, branch) + or + Util::eqZeroWithNegate(cmp, _, false, branch) + | + phi.isGuardPhi(v, access, cmp, branch) and + not isNEPhi(v, phi, access, _) + ) + } + + /** + * Gets the upper bound of the expression, if the expression is guarded. + * An upper bound can only be found, if a guard phi node can be found, and the + * expression has only one immediate predecessor. + */ + private float getGuardedUpperBound(VariableAccess guardedAccess) { + exists( + RangeSsaDefinition def, StackVariable v, VariableAccess guardVa, Expr guard, boolean branch + | + def.isGuardPhi(v, guardVa, guard, branch) and + // If the basic block for the variable access being examined has + // more than one predecessor, the guard phi node could originate + // from one of the predecessors. This is because the guard phi + // node is attached to the block at the end of the edge and not on + // the actual edge. It is therefore not possible to determine which + // edge the guard phi node belongs to. The predicate below ensures + // that there is one predecessor, albeit somewhat conservative. + exists(unique(BasicBlock b | b = def.(BasicBlock).getAPredecessor())) and + guardedAccess = def.getAUse(v) and + result = max(float ub | upperBoundFromGuard(guard, guardVa, ub, branch)) and + not convertedExprMightOverflow(guard.getAChild+()) + ) + } + + cached + private module SimpleRangeAnalysisCached { + /** + * Gets the lower bound of the expression. + * + * Note: expressions in C/C++ are often implicitly or explicitly cast to a + * different result type. Such casts can cause the value of the expression + * to overflow or to be truncated. This predicate computes the lower bound + * of the expression without including the effect of the casts. To compute + * the lower bound of the expression after all the casts have been applied, + * call `lowerBound` like this: + * + * `lowerBound(expr.getFullyConverted())` + */ + cached + float lowerBound(Expr expr) { + // Combine the lower bounds returned by getTruncatedLowerBounds into a + // single minimum value. + result = min(float lb | lb = getTruncatedLowerBounds(expr) | lb) + } + + /** + * Gets the upper bound of the expression. + * + * Note: expressions in C/C++ are often implicitly or explicitly cast to a + * different result type. Such casts can cause the value of the expression + * to overflow or to be truncated. This predicate computes the upper bound + * of the expression without including the effect of the casts. To compute + * the upper bound of the expression after all the casts have been applied, + * call `upperBound` like this: + * + * `upperBound(expr.getFullyConverted())` + */ + cached + float upperBound(Expr expr) { + // Combine the upper bounds returned by getTruncatedUpperBounds and + // getGuardedUpperBound into a single maximum value + result = min([max(getTruncatedUpperBounds(expr)), getGuardedUpperBound(expr)]) + } + + /** Holds if the upper bound of `expr` may have been widened. This means the upper bound is in practice likely to be overly wide. */ + cached + predicate upperBoundMayBeWidened(Expr e) { + isRecursiveExpr(e) and + // Widening is not a problem if the post-analysis in `getGuardedUpperBound` has overridden the widening. + // Note that the RHS of `<` may be multi-valued. + not getGuardedUpperBound(e) < getTruncatedUpperBounds(e) + } + + /** + * Holds if `expr` has a provably empty range. For example: + * + * 10 < expr and expr < 5 + * + * The range of an expression can only be empty if it can never be + * executed. For example: + * + * if (10 < x) { + * if (x < 5) { + * // Unreachable code + * return x; // x has an empty range: 10 < x && x < 5 + * } + * } + */ + cached + predicate exprWithEmptyRange(Expr expr) { + analyzableExpr(expr) and + ( + not exists(lowerBound(expr)) or + not exists(upperBound(expr)) or + lowerBound(expr) > upperBound(expr) + ) + } + + /** Holds if the definition might overflow negatively. */ + cached + predicate defMightOverflowNegatively(RangeSsaDefinition def, StackVariable v) { + getDefLowerBoundsImpl(def, v) < Util::varMinVal(v) + } + + /** Holds if the definition might overflow positively. */ + cached + predicate defMightOverflowPositively(RangeSsaDefinition def, StackVariable v) { + getDefUpperBoundsImpl(def, v) > Util::varMaxVal(v) + } + + /** + * Holds if the definition might overflow (either positively or + * negatively). + */ + cached + predicate defMightOverflow(RangeSsaDefinition def, StackVariable v) { + defMightOverflowNegatively(def, v) or + defMightOverflowPositively(def, v) + } + + /** + * Holds if `e` is an expression where the concept of overflow makes sense. + * This predicate is used to filter out some of the unanalyzable expressions + * from `exprMightOverflowPositively` and `exprMightOverflowNegatively`. + */ + pragma[inline] + private predicate exprThatCanOverflow(Expr e) { + e instanceof UnaryArithmeticOperation or + e instanceof BinaryArithmeticOperation or + e instanceof AssignArithmeticOperation or + e instanceof LShiftExpr or + e instanceof AssignLShiftExpr + } + + /** + * Holds if the expression might overflow negatively. This predicate + * does not consider the possibility that the expression might overflow + * due to a conversion. + */ + cached + predicate exprMightOverflowNegatively(Expr expr) { + getLowerBoundsImpl(expr) < Util::exprMinVal(expr) + or + // The lower bound of the expression `x--` is the same as the lower + // bound of `x`, so the standard logic (above) does not work for + // detecting whether it might overflow. + getLowerBoundsImpl(expr.(PostfixDecrExpr)) = Util::exprMinVal(expr) + or + // We can't conclude that any unanalyzable expression might overflow. This + // is because there are many expressions that the range analysis doesn't + // handle, but where the concept of overflow doesn't make sense. + exprThatCanOverflow(expr) and not analyzableExpr(expr) + } + + /** + * Holds if the expression might overflow negatively. Conversions + * are also taken into account. For example the expression + * `(int16)(x+y)` might overflow due to the `(int16)` cast, rather than + * due to the addition. + */ + cached + predicate convertedExprMightOverflowNegatively(Expr expr) { + exprMightOverflowNegatively(expr) or + convertedExprMightOverflowNegatively(expr.getConversion()) + } + + /** + * Holds if the expression might overflow positively. This predicate + * does not consider the possibility that the expression might overflow + * due to a conversion. + */ + cached + predicate exprMightOverflowPositively(Expr expr) { + getUpperBoundsImpl(expr) > Util::exprMaxVal(expr) + or + // The upper bound of the expression `x++` is the same as the upper + // bound of `x`, so the standard logic (above) does not work for + // detecting whether it might overflow. + getUpperBoundsImpl(expr.(PostfixIncrExpr)) = Util::exprMaxVal(expr) + } + + /** + * Holds if the expression might overflow positively. Conversions + * are also taken into account. For example the expression + * `(int16)(x+y)` might overflow due to the `(int16)` cast, rather than + * due to the addition. + */ + cached + predicate convertedExprMightOverflowPositively(Expr expr) { + exprMightOverflowPositively(expr) or + convertedExprMightOverflowPositively(expr.getConversion()) + } + + /** + * Holds if the expression might overflow (either positively or + * negatively). The possibility that the expression might overflow + * due to an implicit or explicit cast is also considered. + */ + cached + predicate convertedExprMightOverflow(Expr expr) { + convertedExprMightOverflowNegatively(expr) or + convertedExprMightOverflowPositively(expr) + } + } + + /** + * Gets the truncated lower bounds of the fully converted expression. + */ + float getFullyConvertedLowerBounds(Expr expr) { + result = getTruncatedLowerBounds(expr.getFullyConverted()) + } + + /** + * Gets the truncated upper bounds of the fully converted expression. + */ + float getFullyConvertedUpperBounds(Expr expr) { + result = getTruncatedUpperBounds(expr.getFullyConverted()) + } + + /** + * Get the lower bounds for a `RangeSsaDefinition`. Most of the work is + * done by `getDefLowerBoundsImpl`, but this is where widening is applied + * to prevent the analysis from exploding due to a recursive definition. + */ + float getDefLowerBounds(RangeSsaDefinition def, StackVariable v) { + exists(float newLB, float truncatedLB | + newLB = getDefLowerBoundsImpl(def, v) and + if Util::varMinVal(v) <= newLB and newLB <= Util::varMaxVal(v) + then truncatedLB = newLB + else truncatedLB = Util::varMinVal(v) + | + // Widening: check whether the new lower bound is from a source which + // depends recursively on the current definition. + if isRecursiveDef(def, v) + then + // The new lower bound is from a recursive source, so we round + // down to one of a limited set of values to prevent the + // recursion from exploding. + result = + max(float widenLB | + widenLB = wideningLowerBounds(Util::getVariableRangeType(v)) and + not widenLB > truncatedLB + | + widenLB + ) + else result = truncatedLB + ) + or + // The definition might overflow positively and wrap. If so, the lower + // bound is `typeLowerBound`. + defMightOverflowPositively(def, v) and result = Util::varMinVal(v) + } + + /** See comment for `getDefLowerBounds`, above. */ + float getDefUpperBounds(RangeSsaDefinition def, StackVariable v) { + exists(float newUB, float truncatedUB | + newUB = getDefUpperBoundsImpl(def, v) and + if Util::varMinVal(v) <= newUB and newUB <= Util::varMaxVal(v) + then truncatedUB = newUB + else truncatedUB = Util::varMaxVal(v) + | + // Widening: check whether the new upper bound is from a source which + // depends recursively on the current definition. + if isRecursiveDef(def, v) + then + // The new upper bound is from a recursive source, so we round + // up to one of a fixed set of values to prevent the recursion + // from exploding. + result = + min(float widenUB | + widenUB = wideningUpperBounds(Util::getVariableRangeType(v)) and + not widenUB < truncatedUB + | + widenUB + ) + else result = truncatedUB + ) + or + // The definition might overflow negatively and wrap. If so, the upper + // bound is `typeUpperBound`. + defMightOverflowNegatively(def, v) and result = Util::varMaxVal(v) + } +} diff --git a/cpp/common/src/codingstandards/cpp/SimpleRangeAnalysisCustomizations.qll b/cpp/common/src/codingstandards/cpp/SimpleRangeAnalysisCustomizations.qll index 5144f63dc2..2688452d28 100644 --- a/cpp/common/src/codingstandards/cpp/SimpleRangeAnalysisCustomizations.qll +++ b/cpp/common/src/codingstandards/cpp/SimpleRangeAnalysisCustomizations.qll @@ -14,6 +14,45 @@ import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils import experimental.semmle.code.cpp.rangeanalysis.extensions.ConstantBitwiseAndExprRange private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr +// Disabled, causing performance issues in grpc: +/* +private class DivByConstantExpr extends SimpleRangeAnalysisExpr, DivExpr { + float quotient; + + DivByConstantExpr() { + quotient = evaluateConstantExpr(getRightOperand()) + } + + override predicate dependsOnChild(Expr e) { + e = getLeftOperand() + } + + override float getLowerBounds() { + exists(float numerator | + result = numerator / quotient and + if (quotient > 0) then + // x / y where and y is positive scales the UB/LB. + numerator = getFullyConvertedLowerBounds(getLeftOperand()) + else + // x / -y where and -y is negative will invert and scale the UB/LB. + numerator = getFullyConvertedUpperBounds(getLeftOperand()) + ) + } + + override float getUpperBounds() { + exists(float numerator | + result = numerator / quotient and + if (quotient > 0) then + // x / y where and y is positive scales the UB/LB. + numerator = getFullyConvertedUpperBounds(getLeftOperand()) + else + // x / -y where and -y is negative will invert and scale the UB/LB. + numerator = getFullyConvertedLowerBounds(getLeftOperand()) + ) + } +} + */ + /** * A range analysis extension that support bitwise `|` and `|=` where at least one operand is a * non-negative constant. diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/FloatingTypes2.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/FloatingTypes2.qll new file mode 100644 index 0000000000..7cdc6430a3 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/FloatingTypes2.qll @@ -0,0 +1,44 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype FloatingTypes2Query = + TPossibleMisuseOfUndetectedInfinityQuery() or + TPossibleMisuseOfUndetectedNaNQuery() + +predicate isFloatingTypes2QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `possibleMisuseOfUndetectedInfinity` query + FloatingTypes2Package::possibleMisuseOfUndetectedInfinityQuery() and + queryId = + // `@id` for the `possibleMisuseOfUndetectedInfinity` query + "c/misra/possible-misuse-of-undetected-infinity" and + ruleId = "DIR-4-15" and + category = "required" + or + query = + // `Query` instance for the `possibleMisuseOfUndetectedNaN` query + FloatingTypes2Package::possibleMisuseOfUndetectedNaNQuery() and + queryId = + // `@id` for the `possibleMisuseOfUndetectedNaN` query + "c/misra/possible-misuse-of-undetected-na-n" and + ruleId = "DIR-4-15" and + category = "required" +} + +module FloatingTypes2Package { + Query possibleMisuseOfUndetectedInfinityQuery() { + //autogenerate `Query` type + result = + // `Query` type for `possibleMisuseOfUndetectedInfinity` query + TQueryC(TFloatingTypes2PackageQuery(TPossibleMisuseOfUndetectedInfinityQuery())) + } + + Query possibleMisuseOfUndetectedNaNQuery() { + //autogenerate `Query` type + result = + // `Query` type for `possibleMisuseOfUndetectedNaN` query + TQueryC(TFloatingTypes2PackageQuery(TPossibleMisuseOfUndetectedNaNQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index 6ab695fb99..41ae2931b1 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -32,6 +32,7 @@ import Declarations8 import EssentialTypes import Expressions import FloatingTypes +import FloatingTypes2 import FunctionTypes import IO1 import IO2 @@ -112,6 +113,7 @@ newtype TCQuery = TEssentialTypesPackageQuery(EssentialTypesQuery q) or TExpressionsPackageQuery(ExpressionsQuery q) or TFloatingTypesPackageQuery(FloatingTypesQuery q) or + TFloatingTypes2PackageQuery(FloatingTypes2Query q) or TFunctionTypesPackageQuery(FunctionTypesQuery q) or TIO1PackageQuery(IO1Query q) or TIO2PackageQuery(IO2Query q) or @@ -192,6 +194,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isEssentialTypesQueryMetadata(query, queryId, ruleId, category) or isExpressionsQueryMetadata(query, queryId, ruleId, category) or isFloatingTypesQueryMetadata(query, queryId, ruleId, category) or + isFloatingTypes2QueryMetadata(query, queryId, ruleId, category) or isFunctionTypesQueryMetadata(query, queryId, ruleId, category) or isIO1QueryMetadata(query, queryId, ruleId, category) or isIO2QueryMetadata(query, queryId, ruleId, category) or diff --git a/rule_packages/c/FloatingTypes2.json b/rule_packages/c/FloatingTypes2.json new file mode 100644 index 0000000000..152ead08d3 --- /dev/null +++ b/rule_packages/c/FloatingTypes2.json @@ -0,0 +1,36 @@ +{ + "MISRA-C-2012": { + "DIR-4-15": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Evaluation of floating-point expressions shall not lead to the undetected generation of infinities.", + "kind": "path-problem", + "name": "Evaluation of floating-point expressions shall not lead to the undetected generation of infinities", + "precision": "high", + "severity": "error", + "short_name": "PossibleMisuseOfUndetectedInfinity", + "tags": [ + "correctness", + "external/misra/c/2012/amendment3" + ] + }, + { + "description": "Evaluation of floating-point expressions shall not lead to the undetected generation of NaNs.", + "kind": "path-problem", + "name": "Evaluation of floating-point expressions shall not lead to the undetected generation of NaNs", + "precision": "high", + "severity": "error", + "short_name": "PossibleMisuseOfUndetectedNaN", + "tags": [ + "correctness", + "external/misra/c/2012/amendment3" + ] + } + ], + "title": "Evaluation of floating-point expressions shall not lead to the undetected generation of infinities and NaNs" + } + } +} \ No newline at end of file From 16d44f1ae793cbdcca2854bf610cd8f0d707776c Mon Sep 17 00:00:00 2001 From: MichaelRFairhurst <1627771+MichaelRFairhurst@users.noreply.github.com> Date: Sat, 1 Feb 2025 03:15:52 +0000 Subject: [PATCH 173/370] Upgrading `github/codeql` dependency to 2.19.4 --- c/cert/src/codeql-pack.lock.yml | 20 +++++++++---------- c/cert/src/qlpack.yml | 2 +- c/cert/test/codeql-pack.lock.yml | 20 +++++++++---------- c/common/src/codeql-pack.lock.yml | 20 +++++++++---------- c/common/src/qlpack.yml | 2 +- c/common/test/codeql-pack.lock.yml | 20 +++++++++---------- c/misra/src/codeql-pack.lock.yml | 20 +++++++++---------- c/misra/src/qlpack.yml | 2 +- c/misra/test/codeql-pack.lock.yml | 20 +++++++++---------- cpp/autosar/src/codeql-pack.lock.yml | 20 +++++++++---------- cpp/autosar/src/qlpack.yml | 2 +- cpp/autosar/test/codeql-pack.lock.yml | 20 +++++++++---------- cpp/cert/src/codeql-pack.lock.yml | 20 +++++++++---------- cpp/cert/src/qlpack.yml | 2 +- cpp/cert/test/codeql-pack.lock.yml | 20 +++++++++---------- cpp/common/src/codeql-pack.lock.yml | 20 +++++++++---------- cpp/common/src/qlpack.yml | 2 +- cpp/common/test/codeql-pack.lock.yml | 20 +++++++++---------- cpp/misra/src/codeql-pack.lock.yml | 20 +++++++++---------- cpp/misra/src/qlpack.yml | 2 +- cpp/misra/test/codeql-pack.lock.yml | 20 +++++++++---------- cpp/report/src/codeql-pack.lock.yml | 20 +++++++++---------- cpp/report/src/qlpack.yml | 2 +- .../queries/codeql-pack.lock.yml | 20 +++++++++---------- scripts/generate_modules/queries/qlpack.yml | 2 +- supported_codeql_configs.json | 6 +++--- 26 files changed, 172 insertions(+), 172 deletions(-) diff --git a/c/cert/src/codeql-pack.lock.yml b/c/cert/src/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/c/cert/src/codeql-pack.lock.yml +++ b/c/cert/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/c/cert/src/qlpack.yml b/c/cert/src/qlpack.yml index d5ba524b14..6e023bc238 100644 --- a/c/cert/src/qlpack.yml +++ b/c/cert/src/qlpack.yml @@ -5,4 +5,4 @@ suites: codeql-suites license: MIT dependencies: codeql/common-c-coding-standards: '*' - codeql/cpp-all: 1.4.2 + codeql/cpp-all: 2.1.1 diff --git a/c/cert/test/codeql-pack.lock.yml b/c/cert/test/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/c/cert/test/codeql-pack.lock.yml +++ b/c/cert/test/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/c/common/src/codeql-pack.lock.yml b/c/common/src/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/c/common/src/codeql-pack.lock.yml +++ b/c/common/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/c/common/src/qlpack.yml b/c/common/src/qlpack.yml index e775358108..9188ad8bda 100644 --- a/c/common/src/qlpack.yml +++ b/c/common/src/qlpack.yml @@ -3,4 +3,4 @@ version: 2.42.0-dev license: MIT dependencies: codeql/common-cpp-coding-standards: '*' - codeql/cpp-all: 1.4.2 + codeql/cpp-all: 2.1.1 diff --git a/c/common/test/codeql-pack.lock.yml b/c/common/test/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/c/common/test/codeql-pack.lock.yml +++ b/c/common/test/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/c/misra/src/codeql-pack.lock.yml b/c/misra/src/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/c/misra/src/codeql-pack.lock.yml +++ b/c/misra/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/c/misra/src/qlpack.yml b/c/misra/src/qlpack.yml index 0ed5ef8b97..721a052e6b 100644 --- a/c/misra/src/qlpack.yml +++ b/c/misra/src/qlpack.yml @@ -6,4 +6,4 @@ license: MIT default-suite-file: codeql-suites/misra-c-default.qls dependencies: codeql/common-c-coding-standards: '*' - codeql/cpp-all: 1.4.2 + codeql/cpp-all: 2.1.1 diff --git a/c/misra/test/codeql-pack.lock.yml b/c/misra/test/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/c/misra/test/codeql-pack.lock.yml +++ b/c/misra/test/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/cpp/autosar/src/codeql-pack.lock.yml b/cpp/autosar/src/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/cpp/autosar/src/codeql-pack.lock.yml +++ b/cpp/autosar/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/cpp/autosar/src/qlpack.yml b/cpp/autosar/src/qlpack.yml index 80f6d1b0d2..e4d17b7309 100644 --- a/cpp/autosar/src/qlpack.yml +++ b/cpp/autosar/src/qlpack.yml @@ -5,4 +5,4 @@ suites: codeql-suites license: MIT dependencies: codeql/common-cpp-coding-standards: '*' - codeql/cpp-all: 1.4.2 + codeql/cpp-all: 2.1.1 diff --git a/cpp/autosar/test/codeql-pack.lock.yml b/cpp/autosar/test/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/cpp/autosar/test/codeql-pack.lock.yml +++ b/cpp/autosar/test/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/cpp/cert/src/codeql-pack.lock.yml b/cpp/cert/src/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/cpp/cert/src/codeql-pack.lock.yml +++ b/cpp/cert/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/cpp/cert/src/qlpack.yml b/cpp/cert/src/qlpack.yml index 3005c15ec3..b0645353f6 100644 --- a/cpp/cert/src/qlpack.yml +++ b/cpp/cert/src/qlpack.yml @@ -4,5 +4,5 @@ description: CERT C++ 2016 suites: codeql-suites license: MIT dependencies: - codeql/cpp-all: 1.4.2 + codeql/cpp-all: 2.1.1 codeql/common-cpp-coding-standards: '*' diff --git a/cpp/cert/test/codeql-pack.lock.yml b/cpp/cert/test/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/cpp/cert/test/codeql-pack.lock.yml +++ b/cpp/cert/test/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/cpp/common/src/codeql-pack.lock.yml b/cpp/common/src/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/cpp/common/src/codeql-pack.lock.yml +++ b/cpp/common/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/cpp/common/src/qlpack.yml b/cpp/common/src/qlpack.yml index d97b322120..4b4619e6b9 100644 --- a/cpp/common/src/qlpack.yml +++ b/cpp/common/src/qlpack.yml @@ -2,6 +2,6 @@ name: codeql/common-cpp-coding-standards version: 2.42.0-dev license: MIT dependencies: - codeql/cpp-all: 1.4.2 + codeql/cpp-all: 2.1.1 dataExtensions: - ext/*.model.yml diff --git a/cpp/common/test/codeql-pack.lock.yml b/cpp/common/test/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/cpp/common/test/codeql-pack.lock.yml +++ b/cpp/common/test/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/cpp/misra/src/codeql-pack.lock.yml b/cpp/misra/src/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/cpp/misra/src/codeql-pack.lock.yml +++ b/cpp/misra/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/cpp/misra/src/qlpack.yml b/cpp/misra/src/qlpack.yml index fc3162ffb4..2c8f21a82f 100644 --- a/cpp/misra/src/qlpack.yml +++ b/cpp/misra/src/qlpack.yml @@ -5,4 +5,4 @@ default-suite: codeql-suites/misra-cpp-default.qls license: MIT dependencies: codeql/common-cpp-coding-standards: '*' - codeql/cpp-all: 1.4.2 + codeql/cpp-all: 2.1.1 diff --git a/cpp/misra/test/codeql-pack.lock.yml b/cpp/misra/test/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/cpp/misra/test/codeql-pack.lock.yml +++ b/cpp/misra/test/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/cpp/report/src/codeql-pack.lock.yml b/cpp/report/src/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/cpp/report/src/codeql-pack.lock.yml +++ b/cpp/report/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/cpp/report/src/qlpack.yml b/cpp/report/src/qlpack.yml index 1a8ea75e77..3203133ffc 100644 --- a/cpp/report/src/qlpack.yml +++ b/cpp/report/src/qlpack.yml @@ -2,4 +2,4 @@ name: codeql/report-cpp-coding-standards version: 2.42.0-dev license: MIT dependencies: - codeql/cpp-all: 1.4.2 + codeql/cpp-all: 2.1.1 diff --git a/scripts/generate_modules/queries/codeql-pack.lock.yml b/scripts/generate_modules/queries/codeql-pack.lock.yml index 910a6e060e..ab9a39f9c1 100644 --- a/scripts/generate_modules/queries/codeql-pack.lock.yml +++ b/scripts/generate_modules/queries/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 1.4.2 + version: 2.1.1 codeql/dataflow: - version: 1.1.1 + version: 1.1.6 codeql/mad: - version: 1.0.7 + version: 1.0.12 codeql/rangeanalysis: - version: 1.0.7 + version: 1.0.12 codeql/ssa: - version: 1.0.7 + version: 1.0.12 codeql/tutorial: - version: 1.0.7 + version: 1.0.12 codeql/typeflow: - version: 1.0.7 + version: 1.0.12 codeql/typetracking: - version: 1.0.7 + version: 1.0.12 codeql/util: - version: 1.0.7 + version: 1.0.12 codeql/xml: - version: 1.0.7 + version: 1.0.12 compiled: false diff --git a/scripts/generate_modules/queries/qlpack.yml b/scripts/generate_modules/queries/qlpack.yml index 88a48269e7..d2c729dfb9 100644 --- a/scripts/generate_modules/queries/qlpack.yml +++ b/scripts/generate_modules/queries/qlpack.yml @@ -2,4 +2,4 @@ name: codeql/standard-library-extraction-cpp-coding-standards version: 0.0.0 license: MIT dependencies: - codeql/cpp-all: 1.4.2 + codeql/cpp-all: 2.1.1 diff --git a/supported_codeql_configs.json b/supported_codeql_configs.json index b143f67fe9..77534bd53d 100644 --- a/supported_codeql_configs.json +++ b/supported_codeql_configs.json @@ -1,9 +1,9 @@ { "supported_environment": [ { - "codeql_cli": "2.18.4", - "codeql_standard_library": "codeql-cli/v2.18.4", - "codeql_cli_bundle": "codeql-bundle-v2.18.4" + "codeql_cli": "2.19.4", + "codeql_standard_library": "codeql-cli/v2.19.4", + "codeql_cli_bundle": "codeql-bundle-v2.19.4" } ], "supported_language": [ From 59ebba0f3c52d090b1c07c0e732db7d740485870 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 3 Feb 2025 19:11:59 -0800 Subject: [PATCH 174/370] Support guards isinf(), isfinite(), isnan(), etc --- .../PossibleMisuseOfUndetectedInfinity.ql | 12 + .../DIR-4-15/PossibleMisuseOfUndetectedNaN.ql | 41 ++- ...ossibleMisuseOfUndetectedInfinity.expected | 59 +++- .../PossibleMisuseOfUndetectedNaN.expected | 43 ++- c/misra/test/rules/DIR-4-15/test.c | 99 +++++- .../src/codingstandards/cpp/FloatingPoint.qll | 317 +++++++++++++++++- .../cpp/RestrictedRangeAnalysis.qll | 22 +- 7 files changed, 521 insertions(+), 72 deletions(-) diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql index 84a3fbfd3c..97dd251083 100644 --- a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql @@ -44,6 +44,18 @@ module InvalidInfinityUsage implements DataFlow::ConfigSig { exprMayEqualInfinity(node.asExpr(), _) } + predicate isBarrierOut(DataFlow::Node node) { + guardedNotFPClass(node.asExpr(), TInfinite()) + or + exists(Expr e | + e.getType() instanceof IntegralType and + e = node.asConvertedExpr() + ) + or + // Sinks are places where Infinity produce a finite value + isSink(node) + } + /** * An additional flow step to handle operations which propagate Infinity. * diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql index 6962a1c36d..036d470247 100644 --- a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql @@ -89,7 +89,6 @@ class InvalidOperationExpr extends BinaryOperation { } module InvalidNaNUsage implements DataFlow::ConfigSig { - /** * An expression which has non-NaN inputs and may produce a NaN output. */ @@ -108,6 +107,15 @@ module InvalidNaNUsage implements DataFlow::ConfigSig { node.asExpr() instanceof InvalidOperationExpr } + predicate isBarrierOut(DataFlow::Node node) { + guardedNotFPClass(node.asExpr(), TNaN()) + or + exists(Expr e | + e.getType() instanceof IntegralType and + e = node.asConvertedExpr() + ) + } + /** * Add an additional flow step to handle NaN propagation through floating point operations. */ @@ -120,21 +128,24 @@ module InvalidNaNUsage implements DataFlow::ConfigSig { } predicate isSink(DataFlow::Node node) { - // Case 1: NaNs shall not be compared, except to themselves - exists(ComparisonOperation cmp | - node.asExpr() = cmp.getAnOperand() and - not hashCons(cmp.getLeftOperand()) = hashCons(cmp.getRightOperand()) - ) - or - // Case 2: NaNs and infinities shall not be cast to integers - exists(Conversion c | - node.asExpr() = c.getUnconverted() and - c.getExpr().getType() instanceof FloatingPointType and - c.getType() instanceof IntegralType + not guardedNotFPClass(node.asExpr(), TNaN()) and + ( + // Case 1: NaNs shall not be compared, except to themselves + exists(ComparisonOperation cmp | + node.asExpr() = cmp.getAnOperand() and + not hashCons(cmp.getLeftOperand()) = hashCons(cmp.getRightOperand()) + ) + or + // Case 2: NaNs and infinities shall not be cast to integers + exists(Conversion c | + node.asExpr() = c.getUnconverted() and + c.getExpr().getType() instanceof FloatingPointType and + c.getType() instanceof IntegralType + ) + //or + //// Case 4: Functions shall not return NaNs or infinities + //exists(ReturnStmt ret | node.asExpr() = ret.getExpr()) ) - //or - //// Case 4: Functions shall not return NaNs or infinities - //exists(ReturnStmt ret | node.asExpr() = ret.getExpr()) } } diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected index 78f4c6baec..75534df6a0 100644 --- a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected +++ b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected @@ -1,5 +1,6 @@ edges | test.c:8:14:8:20 | ... / ... | test.c:8:14:8:20 | ... / ... | provenance | | +| test.c:8:14:8:20 | ... / ... | test.c:9:14:9:16 | - ... | provenance | Config | | test.c:8:14:8:20 | ... / ... | test.c:12:8:12:9 | l2 | provenance | | | test.c:8:14:8:20 | ... / ... | test.c:18:3:18:9 | l2 | provenance | | | test.c:8:14:8:20 | ... / ... | test.c:27:19:27:20 | l2 | provenance | | @@ -9,8 +10,17 @@ edges | test.c:9:14:9:16 | - ... | test.c:28:19:28:20 | l3 | provenance | | | test.c:31:14:32:15 | ... / ... | test.c:31:14:32:15 | ... / ... | provenance | | | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | provenance | | -| test.c:33:14:33:22 | ... / ... | test.c:33:14:33:22 | ... / ... | provenance | | -| test.c:33:14:33:22 | ... / ... | test.c:39:3:39:9 | l8 | provenance | | +| test.c:77:15:77:21 | ... / ... | test.c:77:15:77:21 | ... / ... | provenance | | +| test.c:77:15:77:21 | ... / ... | test.c:79:5:79:12 | l12 | provenance | | +| test.c:77:15:77:21 | ... / ... | test.c:87:5:87:12 | l12 | provenance | | +| test.c:77:15:77:21 | ... / ... | test.c:91:5:91:12 | l12 | provenance | | +| test.c:77:15:77:21 | ... / ... | test.c:93:5:93:12 | l12 | provenance | | +| test.c:77:15:77:21 | ... / ... | test.c:99:5:99:12 | l12 | provenance | | +| test.c:77:15:77:21 | ... / ... | test.c:105:5:105:12 | l12 | provenance | | +| test.c:77:15:77:21 | ... / ... | test.c:111:5:111:12 | l12 | provenance | | +| test.c:77:15:77:21 | ... / ... | test.c:114:16:114:23 | l12 | provenance | | +| test.c:77:15:77:21 | ... / ... | test.c:117:23:117:30 | l12 | provenance | | +| test.c:77:15:77:21 | ... / ... | test.c:120:20:120:27 | l12 | provenance | | nodes | test.c:8:14:8:20 | ... / ... | semmle.label | ... / ... | | test.c:8:14:8:20 | ... / ... | semmle.label | ... / ... | @@ -24,25 +34,46 @@ nodes | test.c:28:19:28:20 | l3 | semmle.label | l3 | | test.c:31:14:32:15 | ... / ... | semmle.label | ... / ... | | test.c:31:14:32:15 | ... / ... | semmle.label | ... / ... | -| test.c:33:14:33:22 | ... / ... | semmle.label | ... / ... | -| test.c:33:14:33:22 | ... / ... | semmle.label | ... / ... | | test.c:38:3:38:9 | l7 | semmle.label | l7 | -| test.c:39:3:39:9 | l8 | semmle.label | l8 | -| test.c:61:5:61:19 | ... / ... | semmle.label | ... / ... | -| test.c:66:5:66:21 | ... / ... | semmle.label | ... / ... | -| test.c:72:14:72:30 | ... / ... | semmle.label | ... / ... | -| test.c:75:18:75:34 | ... / ... | semmle.label | ... / ... | +| test.c:61:5:61:18 | ... / ... | semmle.label | ... / ... | +| test.c:66:5:66:20 | ... / ... | semmle.label | ... / ... | +| test.c:72:14:72:29 | ... / ... | semmle.label | ... / ... | +| test.c:75:18:75:33 | ... / ... | semmle.label | ... / ... | +| test.c:77:15:77:21 | ... / ... | semmle.label | ... / ... | +| test.c:77:15:77:21 | ... / ... | semmle.label | ... / ... | +| test.c:79:5:79:12 | l12 | semmle.label | l12 | +| test.c:87:5:87:12 | l12 | semmle.label | l12 | +| test.c:91:5:91:12 | l12 | semmle.label | l12 | +| test.c:93:5:93:12 | l12 | semmle.label | l12 | +| test.c:99:5:99:12 | l12 | semmle.label | l12 | +| test.c:105:5:105:12 | l12 | semmle.label | l12 | +| test.c:111:5:111:12 | l12 | semmle.label | l12 | +| test.c:114:16:114:23 | l12 | semmle.label | l12 | +| test.c:117:23:117:30 | l12 | semmle.label | l12 | +| test.c:120:20:120:27 | l12 | semmle.label | l12 | subpaths #select | test.c:12:8:12:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:12:8:12:9 | l2 | Invalid usage of possible $@. | test.c:8:14:8:20 | ... / ... | infinity | +| test.c:13:8:13:9 | l3 | test.c:8:14:8:20 | ... / ... | test.c:13:8:13:9 | l3 | Invalid usage of possible $@. | test.c:8:14:8:20 | ... / ... | infinity | | test.c:13:8:13:9 | l3 | test.c:9:14:9:16 | - ... | test.c:13:8:13:9 | l3 | Invalid usage of possible $@. | test.c:9:14:9:16 | - ... | infinity | | test.c:18:8:18:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:18:3:18:9 | l2 | Invalid usage of possible $@. | test.c:8:14:8:20 | ... / ... | infinity | +| test.c:19:8:19:9 | l3 | test.c:8:14:8:20 | ... / ... | test.c:19:3:19:9 | l3 | Invalid usage of possible $@. | test.c:8:14:8:20 | ... / ... | infinity | | test.c:19:8:19:9 | l3 | test.c:9:14:9:16 | - ... | test.c:19:3:19:9 | l3 | Invalid usage of possible $@. | test.c:9:14:9:16 | - ... | infinity | | test.c:27:19:27:20 | l2 | test.c:8:14:8:20 | ... / ... | test.c:27:19:27:20 | l2 | Invalid usage of possible $@. | test.c:8:14:8:20 | ... / ... | infinity | +| test.c:28:19:28:20 | l3 | test.c:8:14:8:20 | ... / ... | test.c:28:19:28:20 | l3 | Invalid usage of possible $@. | test.c:8:14:8:20 | ... / ... | infinity | | test.c:28:19:28:20 | l3 | test.c:9:14:9:16 | - ... | test.c:28:19:28:20 | l3 | Invalid usage of possible $@. | test.c:9:14:9:16 | - ... | infinity | | test.c:38:8:38:9 | l7 | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | Invalid usage of possible $@. | test.c:31:14:32:15 | ... / ... | infinity | -| test.c:39:8:39:9 | l8 | test.c:33:14:33:22 | ... / ... | test.c:39:3:39:9 | l8 | Invalid usage of possible $@. | test.c:33:14:33:22 | ... / ... | infinity | -| test.c:61:12:61:18 | ... / ... | test.c:61:5:61:19 | ... / ... | test.c:61:5:61:19 | ... / ... | Invalid usage of possible $@. | test.c:61:5:61:19 | ... / ... | infinity | -| test.c:66:12:66:20 | ... / ... | test.c:66:5:66:21 | ... / ... | test.c:66:5:66:21 | ... / ... | Invalid usage of possible $@. | test.c:66:5:66:21 | ... / ... | infinity | -| test.c:72:21:72:29 | ... / ... | test.c:72:14:72:30 | ... / ... | test.c:72:14:72:30 | ... / ... | Invalid usage of possible $@. | test.c:72:14:72:30 | ... / ... | infinity | -| test.c:75:25:75:33 | ... / ... | test.c:75:18:75:34 | ... / ... | test.c:75:18:75:34 | ... / ... | Invalid usage of possible $@. | test.c:75:18:75:34 | ... / ... | infinity | +| test.c:61:11:61:17 | ... / ... | test.c:61:5:61:18 | ... / ... | test.c:61:5:61:18 | ... / ... | Invalid usage of possible $@. | test.c:61:5:61:18 | ... / ... | infinity | +| test.c:66:11:66:19 | ... / ... | test.c:66:5:66:20 | ... / ... | test.c:66:5:66:20 | ... / ... | Invalid usage of possible $@. | test.c:66:5:66:20 | ... / ... | infinity | +| test.c:72:20:72:28 | ... / ... | test.c:72:14:72:29 | ... / ... | test.c:72:14:72:29 | ... / ... | Invalid usage of possible $@. | test.c:72:14:72:29 | ... / ... | infinity | +| test.c:75:24:75:32 | ... / ... | test.c:75:18:75:33 | ... / ... | test.c:75:18:75:33 | ... / ... | Invalid usage of possible $@. | test.c:75:18:75:33 | ... / ... | infinity | +| test.c:79:10:79:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:79:5:79:12 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | +| test.c:87:10:87:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:87:5:87:12 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | +| test.c:91:10:91:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:91:5:91:12 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | +| test.c:93:10:93:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:93:5:93:12 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | +| test.c:99:10:99:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:99:5:99:12 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | +| test.c:105:10:105:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:105:5:105:12 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | +| test.c:111:10:111:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:111:5:111:12 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | +| test.c:114:21:114:23 | l12 | test.c:77:15:77:21 | ... / ... | test.c:114:16:114:23 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | +| test.c:117:28:117:30 | l12 | test.c:77:15:77:21 | ... / ... | test.c:117:23:117:30 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | +| test.c:120:25:120:27 | l12 | test.c:77:15:77:21 | ... / ... | test.c:120:20:120:27 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected index f317f236ef..e59d43d867 100644 --- a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected +++ b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected @@ -16,6 +16,15 @@ edges | test.c:33:14:33:22 | ... / ... | test.c:33:14:33:22 | ... / ... | provenance | | | test.c:33:14:33:22 | ... / ... | test.c:39:3:39:9 | l8 | provenance | | | test.c:33:14:33:22 | ... / ... | test.c:54:3:54:4 | l8 | provenance | | +| test.c:122:15:122:21 | ... / ... | test.c:122:15:122:21 | ... / ... | provenance | | +| test.c:122:15:122:21 | ... / ... | test.c:126:5:126:12 | l13 | provenance | | +| test.c:122:15:122:21 | ... / ... | test.c:132:5:132:12 | l13 | provenance | | +| test.c:122:15:122:21 | ... / ... | test.c:138:5:138:12 | l13 | provenance | | +| test.c:122:15:122:21 | ... / ... | test.c:144:5:144:12 | l13 | provenance | | +| test.c:122:15:122:21 | ... / ... | test.c:148:5:148:12 | l13 | provenance | | +| test.c:122:15:122:21 | ... / ... | test.c:154:20:154:27 | l13 | provenance | | +| test.c:122:15:122:21 | ... / ... | test.c:156:23:156:30 | l13 | provenance | | +| test.c:122:15:122:21 | ... / ... | test.c:157:16:157:23 | l13 | provenance | | nodes | test.c:27:14:27:20 | ... / ... | semmle.label | ... / ... | | test.c:27:14:27:20 | ... / ... | semmle.label | ... / ... | @@ -38,10 +47,20 @@ nodes | test.c:52:3:52:4 | l6 | semmle.label | l6 | | test.c:53:3:53:4 | l7 | semmle.label | l7 | | test.c:54:3:54:4 | l8 | semmle.label | l8 | -| test.c:61:5:61:19 | ... / ... | semmle.label | ... / ... | -| test.c:66:5:66:21 | ... / ... | semmle.label | ... / ... | -| test.c:72:14:72:30 | ... / ... | semmle.label | ... / ... | -| test.c:75:18:75:34 | ... / ... | semmle.label | ... / ... | +| test.c:61:5:61:18 | ... / ... | semmle.label | ... / ... | +| test.c:66:5:66:20 | ... / ... | semmle.label | ... / ... | +| test.c:72:14:72:29 | ... / ... | semmle.label | ... / ... | +| test.c:75:18:75:33 | ... / ... | semmle.label | ... / ... | +| test.c:122:15:122:21 | ... / ... | semmle.label | ... / ... | +| test.c:122:15:122:21 | ... / ... | semmle.label | ... / ... | +| test.c:126:5:126:12 | l13 | semmle.label | l13 | +| test.c:132:5:132:12 | l13 | semmle.label | l13 | +| test.c:138:5:138:12 | l13 | semmle.label | l13 | +| test.c:144:5:144:12 | l13 | semmle.label | l13 | +| test.c:148:5:148:12 | l13 | semmle.label | l13 | +| test.c:154:20:154:27 | l13 | semmle.label | l13 | +| test.c:156:23:156:30 | l13 | semmle.label | l13 | +| test.c:157:16:157:23 | l13 | semmle.label | l13 | subpaths #select | test.c:36:8:36:9 | l5 | test.c:27:14:27:20 | ... / ... | test.c:36:3:36:9 | l5 | Invalid usage of possible $@. | test.c:27:14:27:20 | ... / ... | NaN resulting from possible division of infinity by infinity | @@ -57,7 +76,15 @@ subpaths | test.c:52:3:52:4 | l6 | test.c:28:14:28:20 | ... / ... | test.c:52:3:52:4 | l6 | Invalid usage of possible $@. | test.c:28:14:28:20 | ... / ... | NaN resulting from possible division of infinity by infinity | | test.c:53:3:53:4 | l7 | test.c:31:14:32:15 | ... / ... | test.c:53:3:53:4 | l7 | Invalid usage of possible $@. | test.c:31:14:32:15 | ... / ... | NaN resulting from possible division of zero by zero | | test.c:54:3:54:4 | l8 | test.c:33:14:33:22 | ... / ... | test.c:54:3:54:4 | l8 | Invalid usage of possible $@. | test.c:33:14:33:22 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:61:12:61:18 | ... / ... | test.c:61:5:61:19 | ... / ... | test.c:61:5:61:19 | ... / ... | Invalid usage of possible $@. | test.c:61:5:61:19 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:66:12:66:20 | ... / ... | test.c:66:5:66:21 | ... / ... | test.c:66:5:66:21 | ... / ... | Invalid usage of possible $@. | test.c:66:5:66:21 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:72:21:72:29 | ... / ... | test.c:72:14:72:30 | ... / ... | test.c:72:14:72:30 | ... / ... | Invalid usage of possible $@. | test.c:72:14:72:30 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:75:25:75:33 | ... / ... | test.c:75:18:75:34 | ... / ... | test.c:75:18:75:34 | ... / ... | Invalid usage of possible $@. | test.c:75:18:75:34 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:61:11:61:17 | ... / ... | test.c:61:5:61:18 | ... / ... | test.c:61:5:61:18 | ... / ... | Invalid usage of possible $@. | test.c:61:5:61:18 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:66:11:66:19 | ... / ... | test.c:66:5:66:20 | ... / ... | test.c:66:5:66:20 | ... / ... | Invalid usage of possible $@. | test.c:66:5:66:20 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:72:20:72:28 | ... / ... | test.c:72:14:72:29 | ... / ... | test.c:72:14:72:29 | ... / ... | Invalid usage of possible $@. | test.c:72:14:72:29 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:75:24:75:32 | ... / ... | test.c:75:18:75:33 | ... / ... | test.c:75:18:75:33 | ... / ... | Invalid usage of possible $@. | test.c:75:18:75:33 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:126:10:126:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:126:5:126:12 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:132:10:132:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:132:5:132:12 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:138:10:138:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:138:5:138:12 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:144:10:144:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:144:5:144:12 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:148:10:148:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:148:5:148:12 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:154:25:154:27 | l13 | test.c:122:15:122:21 | ... / ... | test.c:154:20:154:27 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:156:28:156:30 | l13 | test.c:122:15:122:21 | ... / ... | test.c:156:23:156:30 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:157:21:157:23 | l13 | test.c:122:15:122:21 | ... / ... | test.c:157:16:157:23 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | diff --git a/c/misra/test/rules/DIR-4-15/test.c b/c/misra/test/rules/DIR-4-15/test.c index d634a6e594..d0f9ab5418 100644 --- a/c/misra/test/rules/DIR-4-15/test.c +++ b/c/misra/test/rules/DIR-4-15/test.c @@ -56,21 +56,104 @@ void f1(float p1) { // Guards float l9 = 0; if (l9 != 0) { - (int) (l9 / l9); // COMPLIANT: l9 is not zero + (int)(l9 / l9); // COMPLIANT: l9 is not zero } else { - (int) (l9 / l9); // NON_COMPLIANT: Casting NaN to integer + (int)(l9 / l9); // NON_COMPLIANT: Guarded to not be NaN } float l10 = 0; if (l10 == 0) { - (int) (l10 / l10); // NON_COMPLIANT: Casting NaN to integer + (int)(l10 / l10); // NON_COMPLIANT: Casting NaN to integer } else { - (int) (l10 / l10); // COMPLIANT: l10 is not zero + (int)(l10 / l10); // COMPLIANT: Guarded to not be NaN } float l11 = 0; - l11 == 0 ? (int) (l11 / l11) : 0; // NON_COMPLIANT - l11 == 0 ? 0 : (int) (l11 / l11); // COMPLIANT - l11 != 0 ? (int) (l11 / l11) : 0; // COMPLIANT - l11 != 0 ? 0 : (int) (l11 / l11); // NON_COMPLIANT + l11 == 0 ? (int)(l11 / l11) : 0; // NON_COMPLIANT + l11 == 0 ? 0 : (int)(l11 / l11); // COMPLIANT + l11 != 0 ? (int)(l11 / l11) : 0; // COMPLIANT + l11 != 0 ? 0 : (int)(l11 / l11); // NON_COMPLIANT + + float l12 = 1.0 / 0; + if (isinf(l12)) { + (int)l12; // NON_COMPLIANT: Casting Infinity to integer + } else { + (int)l12; // COMPLIANT: Guarded not to be Infinity + } + + if (!isinf(l12)) { + (int)l12; // COMPLIANT: Guarded not to be Infinity + } else { + (int)l12; // NON_COMPLIANT: Casting Infinity to integer + } + + if (isinf(l12) == 1) { + (int)l12; // NON_COMPLIANT: Must be +Infinity + } else { + (int)l12; // NON_COMPLIANT: May be -Infinity + } + + if (isfinite(l12)) { + (int)l12; // COMPLIANT: Guarded not to be Infinity + } else { + (int)l12; // NON_COMPLIANT: Casting Infinity to integer + } + + if (isnormal(l12)) { + (int)l12; // COMPLIANT: Guarded not to be Infinity + } else { + (int)l12; // NON_COMPLIANT: Casting Infinity to integer + } + + if (isnan(l12)) { + (int)l12; // COMPLIANT: Guarded not to be Infinity + } else { + (int)l12; // NON_COMPLIANT: Casting Infinity to integer + } + + isinf(l12) ? (int)l12 : 0; // NON_COMPLIANT: Check on wrong branch + isinf(l12) ? 0 : (int)l12; // COMPLIANT: Checked not infinite before use + isfinite(l12) ? (int)l12 : 0; // COMPLIANT: Checked finite before use + isfinite(l12) ? 0 : (int)l12; // NON_COMPLIANT: Checked on wrong branch + isnan(l12) ? (int)l12 + : 0; // COMPLIANT: Checked NaN, therefore not infinite, before use + isnan(l12) ? 0 : (int)l12; // NON_COMPLIANT: Check on wrong branch + + float l13 = 0.0 / 0; + if (isinf(l13)) { + (int)l13; // COMPLIANT: Guarded not to be NaN + } else { + (int)l13; // NON_COMPLIANT: Casting NaN to integer + } + + if (isinf(l13) == 1) { + (int)l13; // COMPLIANT: Guarded not to be NaN (must be +Infinity) + } else { + (int)l13; // NON_COMPLIANT: Casting NaN to integer + } + + if (isfinite(l13)) { + (int)l13; // COMPLIANT: Guarded not to be NaN + } else { + (int)l13; // NON_COMPLIANT: Casting NaN to integer + } + + if (isnormal(l13)) { + (int)l13; // COMPLIANT: Guarded not to be NaN + } else { + (int)l13; // NON_COMPLIANT: Casting NaN to integer + } + + if (isnan(l13)) { + (int)l13; // NON_COMPLIANT: Casting NaN to integer + } else { + (int)l13; // COMPLIANT: Guarded not to be NaN + } + + isinf(l13) ? (int)l13 : 0; // COMPLIANT: Checked infinite, therefore not NaN, before use + isinf(l13) ? 0 : (int)l13; // COMPLIANT: Check on wrong branch + isfinite(l13) ? (int)l13 : 0; // COMPLIANT: Checked finite before use + isfinite(l13) ? 0 : (int)l13; // NON_COMPLIANT: Checked on wrong branch + isnan(l13) ? (int)l13 : 0; // NON_COMPLIANT: Check on wrong branch + isnan(l13) ? 0 : (int)l13; // COMPLIANT: Checked not NaN before use } \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/FloatingPoint.qll b/cpp/common/src/codingstandards/cpp/FloatingPoint.qll index d143f81418..f3ba8dba18 100644 --- a/cpp/common/src/codingstandards/cpp/FloatingPoint.qll +++ b/cpp/common/src/codingstandards/cpp/FloatingPoint.qll @@ -7,6 +7,294 @@ predicate exprMayEqualZero(Expr e) { not guardedNotEqualZero(e) } +newtype TFPClassification = + TFinite() or + TNaN() or + TInfinite() + +class FPClassification extends TFPClassification { + string toString() { + this = TFinite() and + result = "finite" + or + this = TNaN() and + result = "NaN" + or + this = TInfinite() and + result = "infinite" + } +} + +newtype TFPClassificationConstraint = + /* The value may be infinite, NaN, or finite. */ + TUnclassified() or + /** + * The value must be one of: infinite, NaN, or finite. + * + * If strict is `true` then this inverts naively. For example, `!isfinite(x)` means `x` must not + * be finite. However, `!iszero(x)` is true for some finite values, and inverts to + * `TUnclassified`. + */ + TExactFPClassification(TFPClassification cls, Boolean strict) or + /* The value must not be one of: infinite, NaN, or finite. */ + TExcludeFPClassification(TFPClassification cls1) + +class FPClassificationConstraint extends TFPClassificationConstraint { + string toString() { + this = TUnclassified() and + result = "unclassified" + or + exists(FPClassification cls, Boolean strict | + this = TExactFPClassification(cls, strict) and + result = "must be " + cls.toString() + ", strict: " + strict.toString() + or + this = TExcludeFPClassification(cls) and + result = "must NOT be " + cls.toString() + ) + } + + /** + * Invert the constraint, for instance, "must be finite" becomes "must not be finite". + * + * Non-strict exact constraints are inverted to the unclassified constraint. For example, + * `iszero(x)` guarantees `x` to be finite, however, `!iszero(x)` can be true for all three + * classes of floating point values. + * + * The unclassified constraint inverts to itself. + */ + FPClassificationConstraint invert() { + // Unclassified inverts to itself. + this = TUnclassified() and result = this + or + exists(FPClassification cls | + // `!isfinite()` implies is infinite or NaN. + this = TExactFPClassification(cls, true) and + result = TExcludeFPClassification(cls) + or + // `!iszero()` implies nothing. + this = TExactFPClassification(cls, false) and + result = TUnclassified() + or + // For completeness: `!isfinite(x) ? ... : x` would imply `isfinite(x)`. + this = TExcludeFPClassification(cls) and + result = TExactFPClassification(cls, true) + ) + } + + /** + * Naively invert the constraint, for instance, "must be finite" becomes "must not be finite". + * + * Word of caution: inverting a guard condition does not necessarily invert the constraint. For + * example, `iszero(x)` guarantees `x` to be finite, however, `isnotzero(x)` does not guarantee + * `x` not to be finite. + * + * The unclassified constraint is not inverted. + */ + FPClassificationConstraint naiveInversion() { + this = TUnclassified() and result = this + or + exists(FPClassification cls | + this = TExactFPClassification(cls, _) and + result = TExcludeFPClassification(cls) + or + this = TExcludeFPClassification(cls) and + result = TExactFPClassification(cls, true) + ) + } + + predicate mustBe(FPClassification cls) { this = TExactFPClassification(cls, _) } + + predicate mustNotBe(FPClassification cls) { + this = TExcludeFPClassification(cls) + or + this = TExactFPClassification(_, _) and + not this = TExactFPClassification(cls, _) + } + + predicate mayBe(FPClassification cls) { not mustNotBe(cls) } +} + +/** + * The names of the functions or macros that classify floating point values. + * + * These names reflect a check that a value is finite, or infinite, or NaN. Finite and NaN checks + * are either strict (return true for all values in the class) or not (return true for some + * values). + * + * The infinite check is always strict, and specially, returns 1 or -1 for positive or negative + * infinity. + */ +newtype TFPClassifierName = + TClassifiesFinite(string name, boolean strict) { + strict = true and + name = ["finite" + ["", "l", "f"], "isfinite"] + or + strict = false and + name = ["isnormal", "issubnormal", "iszero"] + } or + TClassifiesNaN(string name, boolean strict) { + strict = true and + name = "isnan" + ["", "f", "l"] + or + strict = false and + name = "issignaling" + } or + TClassifiesInfinite(string name) { name = "isinf" + ["", "f", "l"] } + +class FPClassifierName extends TFPClassifierName { + string name; + boolean strict; + + FPClassifierName() { + this = TClassifiesFinite(name, strict) + or + this = TClassifiesInfinite(name) and + strict = true + or + this = TClassifiesNaN(name, strict) + } + + string toString() { result = name } + + /** The classification name, for instance, "isfinite". */ + string getName() { result = name } + + /** + * Whether the check holds for all values in the class, or only some. + * + * For instance, "isfinite" is strict because it returns true for all finite values, but + * "isnormal" is not as it returns false for some finite values. + */ + predicate isStrict() { strict = true } + + FPClassificationConstraint getConstraint() { + this = TClassifiesFinite(_, strict) and + result = TExactFPClassification(any(TFinite t), strict) + or + this = TClassifiesNaN(_, strict) and + result = TExactFPClassification(any(TNaN t), strict) + or + this = TClassifiesInfinite(_) and + // TODO: isinf() is special + result = TExactFPClassification(any(TInfinite t), false) + } +} + +/** + * An invocation of a classification function, for instance, "isfinite(x)", implemented as a macro. + */ +class FPClassifierMacroInvocation extends MacroInvocation { + FPClassifierName classifier; + + FPClassifierMacroInvocation() { getMacroName() = classifier.getName() } + + Expr getCheckedExpr() { + // Getting the checked expr in a cross-platform way is extroardinarily difficult, as glibc has + // multiple conditional implementations of the same macro. Assume the checked expr is a + // variable access so we can search optimistically like so: + exists(VariableAccess va | + va.getTarget().getName() = getExpandedArgument(0) and + va = getAnExpandedElement() and + result = va + ) + } + + /** + * The classification name, for instance, "isfinite". + */ + FPClassifierName getFPClassifierName() { result = classifier } +} + +/** + * A classification function, for instance, "isfinite", when implemented as a function. + */ +class FPClassifierFunction extends Function { + FPClassifierName classifier; + + FPClassifierFunction() { getName() = classifier.getName() } + + FPClassifierName getFPClassifierName() { result = classifier } +} + +class FPClassificationGuard instanceof GuardCondition { + Expr floatExpr; + Expr checkResultExpr; + FPClassifierName classifier; + + FPClassificationGuard() { + super.comparesEq(checkResultExpr, _, _, _) and + ( + exists(FPClassifierMacroInvocation m | + floatExpr = m.getCheckedExpr() and + checkResultExpr = m.getExpr() and + classifier = m.getFPClassifierName() + ) + or + exists(FunctionCall fc, FPClassifierFunction f | + fc.getTarget() = f and + floatExpr = fc.getArgument(0) and + checkResultExpr = fc and + classifier = f.getFPClassifierName() + ) + ) + } + + string toString() { + result = + classifier.toString() + " guard on " + floatExpr.toString() + " via " + + checkResultExpr.toString() + } + + predicate constrainsFPClass(Expr e, FPClassificationConstraint constraint, Boolean testIsTrue) { + floatExpr = e and + exists(BooleanValue value, boolean areEqual, int testResult, FPClassificationConstraint base | + super.comparesEq(checkResultExpr, testResult, areEqual, value) and + base = getBaseConstraint(areEqual, testResult) and + if value.getValue() = testIsTrue then constraint = base else constraint = base.invert() + ) + } + + // Helper function, gets base constraint assuming `classifier() == value` or `classifier != value`. + private FPClassificationConstraint getBaseConstraint(Boolean areEqual, int testResult) { + exists(FPClassificationConstraint base | + testResult = 0 and + exists(Boolean strict | + // Handle isfinite() != 0: + classifier = TClassifiesFinite(_, strict) and + base = TExactFPClassification(TFinite(), strict) + or + // Handle isNaN() != 0: + classifier = TClassifiesNaN(_, strict) and + base = TExactFPClassification(TNaN(), strict) + or + // Handle isinf() != 0, which matches for +/- infinity: + classifier = TClassifiesInfinite(_) and + base = TExactFPClassification(TInfinite(), true) + ) and + // Invert the base constraint in the case of `classifier() == 0` + if areEqual = false then result = base else result = base.invert() + or + // Handle isinf() == 1 or isInf() == -1, which matches for one of +/- infinity: + testResult = 1 and + classifier = TClassifiesInfinite(_) and + base = TExactFPClassification(TInfinite(), false) and + // Invert the base constraint in the case of `classifier() != 1` + if areEqual = true then result = base else result = base.invert() + // TODO: handle fpclassify() == FP_INFINITE, FP_NAN, FP_NORMAL, FP_ZERO, etc. + ) + } + + predicate controls(Expr e, boolean testIsTrue) { + exists(IRGuardCondition irg, IRBlock irb, Instruction eir, BooleanValue bval | + irg.getUnconvertedResultExpression() = this and + bval.getValue() = testIsTrue and + irg.valueControls(irb, bval) and + eir.getAst().(ControlFlowNode).getBasicBlock() = e.getBasicBlock() and + eir.getBlock() = irb + ) + } +} + predicate guardedNotEqualZero(Expr e) { /* Note Boolean cmpEq, false means cmpNeq */ exists(Expr checked, GuardCondition guard, boolean cmpEq, BooleanValue value | @@ -28,24 +316,15 @@ predicate guardedNotEqualZero(Expr e) { ) } -predicate guardedNotInfinite(Expr e) { +predicate guardedNotFPClass(Expr e, FPClassification cls) { /* Note Boolean cmpEq, false means cmpNeq */ - exists(Expr c, GuardCondition guard, boolean cmpEq | - hashCons(c) = hashCons(e) and + exists( + Expr checked, FPClassificationGuard guard, FPClassificationConstraint constraint, boolean cmpEq + | + hashCons(checked) = hashCons(e) and guard.controls(e, cmpEq) and - guard.comparesEq(c, 0, cmpEq.booleanNot(), _) - ) -} - -predicate test(Expr e, Expr v, int k, boolean areEqual, Boolean value, Expr gce, BasicBlock bb) { - exists(GuardCondition gc | gce = gc | - gc.controls(bb, _) and - gc.comparesEq(e, v, k, areEqual, value) and - ( - //gc.getAChild+().toString().matches("%dfYRes%") or - e.getAChild*().toString().matches("%dfPseudoPanchro%") or - v.getAChild*().toString().matches("%dfPseudoPanchro%") - ) + guard.constrainsFPClass(checked, constraint, cmpEq) and + constraint.mustNotBe(cls) ) } @@ -57,5 +336,7 @@ predicate exprMayEqualInfinity(Expr e, Boolean positive) { | RestrictedRangeAnalysis::upperBound(e.getUnconverted()) = target or RestrictedRangeAnalysis::lowerBound(e.getUnconverted()) = target - ) -} \ No newline at end of file + ) and + not guardedNotFPClass(e, TInfinite()) and + not e.getType() instanceof IntegralType +} diff --git a/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll index 79ae2f367a..9b4bba8980 100644 --- a/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll +++ b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll @@ -297,17 +297,21 @@ module RestrictedRangeAnalysis { } /** - * Holds if `expr` may divide by zero. + * Holds if `expr` may divide by zero. Excludes dividing a constant zero divided by zero, + * which produces NaN instead of an infinite value. */ - predicate dividesByZero(Expr expr) { - exists(Expr divisor | + predicate dividesNonzeroByZero(Expr expr) { + exists(Expr divisor, Expr numerator | divisor = expr.(DivExpr).getRightOperand() and + numerator = expr.(DivExpr).getLeftOperand() and getTruncatedLowerBounds(divisor) <= 0.0 and getTruncatedUpperBounds(divisor) >= 0.0 and - not isCheckedNotZero(divisor) + not isCheckedNotZero(divisor) and + not getValue(numerator).toFloat() = 0.0 ) } + /** * Holds if `expr` is checked with a guard to not be zero. * @@ -362,7 +366,7 @@ module RestrictedRangeAnalysis { // Introduces non-monotonic recursion. However, analysis mostly works with this // commented out. // or - // dividesByZero(e) + // dividesNonzeroByZero(e) or e instanceof DivExpr // TODO: confirm this is OK or @@ -681,7 +685,7 @@ module RestrictedRangeAnalysis { } private predicate lowerBoundableExpr(Expr expr) { - (analyzableExpr(expr) or dividesByZero(expr)) and + (analyzableExpr(expr) or dividesNonzeroByZero(expr)) and getUpperBoundsImpl(expr) <= Util::exprMaxVal(expr) and not exists(getValue(expr).toFloat()) } @@ -760,7 +764,7 @@ module RestrictedRangeAnalysis { * this predicate. */ private float getTruncatedUpperBounds(Expr expr) { - (analyzableExpr(expr) or dividesByZero(expr)) + (analyzableExpr(expr) or dividesNonzeroByZero(expr)) and ( // If the expression evaluates to a constant, then there is no // need to call getUpperBoundsImpl. @@ -827,7 +831,7 @@ module RestrictedRangeAnalysis { ) or exists(DivExpr div | expr = div | - dividesByZero(expr) and + dividesNonzeroByZero(expr) and result = getFullyConvertedLowerBounds(div.getLeftOperand()) / 0 ) or @@ -1032,7 +1036,7 @@ module RestrictedRangeAnalysis { ) or exists(DivExpr div | expr = div | - dividesByZero(expr) and + dividesNonzeroByZero(expr) and result = getFullyConvertedUpperBounds(div.getLeftOperand()) / 0 ) or From 1af6957b71ed825ab1d76c92588e082e05a17ec7 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 6 Feb 2025 10:17:27 +0000 Subject: [PATCH 175/370] M5-3-1: Exclude unknown types This ensures we consistently exclude unknown results for unevaluated contexts in uninstantiated templates. --- .../2025-02-06-m5-3-1-exclude-unknown-type.md | 2 ++ ...ogicalAndOrTheLogicalOperatorsShallHaveTypeBool.ql | 5 +++++ cpp/autosar/test/rules/M5-3-1/test.cpp | 11 ++++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 change_notes/2025-02-06-m5-3-1-exclude-unknown-type.md diff --git a/change_notes/2025-02-06-m5-3-1-exclude-unknown-type.md b/change_notes/2025-02-06-m5-3-1-exclude-unknown-type.md new file mode 100644 index 0000000000..ba7f50af45 --- /dev/null +++ b/change_notes/2025-02-06-m5-3-1-exclude-unknown-type.md @@ -0,0 +1,2 @@ + - `M5-3-1` - `EachOperandOfTheOperatorOfTheLogicalAndOrTheLogicalOperatorsShallHaveTypeBool.ql`: + - Consistently exclude results in unevaluated contexts associated with uninstantiated templates, for example `noexcept` specifiers and `static_assert`s. \ No newline at end of file diff --git a/cpp/autosar/src/rules/M5-3-1/EachOperandOfTheOperatorTheLogicalAndOrTheLogicalOperatorsShallHaveTypeBool.ql b/cpp/autosar/src/rules/M5-3-1/EachOperandOfTheOperatorTheLogicalAndOrTheLogicalOperatorsShallHaveTypeBool.ql index 03b4ae7f1c..e4589a364a 100644 --- a/cpp/autosar/src/rules/M5-3-1/EachOperandOfTheOperatorTheLogicalAndOrTheLogicalOperatorsShallHaveTypeBool.ql +++ b/cpp/autosar/src/rules/M5-3-1/EachOperandOfTheOperatorTheLogicalAndOrTheLogicalOperatorsShallHaveTypeBool.ql @@ -25,6 +25,11 @@ where ) and t = operand.getType() and not t.getUnderlyingType().getUnspecifiedType() instanceof BoolType and + // Ignore cases where the type is unknown - this will typically be in unevaluated contexts + // within uninstantiated templates. It's necessary to check for this explicitly because + // not all unevaluated contexts are considered to be `isFromUninstantiatedTemplate(_)`, + // e.g. `noexcept` specifiers + not t instanceof UnknownType and not exists(ReferenceType rt | rt = t.getUnderlyingType().getUnspecifiedType() and rt.getBaseType() instanceof BoolType ) and diff --git a/cpp/autosar/test/rules/M5-3-1/test.cpp b/cpp/autosar/test/rules/M5-3-1/test.cpp index 9098e4e40e..4bda4c6682 100644 --- a/cpp/autosar/test/rules/M5-3-1/test.cpp +++ b/cpp/autosar/test/rules/M5-3-1/test.cpp @@ -25,4 +25,13 @@ template class A { void f() { A a; a.test1(); -} \ No newline at end of file +} + +template constexpr bool some_variable_template_v = false; +template <> constexpr bool some_variable_template_v = true; + +template +void template_with_no_except() noexcept(some_variable_template_v && + true) { // COMPLIANT +} +void test_template() { template_with_no_except(); } \ No newline at end of file From 879a6f27c9d29906e9b58e973574aba0360eccb3 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 6 Feb 2025 16:35:16 +0000 Subject: [PATCH 176/370] A3-1-5: Downgrade to an "audit" query This rule talks about developer intention in a way that is not possible to determine fully automatically with any confidence. We therefore downgrade this rule to an "audit" query. --- ...nTrivialNonTemplateFunctionDefinedInsideClassDefinition.ql | 1 + rule_packages/cpp/Classes.json | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cpp/autosar/src/rules/A3-1-5/NonTrivialNonTemplateFunctionDefinedInsideClassDefinition.ql b/cpp/autosar/src/rules/A3-1-5/NonTrivialNonTemplateFunctionDefinedInsideClassDefinition.ql index 251f94d6eb..2edf73b6ee 100644 --- a/cpp/autosar/src/rules/A3-1-5/NonTrivialNonTemplateFunctionDefinedInsideClassDefinition.ql +++ b/cpp/autosar/src/rules/A3-1-5/NonTrivialNonTemplateFunctionDefinedInsideClassDefinition.ql @@ -7,6 +7,7 @@ * @precision very-high * @problem.severity recommendation * @tags external/autosar/id/a3-1-5 + * external/autosar/audit * external/autosar/allocated-target/design * external/autosar/enforcement/partially-automated * external/autosar/obligation/required diff --git a/rule_packages/cpp/Classes.json b/rule_packages/cpp/Classes.json index 6dd130a55b..d76a9b3bc5 100644 --- a/rule_packages/cpp/Classes.json +++ b/rule_packages/cpp/Classes.json @@ -185,7 +185,9 @@ "precision": "very-high", "severity": "recommendation", "short_name": "NonTrivialNonTemplateFunctionDefinedInsideClassDefinition", - "tags": [] + "tags": [ + "external/autosar/audit" + ] } ], "title": "A function definition shall only be placed in a class definition if (1) the function is intended to be inlined (2) it is a member function template (3) it is a member function of a class template." From 3f6235892f85ffbf1ff9e266fac003fcfeab1728 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 6 Feb 2025 16:39:14 +0000 Subject: [PATCH 177/370] Add change note --- change_notes/2025-02-06-a3-1-5-audit.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 change_notes/2025-02-06-a3-1-5-audit.md diff --git a/change_notes/2025-02-06-a3-1-5-audit.md b/change_notes/2025-02-06-a3-1-5-audit.md new file mode 100644 index 0000000000..3aa0e6671b --- /dev/null +++ b/change_notes/2025-02-06-a3-1-5-audit.md @@ -0,0 +1,2 @@ + - `A3-1-5` - `NonTrivalNonTemplateFunctionDefinedInsideClassDefinition.ql`: + - Mark this as an `audit` query. As a consequence, it will no longer be run as part of the default query suite for AUTOSAR. It can still be run as part of the `autosar-audit.qls` query suite. The query has been downgraded because the rule allows for functions to be declared in the class body if they were "intended" to be inlined, and that developer intention cannot be determined automatically from the code. \ No newline at end of file From 4ee762909b228630ae6f7da1bcab8ba7922b2df5 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 6 Feb 2025 12:00:56 -0800 Subject: [PATCH 178/370] Deduplicate and filter results, improve messages, handle performance issue --- .../PossibleMisuseOfUndetectedInfinity.ql | 69 ++++-- .../DIR-4-15/PossibleMisuseOfUndetectedNaN.ql | 68 ++++-- .../PossibleUndetectedNaNorInfinity.ql | 223 ------------------ .../PossibleUndetectedNaNorInfinity.expected | 1 - .../PossibleUndetectedNaNorInfinity.qlref | 1 - .../cpp/RestrictedRangeAnalysis.qll | 126 ++++++++-- 6 files changed, 207 insertions(+), 281 deletions(-) delete mode 100644 c/misra/src/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.ql delete mode 100644 c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.expected delete mode 100644 c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.qlref diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql index 97dd251083..10c370690b 100644 --- a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql @@ -73,44 +73,73 @@ module InvalidInfinityUsage implements DataFlow::ConfigSig { } predicate isSink(DataFlow::Node node) { + node instanceof InvalidInfinityUsage and ( // Require that range analysis finds this value potentially infinite, to avoid false positives // in the presence of guards. This may induce false negatives. - exprMayEqualInfinity(node.asExpr(), _) or + exprMayEqualInfinity(node.asExpr(), _) + or // Unanalyzable expressions are not checked against range analysis, which assumes a finite // range. not RestrictedRangeAnalysis::analyzableExpr(node.asExpr()) - ) and - ( - // Case 2: NaNs and infinities shall not be cast to integers - exists(Conversion c | - node.asExpr() = c.getUnconverted() and - c.getExpr().getType() instanceof FloatingPointType and - c.getType() instanceof IntegralType - ) - or - // Case 3: Infinities shall not underflow or otherwise produce finite values - exists(BinaryOperation op | - node.asExpr() = op.getRightOperand() and - op.getOperator() = ["/", "%"] - ) ) } } +class InvalidInfinityUsage extends DataFlow::Node { + string description; + string infinityDescription; + + InvalidInfinityUsage() { + // Case 2: NaNs and infinities shall not be cast to integers + exists(Conversion c | + asExpr() = c.getUnconverted() and + c.getExpr().getType() instanceof FloatingPointType and + c.getType() instanceof IntegralType and + description = "$@ casted to integer." and + infinityDescription = "Possibly infinite float value" + ) + or + // Case 3: Infinities shall not underflow or otherwise produce finite values + exists(BinaryOperation op | + asExpr() = op.getRightOperand() and + op.getOperator() = "/" and + description = "Division operation may silently underflow and produce zero, as the divisor $@." and + infinityDescription = "may be an infinite float value" + ) + } + + string getDescription() { result = description } + + string getInfinityDescription() { result = infinityDescription } +} + module InvalidInfinityFlow = DataFlow::Global; import InvalidInfinityFlow::PathGraph from Element elem, InvalidInfinityFlow::PathNode source, InvalidInfinityFlow::PathNode sink, - string msg, string sourceString + InvalidInfinityUsage usage, Expr sourceExpr, Element extra, string extraString where elem = MacroUnwrapper::unwrapElement(sink.getNode().asExpr()) and + not InvalidInfinityFlow::PathGraph::edges(_, source, _, _) and not isExcluded(elem, FloatingTypes2Package::possibleMisuseOfUndetectedInfinityQuery()) and + not sourceExpr.isFromTemplateInstantiation(_) and + not usage.asExpr().isFromTemplateInstantiation(_) and + usage = sink.getNode() and + sourceExpr = source.getNode().asExpr() and + InvalidInfinityFlow::flow(source.getNode(), usage) and ( - InvalidInfinityFlow::flow(source.getNode(), sink.getNode()) and - msg = "Invalid usage of possible $@." and - sourceString = "infinity" + if not sourceExpr.getEnclosingFunction() = usage.asExpr().getEnclosingFunction() + then + extraString = usage.getInfinityDescription() + " computed in function " + sourceExpr.getEnclosingFunction().getName() + and extra = sourceExpr.getEnclosingFunction() + else ( + extra = sourceExpr and + if sourceExpr instanceof DivExpr + then extraString = usage.getInfinityDescription() + " from division by zero" + else extraString = usage.getInfinityDescription() + ) ) -select elem, source, sink, msg, source, sourceString +select elem, source, sink, usage.getDescription(), extra, extraString \ No newline at end of file diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql index 036d470247..942715fe2f 100644 --- a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql @@ -40,7 +40,7 @@ class InvalidOperationExpr extends BinaryOperation { exprMayEqualInfinity(getLeftOperand(), sign) and exprMayEqualInfinity(getRightOperand(), sign.booleanNot()) ) and - reason = "possible addition of infinity and negative infinity" + reason = "from addition of infinity and negative infinity" or // 7.1.2 continued getOperator() = "-" and @@ -48,35 +48,35 @@ class InvalidOperationExpr extends BinaryOperation { exprMayEqualInfinity(getLeftOperand(), sign) and exprMayEqualInfinity(getRightOperand(), sign) ) and - reason = "possible subtraction of an infinity from itself" + reason = "from subtraction of an infinity from itself" or // 7.1.3: multiplication of zero by infinity getOperator() = "*" and exprMayEqualZero(getAnOperand()) and exprMayEqualInfinity(getAnOperand(), _) and - reason = "possible multiplication of zero by infinity" + reason = "from multiplication of zero by infinity" or // 7.1.4: Division of zero by zero, or infinity by infinity getOperator() = "/" and exprMayEqualZero(getLeftOperand()) and exprMayEqualZero(getRightOperand()) and - reason = "possible division of zero by zero" + reason = "from division of zero by zero" or // 7.1.4 continued getOperator() = "/" and exprMayEqualInfinity(getLeftOperand(), _) and exprMayEqualInfinity(getRightOperand(), _) and - reason = "possible division of infinity by infinity" + reason = "from division of infinity by infinity" or // 7.1.5: x % y where y is zero or x is infinite getOperator() = "%" and exprMayEqualInfinity(getLeftOperand(), _) and - reason = "possible modulus of infinity" + reason = "from modulus of infinity" or // 7.1.5 continued getOperator() = "%" and exprMayEqualZero(getRightOperand()) and - reason = "possible modulus by zero" + reason = "from modulus by zero" // 7.1.6 handles the sqrt function, not covered here. // 7.1.7 declares exceptions during invalid conversions, which we catch as sinks in our flow // analysis. @@ -129,24 +129,39 @@ module InvalidNaNUsage implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node node) { not guardedNotFPClass(node.asExpr(), TNaN()) and - ( + node instanceof InvalidNaNUsage + } +} + +class InvalidNaNUsage extends DataFlow::Node { + string description; + string nanDescription; + + InvalidNaNUsage() { // Case 1: NaNs shall not be compared, except to themselves exists(ComparisonOperation cmp | - node.asExpr() = cmp.getAnOperand() and - not hashCons(cmp.getLeftOperand()) = hashCons(cmp.getRightOperand()) + this.asExpr() = cmp.getAnOperand() and + not hashCons(cmp.getLeftOperand()) = hashCons(cmp.getRightOperand()) and + description = "Comparison involving a $@, which always evaluates to false." and + nanDescription = "possibly NaN float value" ) or // Case 2: NaNs and infinities shall not be cast to integers exists(Conversion c | - node.asExpr() = c.getUnconverted() and + this.asExpr() = c.getUnconverted() and c.getExpr().getType() instanceof FloatingPointType and - c.getType() instanceof IntegralType + c.getType() instanceof IntegralType and + description = "$@ casted to integer." and + nanDescription = "Possibly NaN float value" ) //or //// Case 4: Functions shall not return NaNs or infinities //exists(ReturnStmt ret | node.asExpr() = ret.getExpr()) - ) } + + string getDescription() { result = description } + + string getNaNDescription() { result = nanDescription } } module InvalidNaNFlow = DataFlow::Global; @@ -154,15 +169,26 @@ module InvalidNaNFlow = DataFlow::Global; import InvalidNaNFlow::PathGraph from - Element elem, InvalidNaNFlow::PathNode source, InvalidNaNFlow::PathNode sink, string msg, - string sourceString + Element elem, InvalidNaNFlow::PathNode source, InvalidNaNFlow::PathNode sink, + InvalidNaNUsage usage, Expr sourceExpr, string sourceString, Element extra, string extraString where + not InvalidNaNFlow::PathGraph::edges(_, source, _, _) and + not sourceExpr.isFromTemplateInstantiation(_) and + not usage.asExpr().isFromTemplateInstantiation(_) and elem = MacroUnwrapper::unwrapElement(sink.getNode().asExpr()) and - not isExcluded(elem, FloatingTypes2Package::possibleMisuseOfUndetectedNaNQuery()) and - ( - InvalidNaNFlow::flow(source.getNode(), sink.getNode()) and - msg = "Invalid usage of possible $@." and + usage = sink.getNode() and + sourceExpr = source.getNode().asExpr() and sourceString = - "NaN resulting from " + source.getNode().asExpr().(InvalidOperationExpr).getReason() + " (" + source.getNode().asExpr().(InvalidOperationExpr).getReason() + ")" and + InvalidNaNFlow::flow(source.getNode(), usage) and + ( + if not sourceExpr.getEnclosingFunction() = usage.asExpr().getEnclosingFunction() + then + extraString = usage.getNaNDescription() + sourceString + " computed in function " + sourceExpr.getEnclosingFunction().getName() + and extra = sourceExpr.getEnclosingFunction() + else ( + extra = sourceExpr and + extraString = usage.getNaNDescription() + sourceString + ) ) -select elem, source, sink, msg, source, sourceString +select elem, source, sink, usage.getDescription(), extra, extraString \ No newline at end of file diff --git a/c/misra/src/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.ql b/c/misra/src/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.ql deleted file mode 100644 index 94888a95e6..0000000000 --- a/c/misra/src/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.ql +++ /dev/null @@ -1,223 +0,0 @@ -/** - * @id c/misra/possible-undetected-na-nor-infinity - * @name DIR-4-15: Evaluation of floating-point expressions shall not lead to the undetected generation of infinities - * @description Evaluation of floating-point expressions shall not lead to the undetected generation - * of infinities and NaNs. - * @kind path-problem - * @precision high - * @problem.severity error - * @tags external/misra/id/dir-4-15 - * correctness - * external/misra/c/2012/amendment3 - * external/misra/obligation/required - */ - -import cpp -import codeql.util.Boolean -import codingstandards.c.misra -import codingstandards.cpp.RestrictedRangeAnalysis -import codingstandards.cpp.FloatingPoint -import codingstandards.cpp.AlertReporting -import semmle.code.cpp.controlflow.Guards -import semmle.code.cpp.dataflow.new.DataFlow -import semmle.code.cpp.dataflow.new.TaintTracking -import semmle.code.cpp.controlflow.Dominance - -class CantHandleInfinityFunction extends Function { - CantHandleInfinityFunction() { not hasDefinition() and not getName() = "__fpclassifyl" } -} - -class InfinityCheckedExpr extends Expr { - InfinityCheckedExpr() { - exists(MacroInvocation mi | - mi.getMacroName() = ["isfinite", "isinf"] and - mi.getExpr() = this - ) - } - - Expr getCheckedExpr() { - result = - this.(ConditionalExpr) - .getThen() - .(LTExpr) - .getLesserOperand() - .(BitwiseAndExpr) - .getLeftOperand() - .(FunctionCall) - .getArgument(0) - } -} - -/* -signature module ResourceLeakConfigSig { - predicate isResource(DataFlow::Node node); - - predicate isFree(DataFlow::Node node, DataFlow::Node resource); - - default ControlFlowNode outOfScope(DataFlow::Node resource) { - result = resource.asExpr().getEnclosingFunction().getBlock().getLastStmt() - } - - default predicate isAlias(DataFlow::Node alias, DataFlow::Node resource) { - isResource(resource) and - DataFlow::localFlow(resource, alias) - } -} - -module ResourceLeak { - predicate isLeaked(DataFlow::Node resource, ControlFlowNode cfgNode) { - resource.asExpr() = cfgNode - or - isLeaked(resource, cfgNode.getAPredecessor()) and - not exists(DataFlow::Node free, DataFlow::Node freed | - free.asExpr() = cfgNode and - Config::isFree(free, freed) and - Config::isAlias(freed, resource) - ) - } - - private ControlFlowNode getARawLeak(DataFlow::Node resource) { - Config::isResource(resource) and - result = Config::outOfScope(resource) and - isLeaked(resource, result) - } - - ControlFlowNode getALeak(DataFlow::Node resource) { - result = getARawLeak(resource) and - not exists(DataFlow::Node dealiased | - Config::isResource(dealiased) and - Config::isAlias(resource, dealiased) and - not resource = dealiased and - result = getARawLeak(dealiased) - ) and - not exists(ControlFlowNode dominator | - dominator = getARawLeak(resource) and - strictlyDominates(dominator, result) - ) - } -} - -module MissedInfinityConfig implements ResourceLeakConfigSig { - predicate isResource(DataFlow::Node node) { - //exists(BinaryOperation expr | - // expr = node.asExpr() and - // expr.getOperator() = "/" and - // RestrictedRangeAnalysis::upperBound(expr.getRightOperand()) <= 0 and - // RestrictedRangeAnalysis::lowerBound(expr.getRightOperand()) >= 0 - //) - [ - RestrictedRangeAnalysis::upperBound(node.asExpr()), - RestrictedRangeAnalysis::lowerBound(node.asExpr()) - ].toString() = "Infinity" - //and not node.asExpr() instanceof VariableAccess - //and not node.asExpr() instanceof ArrayExpr - } - - predicate test(Expr expr, string lowerBound, string upperBound) { - //expr.getType() instanceof FloatingPointType - //and - lowerBound = RestrictedRangeAnalysis::lowerBound(expr).toString() and - upperBound = RestrictedRangeAnalysis::upperBound(expr).toString() and - [lowerBound, upperBound] = "Infinity" - } - - additional predicate testDiv( - DivExpr div, string lbDiv, string ubDiv, string lbNum, string ubNum, string lbDenom, - string ubDenom - ) { - lbDiv = RestrictedRangeAnalysis::lowerBound(div).toString() and - ubDiv = RestrictedRangeAnalysis::upperBound(div).toString() and - lbNum = RestrictedRangeAnalysis::lowerBound(div.getLeftOperand()).toString() and - ubNum = RestrictedRangeAnalysis::upperBound(div.getLeftOperand()).toString() and - lbDenom = RestrictedRangeAnalysis::lowerBound(div.getRightOperand()).toString() and - ubDenom = RestrictedRangeAnalysis::upperBound(div.getRightOperand()).toString() and - not lbDiv = ubDiv and - InvalidNaNUsage::isSource(DataFlow::exprNode(div)) - } - - predicate isFree(DataFlow::Node node, DataFlow::Node resource) { - isResource(resource) and - ( - node.asExpr().(InfinityCheckedExpr).getCheckedExpr() = resource.asExpr() - or - not [ - RestrictedRangeAnalysis::lowerBound(node.asExpr()), - RestrictedRangeAnalysis::upperBound(node.asExpr()) - ].toString() = "Infinity" and - isMove(node, resource) - ) - } - - predicate isMove(DataFlow::Node node, DataFlow::Node moved) { - isResource(moved) and - isAlias(node, moved) and - not exists(DataFlow::Node laterUse, ControlFlowNode later | - later = laterUse.asExpr() and - later = node.asExpr().getASuccessor+() and - hashCons(laterUse.asExpr()) = hashCons(moved.asExpr()) - ) - } - - ControlFlowNode outOfScope(DataFlow::Node resource) { - result = resource.asExpr().getEnclosingFunction().getBlock().getLastStmt() - or - exists(AssignExpr assign, DataFlow::Node alias | - assign.getRValue() = alias.asExpr() and - isAlias(alias, resource) and - not assign.getRValue().(VariableAccess).getTarget() instanceof StackVariable and - result = assign - ) - or - exists(FunctionCall fc | - fc.getArgument(_) = resource.asExpr() and - result = fc - ) - } - - predicate isAlias(DataFlow::Node alias, DataFlow::Node resource) { - TaintTracking::localTaint(resource, alias) - } -} - -import ResourceLeak as MissedInfinity -*/ - -//from Expr value, FunctionCall fc -//where -// not isExcluded(value, FloatingTypes2Package::possibleUndetectedNaNorInfinityQuery()) and -// [RestrictedRangeAnalysis::lowerBound(value), RestrictedRangeAnalysis::upperBound(value)].toString() = "Infinity" and -// value = fc.getAnArgument() and -// fc.getTarget() instanceof CantHandleInfinityFunction and -// not value instanceof InfinityCheckedExpr and -// not exists (GuardCondition g | -// g.controls(fc.getBasicBlock(), true) and -// g instanceof InfinityCheckedExpr -// // TODO check we check the right expr -// ) -//select -// value, "possible use of unchecked infinity as arg to " + fc.getTarget().getName() -//from DataFlow::Node node, ControlFlowNode leakPoint -//where -// not isExcluded(node.asExpr(), FloatingTypes2Package::possibleUndetectedNaNorInfinityQuery()) and -// leakPoint = MissedInfinity::getALeak(node) -// select node, "Expression generates an infinity which is not checked before $@.", leakPoint, "external leak point" - - -//import InvalidNaNFlow::PathGraph -//from Element elem, DataFlow::Node source, DataFlow::Node sink, string msg, string sourceString -from - Element elem, InvalidInfinityFlow::PathNode source, InvalidInfinityFlow::PathNode sink, - string msg, string sourceString -where - elem = MacroUnwrapper::unwrapElement(sink.getNode().asExpr()) and - not isExcluded(elem, FloatingTypes2Package::possibleUndetectedNaNorInfinityQuery()) and - ( - InvalidInfinityFlow::flow(source.getNode(), sink.getNode()) and - msg = "Invalid usage of possible $@." and - sourceString = "infinity" - //or - //InvalidNaNFlow::flow(source, sink) and - //msg = "Invalid usage of possible $@." and - //sourceString = "NaN resulting from " + source.asExpr().(InvalidOperationExpr).getReason() - ) -select elem, source, sink, msg, source, sourceString diff --git a/c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.expected b/c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.expected deleted file mode 100644 index 2ec1a0ac6c..0000000000 --- a/c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.expected +++ /dev/null @@ -1 +0,0 @@ -No expected results have yet been specified \ No newline at end of file diff --git a/c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.qlref b/c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.qlref deleted file mode 100644 index 1ffb7ad071..0000000000 --- a/c/misra/test/rules/DIR-4-15/PossibleUndetectedNaNorInfinity.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/DIR-4-15/PossibleUndetectedNaNorInfinity.ql \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll index 9b4bba8980..8ae3c9c38b 100644 --- a/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll +++ b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll @@ -1,5 +1,6 @@ import semmle.code.cpp.controlflow.Guards import semmle.code.cpp.valuenumbering.HashCons + /** * A fork of SimpleRangeAnalysis.qll, which is intended to only give * results with a conservative basis. @@ -311,7 +312,6 @@ module RestrictedRangeAnalysis { ) } - /** * Holds if `expr` is checked with a guard to not be zero. * @@ -332,7 +332,8 @@ module RestrictedRangeAnalysis { expr = def.getAUse(v) and isNEPhi(v, def, guardVa, 0) ) - or guardedHashConsNotEqualZero(expr) + or + guardedHashConsNotEqualZero(expr) } predicate guardedHashConsNotEqualZero(Expr e) { @@ -342,8 +343,8 @@ module RestrictedRangeAnalysis { valVal = getValue(val).toFloat() and guard.controls(e.getBasicBlock(), cmpEq) and ( - guard.comparesEq(check, val, -valVal, false, cmpEq) or - guard.comparesEq(val, check, -valVal, false, cmpEq) + guard.comparesEq(check, val, -valVal, false, cmpEq) or + guard.comparesEq(val, check, -valVal, false, cmpEq) ) ) } @@ -363,11 +364,11 @@ module RestrictedRangeAnalysis { dividesByPositive(e, _, _) or dividesByNegative(e, _, _) + or // Introduces non-monotonic recursion. However, analysis mostly works with this // commented out. // or // dividesNonzeroByZero(e) - or e instanceof DivExpr // TODO: confirm this is OK or e instanceof MinExpr @@ -469,6 +470,8 @@ module RestrictedRangeAnalysis { exprDependsOnDef(operand, srcDef, srcVar) ) or + exists(DivExpr div | div = e | exprDependsOnDef(div.getAnOperand(), srcDef, srcVar)) + or exists(MinExpr minExpr | e = minExpr | exprDependsOnDef(minExpr.getAnOperand(), srcDef, srcVar)) or exists(MaxExpr maxExpr | e = maxExpr | exprDependsOnDef(maxExpr.getAnOperand(), srcDef, srcVar)) @@ -595,6 +598,98 @@ module RestrictedRangeAnalysis { isRecursiveExpr(binop.getRightOperand()) } + private predicate applyWideningToBinary(BinaryOperation op) { + // Original behavior: + isRecursiveBinary(op) + or + // As we added support for DivExpr, we found cases of combinatorial explosion that are not + // caused by recursion. Given expr `x` that depends on a phi node that has evaluated y unique + // values, `x + x` will in the worst case evaluate to y^2 unique values, even if `x` is not + // recursive. By adding support for division, we have revealed certain pathological cases in + // open source code, for instance `posix_time_from_utc` from boringssl. We can reduce this + // greatly by widening, and targeting division effectively reduces the chains of evaluations + // that cause this issue while preserving the original behavior. + // + // There is also a set of functions intended to estimate the combinations of phi nodes each + // expression depends on, which could be used to accurately widen only expensive nodes. However, + // that estimation is more involved than it may seem, and hasn't yet resulted in a net + // improvement. See `estimatedPhiCombinationsExpr` and `estimatedPhiCombinationsDef`. + // + // This approach currently has the best performance. + op instanceof DivExpr + } + + /** + * Recursively scan this expr to see how many phi nodes it depends on. Binary expressions + * induce a combination effect, so `a + b` where `a` depends on 3 phi nodes and `b` depends on 4 + * will induce 3*4 = 12 phi node combinations. + * + * This currently requires additional optimization to be useful in practice. + */ + int estimatedPhiCombinationsExpr(Expr expr) { + if isRecursiveExpr(expr) + // Assume 10 values were computed to analyze recursive expressions. + then result = 10 + else ( + exists(RangeSsaDefinition def, StackVariable v | expr = def.getAUse(v) | + def.isPhiNode(v) and + result = estimatedPhiCombinationsDef(def, v) + ) + or + exists(BinaryOperation binop | + binop = expr and + result = + estimatedPhiCombinationsExpr(binop.getLeftOperand()) * + estimatedPhiCombinationsExpr(binop.getRightOperand()) + ) + or + not expr instanceof BinaryOperation and + exists(RangeSsaDefinition def, StackVariable v | exprDependsOnDef(expr, def, v) | + result = estimatedPhiCombinationsDef(def, v) + ) + or + not expr instanceof BinaryOperation and + not exprDependsOnDef(expr, _, _) and result = 1 + ) + } + + /** + * Recursively scan this def to see how many phi nodes it depends on. + * + * If this def is a phi node, it sums its downstream cost and adds one to account for itself, + * which is not exactly correct. + * + * This def may also be a crement expression (not currently supported), or an assign expr + * (currently not supported), or an unanalyzable expression which is the root of the recursion + * and given a value of 1. + */ + language[monotonicAggregates] + int estimatedPhiCombinationsDef(RangeSsaDefinition def, StackVariable v) { + if isRecursiveDef(def, v) + // Assume 10 values were computed to analyze recursive expressions. + then result = 10 + else ( + if def.isPhiNode(v) + then + exists(Expr e | e = def.getAUse(v) | + result = + 1 + + sum(RangeSsaDefinition srcDef | + srcDef = def.getAPhiInput(v) + | + estimatedPhiCombinationsDef(srcDef, v) + ) + ) + else ( + exists(Expr expr | assignmentDef(def, v, expr) | result = estimatedPhiCombinationsExpr(expr)) + or + v = def.getAVariable() and + not assignmentDef(def, v, _) and + result = 1 + ) + ) + } + /** * We distinguish 3 kinds of RangeSsaDefinition: * @@ -719,7 +814,7 @@ module RestrictedRangeAnalysis { if Util::exprMinVal(expr) <= newLB and newLB <= Util::exprMaxVal(expr) then // Apply widening where we might get a combinatorial explosion. - if isRecursiveBinary(expr) + if applyWideningToBinary(expr) then result = max(float widenLB | @@ -764,8 +859,8 @@ module RestrictedRangeAnalysis { * this predicate. */ private float getTruncatedUpperBounds(Expr expr) { - (analyzableExpr(expr) or dividesNonzeroByZero(expr)) - and ( + (analyzableExpr(expr) or dividesNonzeroByZero(expr)) and + ( // If the expression evaluates to a constant, then there is no // need to call getUpperBoundsImpl. if exists(getValue(expr).toFloat()) @@ -778,7 +873,7 @@ module RestrictedRangeAnalysis { if Util::exprMinVal(expr) <= newUB and newUB <= Util::exprMaxVal(expr) then // Apply widening where we might get a combinatorial explosion. - if isRecursiveBinary(expr) + if applyWideningToBinary(expr) then result = min(float widenUB | @@ -794,13 +889,14 @@ module RestrictedRangeAnalysis { exprMightOverflowNegatively(expr) and result = Util::exprMaxVal(expr) ) - ) or + ) + or not analyzableExpr(expr) and - // The expression is not analyzable, so its upper bound is - // unknown. Note that the call to exprMaxVal restricts the - // expressions to just those with arithmetic types. There is no - // need to return results for non-arithmetic expressions. - result = exprMaxVal(expr) + // The expression is not analyzable, so its upper bound is + // unknown. Note that the call to exprMaxVal restricts the + // expressions to just those with arithmetic types. There is no + // need to return results for non-arithmetic expressions. + result = exprMaxVal(expr) } /** Only to be called by `getTruncatedLowerBounds`. */ From dee226188f61262f5f5a02173c1545c7ad8783ca Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 7 Feb 2025 04:28:13 -0800 Subject: [PATCH 179/370] Widening/dedupe fixes, plus math lib support --- .../PossibleMisuseOfUndetectedInfinity.ql | 8 +- .../DIR-4-15/PossibleMisuseOfUndetectedNaN.ql | 74 +++++- ...ossibleMisuseOfUndetectedInfinity.expected | 82 ++++-- .../PossibleMisuseOfUndetectedNaN.expected | 108 +++++--- c/misra/test/rules/DIR-4-15/test.c | 59 ++++- .../cpp/RestrictedRangeAnalysis.qll | 242 +++++++++++++++++- 6 files changed, 496 insertions(+), 77 deletions(-) diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql index 10c370690b..357a8fce71 100644 --- a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql @@ -51,9 +51,6 @@ module InvalidInfinityUsage implements DataFlow::ConfigSig { e.getType() instanceof IntegralType and e = node.asConvertedExpr() ) - or - // Sinks are places where Infinity produce a finite value - isSink(node) } /** @@ -81,7 +78,9 @@ module InvalidInfinityUsage implements DataFlow::ConfigSig { or // Unanalyzable expressions are not checked against range analysis, which assumes a finite // range. - not RestrictedRangeAnalysis::analyzableExpr(node.asExpr()) + not RestrictedRangeAnalysis::canBoundExpr(node.asExpr()) + or + node.asExpr().(VariableAccess).getTarget() instanceof Parameter ) } } @@ -124,6 +123,7 @@ from where elem = MacroUnwrapper::unwrapElement(sink.getNode().asExpr()) and not InvalidInfinityFlow::PathGraph::edges(_, source, _, _) and + not InvalidInfinityFlow::PathGraph::edges(sink, _, _, _) and not isExcluded(elem, FloatingTypes2Package::possibleMisuseOfUndetectedInfinityQuery()) and not sourceExpr.isFromTemplateInstantiation(_) and not usage.asExpr().isFromTemplateInstantiation(_) and diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql index 942715fe2f..f850cc3e55 100644 --- a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql @@ -23,8 +23,73 @@ import semmle.code.cpp.dataflow.new.DataFlow import semmle.code.cpp.dataflow.new.TaintTracking import semmle.code.cpp.controlflow.Dominance +bindingset[name] +Function getMathVariants(string name) { result.hasGlobalOrStdName([name, name + "f", name + "l"]) } + +predicate hasDomainError(FunctionCall fc, string description) { + exists(Function functionWithDomainError | fc.getTarget() = functionWithDomainError | + functionWithDomainError = [getMathVariants(["acos", "asin", "atanh"])] and + not ( + RestrictedRangeAnalysis::upperBound(fc.getArgument(0)) <= 1.0 and + RestrictedRangeAnalysis::lowerBound(fc.getArgument(0)) >= -1.0 + ) and + description = + "the argument has a range " + RestrictedRangeAnalysis::lowerBound(fc.getArgument(0)) + "..." + + RestrictedRangeAnalysis::upperBound(fc.getArgument(0)) + " which is outside the domain of this function (-1.0...1.0)" + or + functionWithDomainError = getMathVariants(["atan2", "pow"]) and + ( + exprMayEqualZero(fc.getArgument(0)) and + exprMayEqualZero(fc.getArgument(1)) and + description = "both arguments are equal to zero" + ) + or + functionWithDomainError = getMathVariants("pow") and + ( + RestrictedRangeAnalysis::upperBound(fc.getArgument(0)) < 0.0 and + RestrictedRangeAnalysis::upperBound(fc.getArgument(1)) < 0.0 and + description = "both arguments are less than zero" + ) + or + functionWithDomainError = getMathVariants("acosh") and + RestrictedRangeAnalysis::upperBound(fc.getArgument(0)) < 1.0 and + description = "argument is less than 1" + or + //pole error is the same as domain for logb and tgamma (but not ilogb - no pole error exists) + functionWithDomainError = getMathVariants(["ilogb", "logb", "tgamma"]) and + exprMayEqualZero(fc.getArgument(0)) and + description = "argument is equal to zero" + or + functionWithDomainError = getMathVariants(["log", "log10", "log2", "sqrt"]) and + RestrictedRangeAnalysis::upperBound(fc.getArgument(0)) < 0.0 and + description = "argument is negative" + or + functionWithDomainError = getMathVariants("log1p") and + RestrictedRangeAnalysis::upperBound(fc.getArgument(0)) < -1.0 and + description = "argument is less than 1" + or + functionWithDomainError = getMathVariants("fmod") and + exprMayEqualZero(fc.getArgument(1)) and + description = "y is 0" + ) +} + +abstract class PotentiallyNaNExpr extends Expr { + abstract string getReason(); +} + +class DomainErrorFunctionCall extends FunctionCall, PotentiallyNaNExpr { + string reason; + + DomainErrorFunctionCall() { + hasDomainError(this, reason) + } + + override string getReason() { result = reason } +} + // IEEE 754-1985 Section 7.1 invalid operations -class InvalidOperationExpr extends BinaryOperation { +class InvalidOperationExpr extends BinaryOperation, PotentiallyNaNExpr { string reason; InvalidOperationExpr() { @@ -85,7 +150,7 @@ class InvalidOperationExpr extends BinaryOperation { ) } - string getReason() { result = reason } + override string getReason() { result = reason } } module InvalidNaNUsage implements DataFlow::ConfigSig { @@ -104,7 +169,7 @@ module InvalidNaNUsage implements DataFlow::ConfigSig { * An expression which may produce a NaN output. */ additional predicate potentialSource(DataFlow::Node node) { - node.asExpr() instanceof InvalidOperationExpr + node.asExpr() instanceof PotentiallyNaNExpr } predicate isBarrierOut(DataFlow::Node node) { @@ -173,13 +238,14 @@ from InvalidNaNUsage usage, Expr sourceExpr, string sourceString, Element extra, string extraString where not InvalidNaNFlow::PathGraph::edges(_, source, _, _) and + not InvalidNaNFlow::PathGraph::edges(sink, _, _, _) and not sourceExpr.isFromTemplateInstantiation(_) and not usage.asExpr().isFromTemplateInstantiation(_) and elem = MacroUnwrapper::unwrapElement(sink.getNode().asExpr()) and usage = sink.getNode() and sourceExpr = source.getNode().asExpr() and sourceString = - " (" + source.getNode().asExpr().(InvalidOperationExpr).getReason() + ")" and + " (" + source.getNode().asExpr().(PotentiallyNaNExpr).getReason() + ")" and InvalidNaNFlow::flow(source.getNode(), usage) and ( if not sourceExpr.getEnclosingFunction() = usage.asExpr().getEnclosingFunction() diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected index 75534df6a0..f1f08b5a51 100644 --- a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected +++ b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected @@ -21,6 +21,21 @@ edges | test.c:77:15:77:21 | ... / ... | test.c:114:16:114:23 | l12 | provenance | | | test.c:77:15:77:21 | ... / ... | test.c:117:23:117:30 | l12 | provenance | | | test.c:77:15:77:21 | ... / ... | test.c:120:20:120:27 | l12 | provenance | | +| test.c:175:22:175:22 | p | test.c:175:27:175:32 | p | provenance | | +| test.c:183:34:183:34 | p | test.c:185:13:185:18 | p | provenance | | +| test.c:189:32:189:32 | p | test.c:189:47:189:59 | ... + ... | provenance | Config | +| test.c:189:47:189:59 | ... + ... | test.c:175:22:175:22 | p | provenance | | +| test.c:189:47:189:59 | ... + ... | test.c:175:22:175:22 | p | provenance | | +| test.c:189:51:189:59 | ... / ... | test.c:189:47:189:59 | ... + ... | provenance | Config | +| test.c:193:13:194:15 | ... / ... | test.c:175:22:175:22 | p | provenance | | +| test.c:200:25:200:33 | ... / ... | test.c:183:34:183:34 | p | provenance | | +| test.c:204:19:204:27 | ... / ... | test.c:204:19:204:27 | ... / ... | provenance | | +| test.c:204:19:204:27 | ... / ... | test.c:206:21:206:31 | ... + ... | provenance | Config | +| test.c:206:21:206:31 | ... + ... | test.c:206:21:206:31 | ... + ... | provenance | | +| test.c:206:21:206:31 | ... + ... | test.c:208:13:208:21 | middleInf | provenance | | +| test.c:206:21:206:31 | ... + ... | test.c:210:23:210:31 | middleInf | provenance | | +| test.c:208:13:208:21 | middleInf | test.c:175:22:175:22 | p | provenance | | +| test.c:210:23:210:31 | middleInf | test.c:189:32:189:32 | p | provenance | | nodes | test.c:8:14:8:20 | ... / ... | semmle.label | ... / ... | | test.c:8:14:8:20 | ... / ... | semmle.label | ... / ... | @@ -51,29 +66,48 @@ nodes | test.c:114:16:114:23 | l12 | semmle.label | l12 | | test.c:117:23:117:30 | l12 | semmle.label | l12 | | test.c:120:20:120:27 | l12 | semmle.label | l12 | +| test.c:163:3:164:16 | ... / ... | semmle.label | ... / ... | +| test.c:175:22:175:22 | p | semmle.label | p | +| test.c:175:27:175:32 | p | semmle.label | p | +| test.c:183:34:183:34 | p | semmle.label | p | +| test.c:185:13:185:18 | p | semmle.label | p | +| test.c:189:32:189:32 | p | semmle.label | p | +| test.c:189:47:189:59 | ... + ... | semmle.label | ... + ... | +| test.c:189:47:189:59 | ... + ... | semmle.label | ... + ... | +| test.c:189:51:189:59 | ... / ... | semmle.label | ... / ... | +| test.c:193:13:194:15 | ... / ... | semmle.label | ... / ... | +| test.c:200:25:200:33 | ... / ... | semmle.label | ... / ... | +| test.c:204:19:204:27 | ... / ... | semmle.label | ... / ... | +| test.c:204:19:204:27 | ... / ... | semmle.label | ... / ... | +| test.c:206:21:206:31 | ... + ... | semmle.label | ... + ... | +| test.c:206:21:206:31 | ... + ... | semmle.label | ... + ... | +| test.c:208:13:208:21 | middleInf | semmle.label | middleInf | +| test.c:210:23:210:31 | middleInf | semmle.label | middleInf | subpaths #select -| test.c:12:8:12:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:12:8:12:9 | l2 | Invalid usage of possible $@. | test.c:8:14:8:20 | ... / ... | infinity | -| test.c:13:8:13:9 | l3 | test.c:8:14:8:20 | ... / ... | test.c:13:8:13:9 | l3 | Invalid usage of possible $@. | test.c:8:14:8:20 | ... / ... | infinity | -| test.c:13:8:13:9 | l3 | test.c:9:14:9:16 | - ... | test.c:13:8:13:9 | l3 | Invalid usage of possible $@. | test.c:9:14:9:16 | - ... | infinity | -| test.c:18:8:18:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:18:3:18:9 | l2 | Invalid usage of possible $@. | test.c:8:14:8:20 | ... / ... | infinity | -| test.c:19:8:19:9 | l3 | test.c:8:14:8:20 | ... / ... | test.c:19:3:19:9 | l3 | Invalid usage of possible $@. | test.c:8:14:8:20 | ... / ... | infinity | -| test.c:19:8:19:9 | l3 | test.c:9:14:9:16 | - ... | test.c:19:3:19:9 | l3 | Invalid usage of possible $@. | test.c:9:14:9:16 | - ... | infinity | -| test.c:27:19:27:20 | l2 | test.c:8:14:8:20 | ... / ... | test.c:27:19:27:20 | l2 | Invalid usage of possible $@. | test.c:8:14:8:20 | ... / ... | infinity | -| test.c:28:19:28:20 | l3 | test.c:8:14:8:20 | ... / ... | test.c:28:19:28:20 | l3 | Invalid usage of possible $@. | test.c:8:14:8:20 | ... / ... | infinity | -| test.c:28:19:28:20 | l3 | test.c:9:14:9:16 | - ... | test.c:28:19:28:20 | l3 | Invalid usage of possible $@. | test.c:9:14:9:16 | - ... | infinity | -| test.c:38:8:38:9 | l7 | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | Invalid usage of possible $@. | test.c:31:14:32:15 | ... / ... | infinity | -| test.c:61:11:61:17 | ... / ... | test.c:61:5:61:18 | ... / ... | test.c:61:5:61:18 | ... / ... | Invalid usage of possible $@. | test.c:61:5:61:18 | ... / ... | infinity | -| test.c:66:11:66:19 | ... / ... | test.c:66:5:66:20 | ... / ... | test.c:66:5:66:20 | ... / ... | Invalid usage of possible $@. | test.c:66:5:66:20 | ... / ... | infinity | -| test.c:72:20:72:28 | ... / ... | test.c:72:14:72:29 | ... / ... | test.c:72:14:72:29 | ... / ... | Invalid usage of possible $@. | test.c:72:14:72:29 | ... / ... | infinity | -| test.c:75:24:75:32 | ... / ... | test.c:75:18:75:33 | ... / ... | test.c:75:18:75:33 | ... / ... | Invalid usage of possible $@. | test.c:75:18:75:33 | ... / ... | infinity | -| test.c:79:10:79:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:79:5:79:12 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | -| test.c:87:10:87:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:87:5:87:12 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | -| test.c:91:10:91:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:91:5:91:12 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | -| test.c:93:10:93:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:93:5:93:12 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | -| test.c:99:10:99:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:99:5:99:12 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | -| test.c:105:10:105:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:105:5:105:12 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | -| test.c:111:10:111:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:111:5:111:12 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | -| test.c:114:21:114:23 | l12 | test.c:77:15:77:21 | ... / ... | test.c:114:16:114:23 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | -| test.c:117:28:117:30 | l12 | test.c:77:15:77:21 | ... / ... | test.c:117:23:117:30 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | -| test.c:120:25:120:27 | l12 | test.c:77:15:77:21 | ... / ... | test.c:120:20:120:27 | l12 | Invalid usage of possible $@. | test.c:77:15:77:21 | ... / ... | infinity | +| test.c:12:8:12:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:12:8:12:9 | l2 | Division operation may silently underflow and produce zero, as the divisor $@. | test.c:8:14:8:20 | ... / ... | may be an infinite float value from division by zero | +| test.c:13:8:13:9 | l3 | test.c:8:14:8:20 | ... / ... | test.c:13:8:13:9 | l3 | Division operation may silently underflow and produce zero, as the divisor $@. | test.c:8:14:8:20 | ... / ... | may be an infinite float value from division by zero | +| test.c:18:8:18:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:18:3:18:9 | l2 | $@ casted to integer. | test.c:8:14:8:20 | ... / ... | Possibly infinite float value from division by zero | +| test.c:19:8:19:9 | l3 | test.c:8:14:8:20 | ... / ... | test.c:19:3:19:9 | l3 | $@ casted to integer. | test.c:8:14:8:20 | ... / ... | Possibly infinite float value from division by zero | +| test.c:27:19:27:20 | l2 | test.c:8:14:8:20 | ... / ... | test.c:27:19:27:20 | l2 | Division operation may silently underflow and produce zero, as the divisor $@. | test.c:8:14:8:20 | ... / ... | may be an infinite float value from division by zero | +| test.c:28:19:28:20 | l3 | test.c:8:14:8:20 | ... / ... | test.c:28:19:28:20 | l3 | Division operation may silently underflow and produce zero, as the divisor $@. | test.c:8:14:8:20 | ... / ... | may be an infinite float value from division by zero | +| test.c:38:8:38:9 | l7 | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | $@ casted to integer. | test.c:31:14:32:15 | ... / ... | Possibly infinite float value from division by zero | +| test.c:61:11:61:17 | ... / ... | test.c:61:5:61:18 | ... / ... | test.c:61:5:61:18 | ... / ... | $@ casted to integer. | test.c:61:11:61:17 | ... / ... | Possibly infinite float value from division by zero | +| test.c:66:11:66:19 | ... / ... | test.c:66:5:66:20 | ... / ... | test.c:66:5:66:20 | ... / ... | $@ casted to integer. | test.c:66:11:66:19 | ... / ... | Possibly infinite float value from division by zero | +| test.c:72:20:72:28 | ... / ... | test.c:72:14:72:29 | ... / ... | test.c:72:14:72:29 | ... / ... | $@ casted to integer. | test.c:72:20:72:28 | ... / ... | Possibly infinite float value from division by zero | +| test.c:75:24:75:32 | ... / ... | test.c:75:18:75:33 | ... / ... | test.c:75:18:75:33 | ... / ... | $@ casted to integer. | test.c:75:24:75:32 | ... / ... | Possibly infinite float value from division by zero | +| test.c:79:10:79:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:79:5:79:12 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | +| test.c:87:10:87:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:87:5:87:12 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | +| test.c:91:10:91:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:91:5:91:12 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | +| test.c:93:10:93:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:93:5:93:12 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | +| test.c:99:10:99:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:99:5:99:12 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | +| test.c:105:10:105:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:105:5:105:12 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | +| test.c:111:10:111:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:111:5:111:12 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | +| test.c:114:21:114:23 | l12 | test.c:77:15:77:21 | ... / ... | test.c:114:16:114:23 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | +| test.c:117:28:117:30 | l12 | test.c:77:15:77:21 | ... / ... | test.c:117:23:117:30 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | +| test.c:120:25:120:27 | l12 | test.c:77:15:77:21 | ... / ... | test.c:120:20:120:27 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | +| test.c:163:9:164:15 | ... / ... | test.c:163:3:164:16 | ... / ... | test.c:163:3:164:16 | ... / ... | $@ casted to integer. | test.c:163:9:164:15 | ... / ... | Possibly infinite float value from division by zero | +| test.c:175:32:175:32 | p | test.c:189:51:189:59 | ... / ... | test.c:175:27:175:32 | p | $@ casted to integer. | test.c:189:6:189:24 | addInfThenCastToInt | Possibly infinite float value computed in function addInfThenCastToInt | +| test.c:175:32:175:32 | p | test.c:193:13:194:15 | ... / ... | test.c:175:27:175:32 | p | $@ casted to integer. | test.c:192:6:192:7 | f2 | Possibly infinite float value computed in function f2 | +| test.c:175:32:175:32 | p | test.c:204:19:204:27 | ... / ... | test.c:175:27:175:32 | p | $@ casted to integer. | test.c:192:6:192:7 | f2 | Possibly infinite float value computed in function f2 | +| test.c:185:18:185:18 | p | test.c:200:25:200:33 | ... / ... | test.c:185:13:185:18 | p | $@ casted to integer. | test.c:192:6:192:7 | f2 | Possibly infinite float value computed in function f2 | diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected index e59d43d867..e0047d9ef7 100644 --- a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected +++ b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected @@ -22,9 +22,27 @@ edges | test.c:122:15:122:21 | ... / ... | test.c:138:5:138:12 | l13 | provenance | | | test.c:122:15:122:21 | ... / ... | test.c:144:5:144:12 | l13 | provenance | | | test.c:122:15:122:21 | ... / ... | test.c:148:5:148:12 | l13 | provenance | | -| test.c:122:15:122:21 | ... / ... | test.c:154:20:154:27 | l13 | provenance | | -| test.c:122:15:122:21 | ... / ... | test.c:156:23:156:30 | l13 | provenance | | -| test.c:122:15:122:21 | ... / ... | test.c:157:16:157:23 | l13 | provenance | | +| test.c:122:15:122:21 | ... / ... | test.c:155:20:155:27 | l13 | provenance | | +| test.c:122:15:122:21 | ... / ... | test.c:157:23:157:30 | l13 | provenance | | +| test.c:122:15:122:21 | ... / ... | test.c:158:16:158:23 | l13 | provenance | | +| test.c:175:22:175:22 | p | test.c:175:27:175:32 | p | provenance | | +| test.c:183:34:183:34 | p | test.c:185:13:185:18 | p | provenance | | +| test.c:188:32:188:32 | p | test.c:188:47:188:51 | ... + ... | provenance | Config | +| test.c:188:47:188:51 | ... + ... | test.c:175:22:175:22 | p | provenance | | +| test.c:190:32:190:32 | p | test.c:190:47:190:59 | ... + ... | provenance | Config | +| test.c:190:47:190:59 | ... + ... | test.c:175:22:175:22 | p | provenance | | +| test.c:190:47:190:59 | ... + ... | test.c:175:22:175:22 | p | provenance | | +| test.c:190:51:190:59 | ... / ... | test.c:190:47:190:59 | ... + ... | provenance | Config | +| test.c:195:13:195:21 | ... / ... | test.c:175:22:175:22 | p | provenance | | +| test.c:199:23:199:31 | ... / ... | test.c:188:32:188:32 | p | provenance | | +| test.c:201:25:201:33 | ... / ... | test.c:183:34:183:34 | p | provenance | | +| test.c:205:19:205:27 | ... / ... | test.c:205:19:205:27 | ... / ... | provenance | | +| test.c:205:19:205:27 | ... / ... | test.c:207:21:207:31 | ... + ... | provenance | Config | +| test.c:207:21:207:31 | ... + ... | test.c:207:21:207:31 | ... + ... | provenance | | +| test.c:207:21:207:31 | ... + ... | test.c:209:13:209:21 | middleNaN | provenance | | +| test.c:207:21:207:31 | ... + ... | test.c:211:23:211:31 | middleNaN | provenance | | +| test.c:209:13:209:21 | middleNaN | test.c:175:22:175:22 | p | provenance | | +| test.c:211:23:211:31 | middleNaN | test.c:190:32:190:32 | p | provenance | | nodes | test.c:27:14:27:20 | ... / ... | semmle.label | ... / ... | | test.c:27:14:27:20 | ... / ... | semmle.label | ... / ... | @@ -58,33 +76,61 @@ nodes | test.c:138:5:138:12 | l13 | semmle.label | l13 | | test.c:144:5:144:12 | l13 | semmle.label | l13 | | test.c:148:5:148:12 | l13 | semmle.label | l13 | -| test.c:154:20:154:27 | l13 | semmle.label | l13 | -| test.c:156:23:156:30 | l13 | semmle.label | l13 | -| test.c:157:16:157:23 | l13 | semmle.label | l13 | +| test.c:155:20:155:27 | l13 | semmle.label | l13 | +| test.c:157:23:157:30 | l13 | semmle.label | l13 | +| test.c:158:16:158:23 | l13 | semmle.label | l13 | +| test.c:166:3:166:18 | call to pow | semmle.label | call to pow | +| test.c:171:3:171:15 | call to acos | semmle.label | call to acos | +| test.c:175:22:175:22 | p | semmle.label | p | +| test.c:175:27:175:32 | p | semmle.label | p | +| test.c:183:34:183:34 | p | semmle.label | p | +| test.c:185:13:185:18 | p | semmle.label | p | +| test.c:188:32:188:32 | p | semmle.label | p | +| test.c:188:47:188:51 | ... + ... | semmle.label | ... + ... | +| test.c:190:32:190:32 | p | semmle.label | p | +| test.c:190:47:190:59 | ... + ... | semmle.label | ... + ... | +| test.c:190:47:190:59 | ... + ... | semmle.label | ... + ... | +| test.c:190:51:190:59 | ... / ... | semmle.label | ... / ... | +| test.c:195:13:195:21 | ... / ... | semmle.label | ... / ... | +| test.c:199:23:199:31 | ... / ... | semmle.label | ... / ... | +| test.c:201:25:201:33 | ... / ... | semmle.label | ... / ... | +| test.c:205:19:205:27 | ... / ... | semmle.label | ... / ... | +| test.c:205:19:205:27 | ... / ... | semmle.label | ... / ... | +| test.c:207:21:207:31 | ... + ... | semmle.label | ... + ... | +| test.c:207:21:207:31 | ... + ... | semmle.label | ... + ... | +| test.c:209:13:209:21 | middleNaN | semmle.label | middleNaN | +| test.c:211:23:211:31 | middleNaN | semmle.label | middleNaN | subpaths #select -| test.c:36:8:36:9 | l5 | test.c:27:14:27:20 | ... / ... | test.c:36:3:36:9 | l5 | Invalid usage of possible $@. | test.c:27:14:27:20 | ... / ... | NaN resulting from possible division of infinity by infinity | -| test.c:37:8:37:9 | l6 | test.c:28:14:28:20 | ... / ... | test.c:37:3:37:9 | l6 | Invalid usage of possible $@. | test.c:28:14:28:20 | ... / ... | NaN resulting from possible division of infinity by infinity | -| test.c:38:8:38:9 | l7 | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | Invalid usage of possible $@. | test.c:31:14:32:15 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:39:8:39:9 | l8 | test.c:33:14:33:22 | ... / ... | test.c:39:3:39:9 | l8 | Invalid usage of possible $@. | test.c:33:14:33:22 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:46:3:46:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:46:3:46:4 | l5 | Invalid usage of possible $@. | test.c:27:14:27:20 | ... / ... | NaN resulting from possible division of infinity by infinity | -| test.c:47:3:47:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:47:3:47:4 | l5 | Invalid usage of possible $@. | test.c:27:14:27:20 | ... / ... | NaN resulting from possible division of infinity by infinity | -| test.c:48:3:48:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:48:3:48:4 | l5 | Invalid usage of possible $@. | test.c:27:14:27:20 | ... / ... | NaN resulting from possible division of infinity by infinity | -| test.c:49:3:49:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:49:3:49:4 | l5 | Invalid usage of possible $@. | test.c:27:14:27:20 | ... / ... | NaN resulting from possible division of infinity by infinity | -| test.c:50:3:50:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:50:3:50:4 | l5 | Invalid usage of possible $@. | test.c:27:14:27:20 | ... / ... | NaN resulting from possible division of infinity by infinity | -| test.c:51:3:51:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:51:3:51:4 | l5 | Invalid usage of possible $@. | test.c:27:14:27:20 | ... / ... | NaN resulting from possible division of infinity by infinity | -| test.c:52:3:52:4 | l6 | test.c:28:14:28:20 | ... / ... | test.c:52:3:52:4 | l6 | Invalid usage of possible $@. | test.c:28:14:28:20 | ... / ... | NaN resulting from possible division of infinity by infinity | -| test.c:53:3:53:4 | l7 | test.c:31:14:32:15 | ... / ... | test.c:53:3:53:4 | l7 | Invalid usage of possible $@. | test.c:31:14:32:15 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:54:3:54:4 | l8 | test.c:33:14:33:22 | ... / ... | test.c:54:3:54:4 | l8 | Invalid usage of possible $@. | test.c:33:14:33:22 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:61:11:61:17 | ... / ... | test.c:61:5:61:18 | ... / ... | test.c:61:5:61:18 | ... / ... | Invalid usage of possible $@. | test.c:61:5:61:18 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:66:11:66:19 | ... / ... | test.c:66:5:66:20 | ... / ... | test.c:66:5:66:20 | ... / ... | Invalid usage of possible $@. | test.c:66:5:66:20 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:72:20:72:28 | ... / ... | test.c:72:14:72:29 | ... / ... | test.c:72:14:72:29 | ... / ... | Invalid usage of possible $@. | test.c:72:14:72:29 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:75:24:75:32 | ... / ... | test.c:75:18:75:33 | ... / ... | test.c:75:18:75:33 | ... / ... | Invalid usage of possible $@. | test.c:75:18:75:33 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:126:10:126:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:126:5:126:12 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:132:10:132:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:132:5:132:12 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:138:10:138:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:138:5:138:12 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:144:10:144:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:144:5:144:12 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:148:10:148:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:148:5:148:12 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:154:25:154:27 | l13 | test.c:122:15:122:21 | ... / ... | test.c:154:20:154:27 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:156:28:156:30 | l13 | test.c:122:15:122:21 | ... / ... | test.c:156:23:156:30 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | -| test.c:157:21:157:23 | l13 | test.c:122:15:122:21 | ... / ... | test.c:157:16:157:23 | l13 | Invalid usage of possible $@. | test.c:122:15:122:21 | ... / ... | NaN resulting from possible division of zero by zero | +| test.c:36:8:36:9 | l5 | test.c:27:14:27:20 | ... / ... | test.c:36:3:36:9 | l5 | $@ casted to integer. | test.c:27:14:27:20 | ... / ... | Possibly NaN float value (from division of infinity by infinity) | +| test.c:37:8:37:9 | l6 | test.c:28:14:28:20 | ... / ... | test.c:37:3:37:9 | l6 | $@ casted to integer. | test.c:28:14:28:20 | ... / ... | Possibly NaN float value (from division of infinity by infinity) | +| test.c:38:8:38:9 | l7 | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | $@ casted to integer. | test.c:31:14:32:15 | ... / ... | Possibly NaN float value (from division of zero by zero) | +| test.c:39:8:39:9 | l8 | test.c:33:14:33:22 | ... / ... | test.c:39:3:39:9 | l8 | $@ casted to integer. | test.c:33:14:33:22 | ... / ... | Possibly NaN float value (from division of zero by zero) | +| test.c:46:3:46:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:46:3:46:4 | l5 | Comparison involving a $@, which always evaluates to false. | test.c:27:14:27:20 | ... / ... | possibly NaN float value (from division of infinity by infinity) | +| test.c:47:3:47:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:47:3:47:4 | l5 | Comparison involving a $@, which always evaluates to false. | test.c:27:14:27:20 | ... / ... | possibly NaN float value (from division of infinity by infinity) | +| test.c:48:3:48:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:48:3:48:4 | l5 | Comparison involving a $@, which always evaluates to false. | test.c:27:14:27:20 | ... / ... | possibly NaN float value (from division of infinity by infinity) | +| test.c:49:3:49:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:49:3:49:4 | l5 | Comparison involving a $@, which always evaluates to false. | test.c:27:14:27:20 | ... / ... | possibly NaN float value (from division of infinity by infinity) | +| test.c:50:3:50:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:50:3:50:4 | l5 | Comparison involving a $@, which always evaluates to false. | test.c:27:14:27:20 | ... / ... | possibly NaN float value (from division of infinity by infinity) | +| test.c:51:3:51:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:51:3:51:4 | l5 | Comparison involving a $@, which always evaluates to false. | test.c:27:14:27:20 | ... / ... | possibly NaN float value (from division of infinity by infinity) | +| test.c:52:3:52:4 | l6 | test.c:28:14:28:20 | ... / ... | test.c:52:3:52:4 | l6 | Comparison involving a $@, which always evaluates to false. | test.c:28:14:28:20 | ... / ... | possibly NaN float value (from division of infinity by infinity) | +| test.c:53:3:53:4 | l7 | test.c:31:14:32:15 | ... / ... | test.c:53:3:53:4 | l7 | Comparison involving a $@, which always evaluates to false. | test.c:31:14:32:15 | ... / ... | possibly NaN float value (from division of zero by zero) | +| test.c:54:3:54:4 | l8 | test.c:33:14:33:22 | ... / ... | test.c:54:3:54:4 | l8 | Comparison involving a $@, which always evaluates to false. | test.c:33:14:33:22 | ... / ... | possibly NaN float value (from division of zero by zero) | +| test.c:61:11:61:17 | ... / ... | test.c:61:5:61:18 | ... / ... | test.c:61:5:61:18 | ... / ... | $@ casted to integer. | test.c:61:11:61:17 | ... / ... | Possibly NaN float value (from division of zero by zero) | +| test.c:66:11:66:19 | ... / ... | test.c:66:5:66:20 | ... / ... | test.c:66:5:66:20 | ... / ... | $@ casted to integer. | test.c:66:11:66:19 | ... / ... | Possibly NaN float value (from division of zero by zero) | +| test.c:72:20:72:28 | ... / ... | test.c:72:14:72:29 | ... / ... | test.c:72:14:72:29 | ... / ... | $@ casted to integer. | test.c:72:20:72:28 | ... / ... | Possibly NaN float value (from division of zero by zero) | +| test.c:75:24:75:32 | ... / ... | test.c:75:18:75:33 | ... / ... | test.c:75:18:75:33 | ... / ... | $@ casted to integer. | test.c:75:24:75:32 | ... / ... | Possibly NaN float value (from division of zero by zero) | +| test.c:126:10:126:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:126:5:126:12 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | +| test.c:132:10:132:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:132:5:132:12 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | +| test.c:138:10:138:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:138:5:138:12 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | +| test.c:144:10:144:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:144:5:144:12 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | +| test.c:148:10:148:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:148:5:148:12 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | +| test.c:155:25:155:27 | l13 | test.c:122:15:122:21 | ... / ... | test.c:155:20:155:27 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | +| test.c:157:28:157:30 | l13 | test.c:122:15:122:21 | ... / ... | test.c:157:23:157:30 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | +| test.c:158:21:158:23 | l13 | test.c:122:15:122:21 | ... / ... | test.c:158:16:158:23 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | +| test.c:166:8:166:10 | call to pow | test.c:166:3:166:18 | call to pow | test.c:166:3:166:18 | call to pow | $@ casted to integer. | test.c:166:8:166:10 | call to pow | Possibly NaN float value (both arguments are equal to zero) | +| test.c:171:8:171:11 | call to acos | test.c:171:3:171:15 | call to acos | test.c:171:3:171:15 | call to acos | $@ casted to integer. | test.c:171:8:171:11 | call to acos | Possibly NaN float value (the argument has a range -1000000000000000...1000000000000000 which is outside the domain of this function (-1.0...1.0)) | +| test.c:175:32:175:32 | p | test.c:190:51:190:59 | ... / ... | test.c:175:27:175:32 | p | $@ casted to integer. | test.c:190:6:190:24 | addNaNThenCastToInt | Possibly NaN float value (from division of zero by zero) computed in function addNaNThenCastToInt | +| test.c:175:32:175:32 | p | test.c:195:13:195:21 | ... / ... | test.c:175:27:175:32 | p | $@ casted to integer. | test.c:192:6:192:7 | f2 | Possibly NaN float value (from division of zero by zero) computed in function f2 | +| test.c:175:32:175:32 | p | test.c:199:23:199:31 | ... / ... | test.c:175:27:175:32 | p | $@ casted to integer. | test.c:192:6:192:7 | f2 | Possibly NaN float value (from division of zero by zero) computed in function f2 | +| test.c:175:32:175:32 | p | test.c:205:19:205:27 | ... / ... | test.c:175:27:175:32 | p | $@ casted to integer. | test.c:192:6:192:7 | f2 | Possibly NaN float value (from division of zero by zero) computed in function f2 | +| test.c:185:18:185:18 | p | test.c:201:25:201:33 | ... / ... | test.c:185:13:185:18 | p | $@ casted to integer. | test.c:192:6:192:7 | f2 | Possibly NaN float value (from division of zero by zero) computed in function f2 | diff --git a/c/misra/test/rules/DIR-4-15/test.c b/c/misra/test/rules/DIR-4-15/test.c index d0f9ab5418..e615d3447a 100644 --- a/c/misra/test/rules/DIR-4-15/test.c +++ b/c/misra/test/rules/DIR-4-15/test.c @@ -150,10 +150,63 @@ void f1(float p1) { (int)l13; // COMPLIANT: Guarded not to be NaN } - isinf(l13) ? (int)l13 : 0; // COMPLIANT: Checked infinite, therefore not NaN, before use + isinf(l13) ? (int)l13 + : 0; // COMPLIANT: Checked infinite, therefore not NaN, before use isinf(l13) ? 0 : (int)l13; // COMPLIANT: Check on wrong branch isfinite(l13) ? (int)l13 : 0; // COMPLIANT: Checked finite before use isfinite(l13) ? 0 : (int)l13; // NON_COMPLIANT: Checked on wrong branch - isnan(l13) ? (int)l13 : 0; // NON_COMPLIANT: Check on wrong branch - isnan(l13) ? 0 : (int)l13; // COMPLIANT: Checked not NaN before use + isnan(l13) ? (int)l13 : 0; // NON_COMPLIANT: Check on wrong branch + isnan(l13) ? 0 : (int)l13; // COMPLIANT: Checked not NaN before use + + (int)pow(2, p1); // NON_COMPLIANT: likely to be Infinity + (int)pow(2, sin(p1)); // COMPLIANT: not likely to be Infinity + (int)(1 / + sin(p1)); // NON_COMPLIANT: possible infinity from zero in denominator + (int)(1 / log(p1)); // COMPLIANT: not possibly zero in denominator + (int)pow(p1, p1); // NON_COMPLIANT: NaN if p1 is zero + if (p1 != 0) { + (int)pow(p1, p1); // COMPLIANT: p1 is not zero + } + + (int)acos(p1); // NON_COMPLIANT: NaN if p1 is not within -1..1 + (int)acos(cos(p1)); // COMPLIANT: cos(p1) is within -1..1 +} + +void castToInt(float p) { (int)p; } + +void checkBeforeCastToInt(float p) { + if (isfinite(p)) { + castToInt(p); + } +} + +void castToIntToFloatToInt(float p) { + // This should be reported as a violation, but not downstream from here. + castToInt((int)p); +} + +void addOneThenCastToInt(float p) { castToInt(p + 1); } +void addInfThenCastToInt(float p) { castToInt(p + 1.0 / 0.0); } +void addNaNThenCastToInt(float p) { castToInt(p + 0.0 / 0.0); } + +void f2() { + castToInt(1.0 / + 0.0); // NON_COMPLIANT: Infinity flows to denominator in division + castToInt(0.0 / 0.0); // NON_COMPLIANT: NaN flows to denominator in division + checkBeforeCastToInt(1.0 / 0.0); // COMPLIANT + checkBeforeCastToInt(0.0 / 0.0); // COMPLIANT + addOneThenCastToInt(1.0 / 0.0); // NON_COMPLIANT[False negative] + addOneThenCastToInt(0.0 / 0.0); // NON_COMPLIANT + castToIntToFloatToInt(1.0 / 0.0); // NON_COMPLIANT + castToIntToFloatToInt(0.0 / 0.0); // NON_COMPLIANT + + // Check that during flow analysis, we only report the true root cause: + float rootInf = 1.0 / 0.0; + float rootNaN = 0.0 / 0.0; + float middleInf = rootInf + 1; + float middleNaN = rootNaN + 1; + castToInt(middleInf); // NON_COMPLIANT + castToInt(middleNaN); // NON_COMPLIANT + addInfThenCastToInt(middleInf); // NON_COMPLIANT + addNaNThenCastToInt(middleNaN); // NON_COMPLIANT } \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll index 8ae3c9c38b..0c98824dbf 100644 --- a/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll +++ b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll @@ -84,7 +84,9 @@ module RestrictedRangeAnalysis { result = -256.0 or result = -32768.0 or result = -65536.0 or - result = max(float v | v = Util::typeLowerBound(t) or v = -largeValue()) + result = -largeValue() or + result = Util::typeLowerBound(t) + //result = max(float v | v = Util::typeLowerBound(t) or v = -largeValue()) } /** See comment for `wideningLowerBounds`, above. */ @@ -100,7 +102,9 @@ module RestrictedRangeAnalysis { result = 255.0 or result = 32767.0 or result = 65535.0 or - result = min(float v | v = Util::typeLowerBound(t) or v = largeValue()) + result = largeValue() or + result = Util::typeUpperBound(t) + //result = min(float v | v = Util::typeLowerBound(t) or v = largeValue()) } /** @@ -312,6 +316,196 @@ module RestrictedRangeAnalysis { ) } + bindingset[name] + Function getMathVariants(string name) { + result.hasGlobalOrStdName([name, name + "f", name + "l"]) + } + + /** + * New support added for mathematical functions that either monotonically increase, or decrease, + * or that have a known lower or upper bound. + * + * For instance, log(x) monotonically increases over x, and acos(x) monotonically decreases, + * while sin(x) has a known output range of -1 to 1. + * + * `pow` is especially common so minimal work is done to support that here as well. `pow(c, x)` + * monotonically increases or decreases over `x` if `c` is a constant, though the reverse is not + * true except in special cases. + */ + newtype TSupportedMathFunctionCall = + /* A monotonically increasing function call. `extra` is a constant for `pow(x, c)`. */ + TMonotonicIncrease(FunctionCall fc, Expr input, float extra) { + // Note: Codeql has no default implementation in codeql for exp2, atanh, acosh, asinh, or + // log1p so we haven't taken the time to support them yet. + fc.getTarget() = + getMathVariants(["log", "log2", "log10", "exp", "asin", "atan", "sinh", "sqrt"]) and + input = fc.getArgument(0) and + extra = 0.0 + or + // Notes: pow is monotonic if the base argument is constant, increasing if the base is greater + // than 1 or between -1 and 0, and decreasing otherwise. A constant power is monotonic over the + // base in the positive or negative domain, but distinguishing those separately can introduce + // non-monotonic recursion errors. + fc.getTarget() = getMathVariants("pow") and + extra = fc.getArgument(0).getValue().toFloat() and + ( + extra > 1.0 + or + extra < 0.0 and extra > -1.0 + ) and + input = fc.getArgument(1) + } or + /* A monotonically decreasing function call. `extra` is a constant for `pow(x, c)`. */ + TMonotonicDecrease(FunctionCall fc, Expr input, float extra) { + fc.getTarget() = getMathVariants(["acos"]) and + input = fc.getArgument(0) and + extra = 0.0 + or + fc.getTarget() = getMathVariants("pow") and + extra = fc.getArgument(0).getValue().toFloat() and + ( + extra < -1.0 + or + extra > 0.0 and extra < 1.0 + ) and + input = fc.getArgument(1) + } or + /* A non-mononotic function call with a known lower bound. */ + TNonMonotonicLowerBound(FunctionCall fc, float lb) { + fc.getTarget() = getMathVariants("cosh") and + lb = 1.0 + or + fc.getTarget() = getMathVariants(["cos", "sin"]) and + lb = -1.0 + } or + /* A non-mononotic function call with a known upper bound. */ + TNonMonotonicUpperBound(FunctionCall fc, float lb) { + fc.getTarget() = getMathVariants(["cos", "sin"]) and + lb = 1.0 + } + + /** + * A function call that is supported by range analysis. + */ + class SupportedFunctionCall extends TSupportedMathFunctionCall { + string toString() { + exists(FunctionCall fc | + this = TMonotonicIncrease(fc, _, _) and + result = "Monotonic increase " + fc.getTarget().getName() + or + this = TMonotonicDecrease(fc, _, _) and + result = "Monotonic decrease " + fc.getTarget().getName() + or + this = TNonMonotonicLowerBound(fc, _) and + result = "Nonmonotonic lower bound " + fc.getTarget().getName() + or + this = TNonMonotonicUpperBound(fc, _) and + result = "Nonmonotonic upper bound " + fc.getTarget().getName() + ) + } + + /** Get the function call node this algebraic type corresponds to. */ + FunctionCall getFunctionCall() { + this = TMonotonicIncrease(result, _, _) + or + this = TMonotonicDecrease(result, _, _) + or + this = TNonMonotonicLowerBound(result, _) + or + this = TNonMonotonicUpperBound(result, _) + } + + /** Get the function name (`sin`, `pow`, etc.) without the `l` or `f` suffix. */ + bindingset[this, result] + string getBaseFunctionName() { getMathVariants(result) = getFunctionCall().getTarget() } + + /** + * Compute a result bound based on an input value and an extra constant value. + * + * The functions `getUpperBound()` and `getLowerBound()` automatically handle the differences + * between monotonically increasing and decreasing functions, and provide the input value. The + * `extra` float exists to support `pow(x, c)` for the constant `c`, otherwise it is `0.0`. + */ + bindingset[value, extra, this] + float compute(float value, float extra) { + exists(string name | name = getBaseFunctionName() | + name = "log" and + result = value.log() + or + name = "log2" and + result = value.log2() + or + name = "log10" and + result = value.log10() + or + name = "exp" and + result = value.exp() + or + name = "asin" and + result = value.asin() + or + name = "atan" and + result = value.atan() + or + name = "acos" and + result = value.acos() + or + name = "sinh" and + result = value.sinh() + or + name = "sqrt" and + result = value.sqrt() + or + name = "pow" and + result = extra.pow(value) + ) + } + + /** + * Get the lower bound of this function, based on its fixed range (if it has one) or based on + * the lower or upper bound of its input, if it is a monotonically increasing or decreasing + * function. + */ + float getLowerBound() { + this = TNonMonotonicLowerBound(_, result) + or + exists(Expr expr, float bound, float extra | + ( + this = TMonotonicIncrease(_, expr, extra) and + bound = getFullyConvertedLowerBounds(expr) + or + this = TMonotonicDecrease(_, expr, extra) and + bound = getFullyConvertedUpperBounds(expr) + ) and + result = compute(bound, extra) + ) + } + + /** + * Get the lower bound of this function, based on its fixed range (if it has one) or based on + * the lower or upper bound of its input, if it is a monotonically increasing or decreasing + * function. + */ + float getUpperBound() { + this = TNonMonotonicUpperBound(_, result) + or + exists(Expr expr, float bound, float extra | + ( + this = TMonotonicIncrease(_, expr, extra) and + bound = getFullyConvertedUpperBounds(expr) + or + this = TMonotonicDecrease(_, expr, extra) and + bound = getFullyConvertedLowerBounds(expr) + ) and + result = compute(bound, extra) + ) + } + } + + predicate supportedMathFunction(FunctionCall fc) { + exists(SupportedFunctionCall sfc | sfc.getFunctionCall() = fc) + } + /** * Holds if `expr` is checked with a guard to not be zero. * @@ -371,6 +565,8 @@ module RestrictedRangeAnalysis { // dividesNonzeroByZero(e) e instanceof DivExpr // TODO: confirm this is OK or + supportedMathFunction(e) + or e instanceof MinExpr or e instanceof MaxExpr @@ -628,8 +824,9 @@ module RestrictedRangeAnalysis { */ int estimatedPhiCombinationsExpr(Expr expr) { if isRecursiveExpr(expr) - // Assume 10 values were computed to analyze recursive expressions. - then result = 10 + then + // Assume 10 values were computed to analyze recursive expressions. + result = 10 else ( exists(RangeSsaDefinition def, StackVariable v | expr = def.getAUse(v) | def.isPhiNode(v) and @@ -649,16 +846,17 @@ module RestrictedRangeAnalysis { ) or not expr instanceof BinaryOperation and - not exprDependsOnDef(expr, _, _) and result = 1 + not exprDependsOnDef(expr, _, _) and + result = 1 ) } /** * Recursively scan this def to see how many phi nodes it depends on. - * + * * If this def is a phi node, it sums its downstream cost and adds one to account for itself, - * which is not exactly correct. - * + * which is not exactly correct. + * * This def may also be a crement expression (not currently supported), or an assign expr * (currently not supported), or an unanalyzable expression which is the root of the recursion * and given a value of 1. @@ -666,8 +864,9 @@ module RestrictedRangeAnalysis { language[monotonicAggregates] int estimatedPhiCombinationsDef(RangeSsaDefinition def, StackVariable v) { if isRecursiveDef(def, v) - // Assume 10 values were computed to analyze recursive expressions. - then result = 10 + then + // Assume 10 values were computed to analyze recursive expressions. + result = 10 else ( if def.isPhiNode(v) then @@ -681,7 +880,9 @@ module RestrictedRangeAnalysis { ) ) else ( - exists(Expr expr | assignmentDef(def, v, expr) | result = estimatedPhiCombinationsExpr(expr)) + exists(Expr expr | assignmentDef(def, v, expr) | + result = estimatedPhiCombinationsExpr(expr) + ) or v = def.getAVariable() and not assignmentDef(def, v, _) and @@ -730,6 +931,17 @@ module RestrictedRangeAnalysis { phiDependsOnDef(def, v, _, _) } + predicate canBoundExpr(Expr e) { + exists(RangeSsaDefinition def, StackVariable v | e = def.getAUse(v) | + analyzableDef(def, v) + ) or + analyzableExpr(e) + or + exists(getGuardedUpperBound(e)) + or + lowerBoundFromGuard(e, _, _, _) + } + /** * Computes a normal form of `x` where -0.0 has changed to +0.0. This can be * needed on the lesser side of a floating-point comparison or on both sides of @@ -931,6 +1143,10 @@ module RestrictedRangeAnalysis { result = getFullyConvertedLowerBounds(div.getLeftOperand()) / 0 ) or + exists(SupportedFunctionCall sfc | sfc.getFunctionCall() = expr | + result = sfc.getLowerBound() + ) + or exists(MinExpr minExpr | expr = minExpr and // Return the union of the lower bounds from both children. @@ -1136,6 +1352,10 @@ module RestrictedRangeAnalysis { result = getFullyConvertedUpperBounds(div.getLeftOperand()) / 0 ) or + exists(SupportedFunctionCall sfc | sfc.getFunctionCall() = expr | + result = sfc.getUpperBound() + ) + or exists(MaxExpr maxExpr | expr = maxExpr and // Return the union of the upper bounds from both children. From 99e92cff45d595f15a033dd7e3559109050e436c Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 7 Feb 2025 04:31:30 -0800 Subject: [PATCH 180/370] formatting fixes --- .../PossibleMisuseOfUndetectedInfinity.ql | 14 +++-- .../DIR-4-15/PossibleMisuseOfUndetectedNaN.ql | 55 +++++++++---------- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql index 357a8fce71..61753c98a9 100644 --- a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql @@ -133,13 +133,15 @@ where ( if not sourceExpr.getEnclosingFunction() = usage.asExpr().getEnclosingFunction() then - extraString = usage.getInfinityDescription() + " computed in function " + sourceExpr.getEnclosingFunction().getName() - and extra = sourceExpr.getEnclosingFunction() + extraString = + usage.getInfinityDescription() + " computed in function " + + sourceExpr.getEnclosingFunction().getName() and + extra = sourceExpr.getEnclosingFunction() else ( extra = sourceExpr and - if sourceExpr instanceof DivExpr - then extraString = usage.getInfinityDescription() + " from division by zero" - else extraString = usage.getInfinityDescription() + if sourceExpr instanceof DivExpr + then extraString = usage.getInfinityDescription() + " from division by zero" + else extraString = usage.getInfinityDescription() ) ) -select elem, source, sink, usage.getDescription(), extra, extraString \ No newline at end of file +select elem, source, sink, usage.getDescription(), extra, extraString diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql index f850cc3e55..701834ca3f 100644 --- a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql @@ -35,7 +35,8 @@ predicate hasDomainError(FunctionCall fc, string description) { ) and description = "the argument has a range " + RestrictedRangeAnalysis::lowerBound(fc.getArgument(0)) + "..." + - RestrictedRangeAnalysis::upperBound(fc.getArgument(0)) + " which is outside the domain of this function (-1.0...1.0)" + RestrictedRangeAnalysis::upperBound(fc.getArgument(0)) + + " which is outside the domain of this function (-1.0...1.0)" or functionWithDomainError = getMathVariants(["atan2", "pow"]) and ( @@ -81,9 +82,7 @@ abstract class PotentiallyNaNExpr extends Expr { class DomainErrorFunctionCall extends FunctionCall, PotentiallyNaNExpr { string reason; - DomainErrorFunctionCall() { - hasDomainError(this, reason) - } + DomainErrorFunctionCall() { hasDomainError(this, reason) } override string getReason() { result = reason } } @@ -203,25 +202,22 @@ class InvalidNaNUsage extends DataFlow::Node { string nanDescription; InvalidNaNUsage() { - // Case 1: NaNs shall not be compared, except to themselves - exists(ComparisonOperation cmp | - this.asExpr() = cmp.getAnOperand() and - not hashCons(cmp.getLeftOperand()) = hashCons(cmp.getRightOperand()) and - description = "Comparison involving a $@, which always evaluates to false." and - nanDescription = "possibly NaN float value" - ) - or - // Case 2: NaNs and infinities shall not be cast to integers - exists(Conversion c | - this.asExpr() = c.getUnconverted() and - c.getExpr().getType() instanceof FloatingPointType and - c.getType() instanceof IntegralType and - description = "$@ casted to integer." and - nanDescription = "Possibly NaN float value" - ) - //or - //// Case 4: Functions shall not return NaNs or infinities - //exists(ReturnStmt ret | node.asExpr() = ret.getExpr()) + // Case 1: NaNs shall not be compared, except to themselves + exists(ComparisonOperation cmp | + this.asExpr() = cmp.getAnOperand() and + not hashCons(cmp.getLeftOperand()) = hashCons(cmp.getRightOperand()) and + description = "Comparison involving a $@, which always evaluates to false." and + nanDescription = "possibly NaN float value" + ) + or + // Case 2: NaNs and infinities shall not be cast to integers + exists(Conversion c | + this.asExpr() = c.getUnconverted() and + c.getExpr().getType() instanceof FloatingPointType and + c.getType() instanceof IntegralType and + description = "$@ casted to integer." and + nanDescription = "Possibly NaN float value" + ) } string getDescription() { result = description } @@ -244,17 +240,18 @@ where elem = MacroUnwrapper::unwrapElement(sink.getNode().asExpr()) and usage = sink.getNode() and sourceExpr = source.getNode().asExpr() and - sourceString = - " (" + source.getNode().asExpr().(PotentiallyNaNExpr).getReason() + ")" and + sourceString = " (" + source.getNode().asExpr().(PotentiallyNaNExpr).getReason() + ")" and InvalidNaNFlow::flow(source.getNode(), usage) and ( if not sourceExpr.getEnclosingFunction() = usage.asExpr().getEnclosingFunction() then - extraString = usage.getNaNDescription() + sourceString + " computed in function " + sourceExpr.getEnclosingFunction().getName() - and extra = sourceExpr.getEnclosingFunction() + extraString = + usage.getNaNDescription() + sourceString + " computed in function " + + sourceExpr.getEnclosingFunction().getName() and + extra = sourceExpr.getEnclosingFunction() else ( extra = sourceExpr and - extraString = usage.getNaNDescription() + sourceString + extraString = usage.getNaNDescription() + sourceString ) ) -select elem, source, sink, usage.getDescription(), extra, extraString \ No newline at end of file +select elem, source, sink, usage.getDescription(), extra, extraString From c473ea0a98848fad8d40e2b292322decfdd4f755 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 7 Feb 2025 04:33:16 -0800 Subject: [PATCH 181/370] C formatting fix --- c/misra/test/rules/DIR-4-15/test.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/c/misra/test/rules/DIR-4-15/test.c b/c/misra/test/rules/DIR-4-15/test.c index e615d3447a..a827a7df97 100644 --- a/c/misra/test/rules/DIR-4-15/test.c +++ b/c/misra/test/rules/DIR-4-15/test.c @@ -162,8 +162,8 @@ void f1(float p1) { (int)pow(2, sin(p1)); // COMPLIANT: not likely to be Infinity (int)(1 / sin(p1)); // NON_COMPLIANT: possible infinity from zero in denominator - (int)(1 / log(p1)); // COMPLIANT: not possibly zero in denominator - (int)pow(p1, p1); // NON_COMPLIANT: NaN if p1 is zero + (int)(1 / log(p1)); // COMPLIANT: not possibly zero in denominator + (int)pow(p1, p1); // NON_COMPLIANT: NaN if p1 is zero if (p1 != 0) { (int)pow(p1, p1); // COMPLIANT: p1 is not zero } @@ -193,10 +193,10 @@ void f2() { castToInt(1.0 / 0.0); // NON_COMPLIANT: Infinity flows to denominator in division castToInt(0.0 / 0.0); // NON_COMPLIANT: NaN flows to denominator in division - checkBeforeCastToInt(1.0 / 0.0); // COMPLIANT - checkBeforeCastToInt(0.0 / 0.0); // COMPLIANT - addOneThenCastToInt(1.0 / 0.0); // NON_COMPLIANT[False negative] - addOneThenCastToInt(0.0 / 0.0); // NON_COMPLIANT + checkBeforeCastToInt(1.0 / 0.0); // COMPLIANT + checkBeforeCastToInt(0.0 / 0.0); // COMPLIANT + addOneThenCastToInt(1.0 / 0.0); // NON_COMPLIANT[False negative] + addOneThenCastToInt(0.0 / 0.0); // NON_COMPLIANT castToIntToFloatToInt(1.0 / 0.0); // NON_COMPLIANT castToIntToFloatToInt(0.0 / 0.0); // NON_COMPLIANT From c0e2020d70840f1f558ec567ef056cedb7687f7d Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 7 Feb 2025 04:34:58 -0800 Subject: [PATCH 182/370] Format range analysis qll --- .../src/codingstandards/cpp/RestrictedRangeAnalysis.qll | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll index 0c98824dbf..b81f113281 100644 --- a/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll +++ b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll @@ -932,9 +932,8 @@ module RestrictedRangeAnalysis { } predicate canBoundExpr(Expr e) { - exists(RangeSsaDefinition def, StackVariable v | e = def.getAUse(v) | - analyzableDef(def, v) - ) or + exists(RangeSsaDefinition def, StackVariable v | e = def.getAUse(v) | analyzableDef(def, v)) + or analyzableExpr(e) or exists(getGuardedUpperBound(e)) From 09891b09d71ff26c6ac2a7e65bdc3442c6ec1f6a Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 7 Feb 2025 04:37:25 -0800 Subject: [PATCH 183/370] Remove changes to SimpleRangeAnalysisCustomizations.qll --- .../cpp/SimpleRangeAnalysisCustomizations.qll | 39 ------------------- 1 file changed, 39 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/SimpleRangeAnalysisCustomizations.qll b/cpp/common/src/codingstandards/cpp/SimpleRangeAnalysisCustomizations.qll index 2688452d28..5144f63dc2 100644 --- a/cpp/common/src/codingstandards/cpp/SimpleRangeAnalysisCustomizations.qll +++ b/cpp/common/src/codingstandards/cpp/SimpleRangeAnalysisCustomizations.qll @@ -14,45 +14,6 @@ import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils import experimental.semmle.code.cpp.rangeanalysis.extensions.ConstantBitwiseAndExprRange private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr -// Disabled, causing performance issues in grpc: -/* -private class DivByConstantExpr extends SimpleRangeAnalysisExpr, DivExpr { - float quotient; - - DivByConstantExpr() { - quotient = evaluateConstantExpr(getRightOperand()) - } - - override predicate dependsOnChild(Expr e) { - e = getLeftOperand() - } - - override float getLowerBounds() { - exists(float numerator | - result = numerator / quotient and - if (quotient > 0) then - // x / y where and y is positive scales the UB/LB. - numerator = getFullyConvertedLowerBounds(getLeftOperand()) - else - // x / -y where and -y is negative will invert and scale the UB/LB. - numerator = getFullyConvertedUpperBounds(getLeftOperand()) - ) - } - - override float getUpperBounds() { - exists(float numerator | - result = numerator / quotient and - if (quotient > 0) then - // x / y where and y is positive scales the UB/LB. - numerator = getFullyConvertedUpperBounds(getLeftOperand()) - else - // x / -y where and -y is negative will invert and scale the UB/LB. - numerator = getFullyConvertedLowerBounds(getLeftOperand()) - ) - } -} - */ - /** * A range analysis extension that support bitwise `|` and `|=` where at least one operand is a * non-negative constant. From 2a0d6cb36c45deef89434d05eb942aabb21e62a4 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 7 Feb 2025 04:41:16 -0800 Subject: [PATCH 184/370] Set more accurate query metadata --- .../rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql | 4 ++-- .../src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql | 4 ++-- rule_packages/c/FloatingTypes2.json | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql index 61753c98a9..3d54b4f829 100644 --- a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql @@ -4,8 +4,8 @@ * @description Evaluation of floating-point expressions shall not lead to the undetected generation * of infinities. * @kind path-problem - * @precision high - * @problem.severity error + * @precision medium + * @problem.severity warning * @tags external/misra/id/dir-4-15 * correctness * external/misra/c/2012/amendment3 diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql index 701834ca3f..2835a454d9 100644 --- a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql @@ -4,8 +4,8 @@ * @description Evaluation of floating-point expressions shall not lead to the undetected generation * of NaNs. * @kind path-problem - * @precision high - * @problem.severity error + * @precision low + * @problem.severity warning * @tags external/misra/id/dir-4-15 * correctness * external/misra/c/2012/amendment3 diff --git a/rule_packages/c/FloatingTypes2.json b/rule_packages/c/FloatingTypes2.json index 152ead08d3..3f4771dcc6 100644 --- a/rule_packages/c/FloatingTypes2.json +++ b/rule_packages/c/FloatingTypes2.json @@ -9,8 +9,8 @@ "description": "Evaluation of floating-point expressions shall not lead to the undetected generation of infinities.", "kind": "path-problem", "name": "Evaluation of floating-point expressions shall not lead to the undetected generation of infinities", - "precision": "high", - "severity": "error", + "precision": "medium", + "severity": "warning", "short_name": "PossibleMisuseOfUndetectedInfinity", "tags": [ "correctness", @@ -21,8 +21,8 @@ "description": "Evaluation of floating-point expressions shall not lead to the undetected generation of NaNs.", "kind": "path-problem", "name": "Evaluation of floating-point expressions shall not lead to the undetected generation of NaNs", - "precision": "high", - "severity": "error", + "precision": "low", + "severity": "warning", "short_name": "PossibleMisuseOfUndetectedNaN", "tags": [ "correctness", From 4920e9ce6c8e18f1559715f46a9a812b8a91bea9 Mon Sep 17 00:00:00 2001 From: Luke Cartey <5377966+lcartey@users.noreply.github.com> Date: Sat, 8 Feb 2025 23:02:59 +0000 Subject: [PATCH 185/370] Update change_notes/2025-02-06-a3-1-5-audit.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- change_notes/2025-02-06-a3-1-5-audit.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change_notes/2025-02-06-a3-1-5-audit.md b/change_notes/2025-02-06-a3-1-5-audit.md index 3aa0e6671b..1f56a25236 100644 --- a/change_notes/2025-02-06-a3-1-5-audit.md +++ b/change_notes/2025-02-06-a3-1-5-audit.md @@ -1,2 +1,2 @@ - - `A3-1-5` - `NonTrivalNonTemplateFunctionDefinedInsideClassDefinition.ql`: + - `A3-1-5` - `NonTrivialNonTemplateFunctionDefinedInsideClassDefinition.ql`: - Mark this as an `audit` query. As a consequence, it will no longer be run as part of the default query suite for AUTOSAR. It can still be run as part of the `autosar-audit.qls` query suite. The query has been downgraded because the rule allows for functions to be declared in the class body if they were "intended" to be inlined, and that developer intention cannot be determined automatically from the code. \ No newline at end of file From 939ab7930b082d15900bfb823493be8923ceb6f5 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sat, 8 Feb 2025 23:07:59 +0000 Subject: [PATCH 186/370] A3-1-5: Move precision to low --- ...NonTrivialNonTemplateFunctionDefinedInsideClassDefinition.ql | 2 +- cpp/autosar/test/rules/A3-1-5/test.cpp | 2 +- rule_packages/cpp/Classes.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/autosar/src/rules/A3-1-5/NonTrivialNonTemplateFunctionDefinedInsideClassDefinition.ql b/cpp/autosar/src/rules/A3-1-5/NonTrivialNonTemplateFunctionDefinedInsideClassDefinition.ql index 2edf73b6ee..9b250e487a 100644 --- a/cpp/autosar/src/rules/A3-1-5/NonTrivialNonTemplateFunctionDefinedInsideClassDefinition.ql +++ b/cpp/autosar/src/rules/A3-1-5/NonTrivialNonTemplateFunctionDefinedInsideClassDefinition.ql @@ -4,7 +4,7 @@ * @description A function that is not either trivial, a template function, or a member of a * template class may not be defined within a class body. * @kind problem - * @precision very-high + * @precision low * @problem.severity recommendation * @tags external/autosar/id/a3-1-5 * external/autosar/audit diff --git a/cpp/autosar/test/rules/A3-1-5/test.cpp b/cpp/autosar/test/rules/A3-1-5/test.cpp index 1b2898bf63..e6db0d1190 100644 --- a/cpp/autosar/test/rules/A3-1-5/test.cpp +++ b/cpp/autosar/test/rules/A3-1-5/test.cpp @@ -188,4 +188,4 @@ int FooBar::f1(int a, int b) { // COMPLIANT not a trivial function ; ; } -} +} \ No newline at end of file diff --git a/rule_packages/cpp/Classes.json b/rule_packages/cpp/Classes.json index d76a9b3bc5..59eb9a0418 100644 --- a/rule_packages/cpp/Classes.json +++ b/rule_packages/cpp/Classes.json @@ -182,7 +182,7 @@ "description": "A function that is not either trivial, a template function, or a member of a template class may not be defined within a class body.", "kind": "problem", "name": "A function shall be defined with a class body if and only if it is intended to be inlined", - "precision": "very-high", + "precision": "low", "severity": "recommendation", "short_name": "NonTrivialNonTemplateFunctionDefinedInsideClassDefinition", "tags": [ From 80edc11f6fd64b48849d07a2674e342ffea12f63 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 9 Feb 2025 00:15:22 -0800 Subject: [PATCH 187/370] Address feedback on emergent language features --- amendments.csv | 2 +- ...024-12-12-lessen-emergent-language-feature-restrictions.md | 2 ++ cpp/common/src/codingstandards/cpp/Emergent.qll | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 change_notes/2024-12-12-lessen-emergent-language-feature-restrictions.md diff --git a/amendments.csv b/amendments.csv index 0f588b0e05..f153e68216 100644 --- a/amendments.csv +++ b/amendments.csv @@ -2,7 +2,7 @@ language,standard,amendment,rule_id,supportable,implementation_category,implemen c,MISRA-C-2012,Amendment3,DIR-4-6,Yes,Expand,Yes,Easy c,MISRA-C-2012,Amendment3,DIR-4-9,Yes,Refine,No,Easy c,MISRA-C-2012,Amendment3,DIR-4-11,Yes,Refine,No,Import -c,MISRA-C-2012,Amendment3,RULE-1-4,Yes,Replace,Yes,Easy +c,MISRA-C-2012,Amendment3,RULE-1-4,Yes,Replace,No,Easy c,MISRA-C-2012,Amendment3,RULE-10-1,Yes,Replace,Yes,Easy c,MISRA-C-2012,Amendment3,RULE-10-3,Yes,Refine,Yes,Easy c,MISRA-C-2012,Amendment3,RULE-10-4,Yes,Refine,Yes,Import diff --git a/change_notes/2024-12-12-lessen-emergent-language-feature-restrictions.md b/change_notes/2024-12-12-lessen-emergent-language-feature-restrictions.md new file mode 100644 index 0000000000..2893ba620b --- /dev/null +++ b/change_notes/2024-12-12-lessen-emergent-language-feature-restrictions.md @@ -0,0 +1,2 @@ + - `RULE-1-4` - `EmergentLanguageFeaturesUsed.ql`: + - Remove restrictions on `stdnoreturn.h`, `stdalign.h`. \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/Emergent.qll b/cpp/common/src/codingstandards/cpp/Emergent.qll index 30f1df58e4..f976da5f62 100644 --- a/cpp/common/src/codingstandards/cpp/Emergent.qll +++ b/cpp/common/src/codingstandards/cpp/Emergent.qll @@ -12,4 +12,8 @@ module C11 { getBody() = "1" } } + + class GenericMacro extends EmergentLanguageFeature, Macro { + GenericMacro() { getBody().indexOf("_Generic") = 0 } + } } From 57b4292b71fb46b76f239363ecc9eb9f35e54f96 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 9 Feb 2025 00:30:17 -0800 Subject: [PATCH 188/370] Revert deletion of stdatomic, threads, as emergent lanugage features --- amendments.csv | 2 +- .../src/codingstandards/cpp/Emergent.qll | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/amendments.csv b/amendments.csv index b64bb98f21..6049525515 100644 --- a/amendments.csv +++ b/amendments.csv @@ -24,7 +24,7 @@ c,MISRA-C-2012,Amendment4,RULE-8-9,Yes,Clarification,Yes,Import c,MISRA-C-2012,Amendment4,RULE-9-4,Yes,Clarification,Yes,Import c,MISRA-C-2012,Amendment4,RULE-10-1,Yes,Clarification,Yes,Import c,MISRA-C-2012,Amendment4,RULE-18-3,Yes,Clarification,Yes,Import -c,MISRA-C-2012,Amendment4,RULE-1-4,Yes,Replace,Yes,Easy +c,MISRA-C-2012,Amendment4,RULE-1-4,Yes,Replace,No,Easy c,MISRA-C-2012,Amendment4,RULE-9-1,Yes,Refine,No,Easy c,MISRA-C-2012,Amendment4,RULE-9-2,Yes,Refine,No,Import c,MISRA-C-2012,Corrigendum2,DIR-4-10,Yes,Clarification,Yes,Import diff --git a/cpp/common/src/codingstandards/cpp/Emergent.qll b/cpp/common/src/codingstandards/cpp/Emergent.qll index f976da5f62..506d024bc9 100644 --- a/cpp/common/src/codingstandards/cpp/Emergent.qll +++ b/cpp/common/src/codingstandards/cpp/Emergent.qll @@ -6,6 +6,24 @@ import cpp module C11 { abstract class EmergentLanguageFeature extends Element { } + class AtomicVariableSpecifier extends EmergentLanguageFeature, Variable { + AtomicVariableSpecifier() { + getType().(DerivedType).getBaseType*().getASpecifier().getName() = "atomic" + } + } + + class AtomicDeclaration extends EmergentLanguageFeature, Declaration { + AtomicDeclaration() { getASpecifier().getName() = "atomic" } + } + + class ThreadLocalDeclaration extends EmergentLanguageFeature, Declaration { + ThreadLocalDeclaration() { getASpecifier().getName() = "is_thread_local" } + } + + class EmergentHeader extends EmergentLanguageFeature, Include { + EmergentHeader() { getIncludedFile().getBaseName() = ["stdatomic.h", "threads.h"] } + } + class LibExt1Macro extends EmergentLanguageFeature, Macro { LibExt1Macro() { getName() = "__STDC_WANT_LIB_EXT1__" and From f473520127921c17de346387f921879ef39eb498 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 9 Feb 2025 00:36:56 -0800 Subject: [PATCH 189/370] Fix tests for rule-1-4 --- .../RULE-1-4/EmergentLanguageFeaturesUsed.expected | 7 +++++++ c/misra/test/rules/RULE-1-4/test.c | 14 +++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected b/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected index 3f63a6c26c..04c0e1bbd6 100644 --- a/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected +++ b/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected @@ -1 +1,8 @@ +| test.c:2:1:2:22 | #include | Usage of emergent language feature. | +| test.c:4:1:4:20 | #include | Usage of emergent language feature. | +| test.c:6:1:6:49 | #define MACRO(x) _Generic((x), int : 0, long : 1) | Usage of emergent language feature. | | test.c:7:1:7:32 | #define __STDC_WANT_LIB_EXT1__ 1 | Usage of emergent language feature. | +| test.c:12:26:12:40 | atomic_new_type | Usage of emergent language feature. | +| test.c:17:15:17:15 | i | Usage of emergent language feature. | +| test.c:24:27:24:28 | i3 | Usage of emergent language feature. | +| test.c:25:28:25:29 | i4 | Usage of emergent language feature. | diff --git a/c/misra/test/rules/RULE-1-4/test.c b/c/misra/test/rules/RULE-1-4/test.c index 8c1e44e6bd..106b29ef61 100644 --- a/c/misra/test/rules/RULE-1-4/test.c +++ b/c/misra/test/rules/RULE-1-4/test.c @@ -1,26 +1,26 @@ #include //COMPLIANT -#include //COMPLIANT +#include //NON-COMPLIANT #include //COMPLIANT -#include //COMPLIANT +#include //NON-COMPLIANT -#define MACRO(x) _Generic((x), int : 0, long : 1) // COMPLIANT +#define MACRO(x) _Generic((x), int : 0, long : 1) // NON-COMPLIANT #define __STDC_WANT_LIB_EXT1__ 1 // NON-COMPLIANT _Noreturn void f0(); // COMPLIANT typedef int new_type; // COMPLIANT -typedef _Atomic new_type atomic_new_type; // COMPLIANT +typedef _Atomic new_type atomic_new_type; // NON-COMPLIANT void f(int p) { int i0 = _Generic(p, int : 0, long : 1); // COMPLIANT - _Atomic int i; // COMPLIANT + _Atomic int i; // NON-COMPLIANT _Alignas(4) int i1; // COMPLIANT alignas(4) int i2; // COMPLIANT int a = _Alignof(int); // COMPLIANT int a1 = alignof(int); // COMPLIANT - static thread_local int i3; // COMPLIANT - static _Thread_local int i4; // COMPLIANT + static thread_local int i3; // NON-COMPLIANT + static _Thread_local int i4; // NON-COMPLIANT } \ No newline at end of file From 137329219c0e1c200f94f2bfe19e8c851636d24a Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 9 Feb 2025 00:38:27 -0800 Subject: [PATCH 190/370] s/NON-COMPLIANT/NON_COMPLIANT in rule-1-4 test.c --- c/misra/test/rules/RULE-1-4/test.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/c/misra/test/rules/RULE-1-4/test.c b/c/misra/test/rules/RULE-1-4/test.c index 106b29ef61..81d609f052 100644 --- a/c/misra/test/rules/RULE-1-4/test.c +++ b/c/misra/test/rules/RULE-1-4/test.c @@ -1,15 +1,15 @@ #include //COMPLIANT -#include //NON-COMPLIANT +#include //NON_COMPLIANT #include //COMPLIANT -#include //NON-COMPLIANT +#include //NON_COMPLIANT -#define MACRO(x) _Generic((x), int : 0, long : 1) // NON-COMPLIANT -#define __STDC_WANT_LIB_EXT1__ 1 // NON-COMPLIANT +#define MACRO(x) _Generic((x), int : 0, long : 1) // NON_COMPLIANT +#define __STDC_WANT_LIB_EXT1__ 1 // NON_COMPLIANT _Noreturn void f0(); // COMPLIANT typedef int new_type; // COMPLIANT -typedef _Atomic new_type atomic_new_type; // NON-COMPLIANT +typedef _Atomic new_type atomic_new_type; // NON_COMPLIANT void f(int p) { int i0 = _Generic(p, int : 0, long : 1); // COMPLIANT @@ -21,6 +21,6 @@ void f(int p) { int a = _Alignof(int); // COMPLIANT int a1 = alignof(int); // COMPLIANT - static thread_local int i3; // NON-COMPLIANT - static _Thread_local int i4; // NON-COMPLIANT + static thread_local int i3; // NON_COMPLIANT + static _Thread_local int i4; // NON_COMPLIANT } \ No newline at end of file From 42836526bb9953e0fb539f805988823612bc608d Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 10 Feb 2025 16:22:57 +0000 Subject: [PATCH 191/370] Deviations: Switch to new deviations format --- .../deviations/CodeIdentifierDeviation.qll | 37 ++++++++++++------ .../TypeLongDoubleUsed.expected | 6 +-- .../UnusedReturnValue.expected | 12 +++--- .../attribute_syntax.cpp | 17 ++++---- .../deviations/deviations_basic_test/main.cpp | 12 +++--- docs/user_manual.md | 39 ++++++++++--------- 6 files changed, 71 insertions(+), 52 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll index bd7100021a..731a04cfc7 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll @@ -1,14 +1,24 @@ /** - * A module for identifying comment markers in code that trigger deviations. + * A module for identifying in code markers in code that trigger deviations. * - * Each comment marker consists of a `code-identifier` with some optional annotations. A deviation will be applied to + * This module supports two different code identifier markers: + * - A C/C++ attribute based syntax + * - A comment-based format + * + * The C/C++ attribute based syntax uses the following format: + * ``` + * [[codeql::_deviation("code-identifier")]] + * ``` + * The deviation will be applied to the selected program element, and any syntactically nested children of that program element. + * + * For the comment format the marker consists of a `code-identifier` with some optional annotations. A deviation will be applied to * some range of lines in the file containing the comment based on the annotation. The supported marker annotation * formats are: * - `` - the deviation applies to results on the current line. - * - `[[codingstandards::deviation()]]` - same as above. - * - `[[codingstandards::deviation_next_line()]]` - this deviation applies to results on the next line. - * - `[[codingstandards::deviation_begin()]]` - marks the beginning of a range of lines where the deviation applies. - * - `[[codingstandards::deviation_end()]]` - marks the end of a range of lines where the deviation applies. + * - `codeql::_deviation()` - same as above. + * - `codeql::_deviation_next_line()` - this deviation applies to results on the next line. + * - `codeql::_deviation_begin()` - marks the beginning of a range of lines where the deviation applies. + * - `codeql::_deviation_end()` - marks the end of a range of lines where the deviation applies. * * The valid `code-identifier`s are specified in deviation records, which also specify the query whose results are * suppressed by the deviation. @@ -23,6 +33,8 @@ import cpp import Deviations +string supportedStandard() { result = ["misra", "autosar", "cert"] } + /** * Holds if the given comment contains the code identifier. */ @@ -67,7 +79,8 @@ abstract class CommentDeviationMarker extends Comment { */ class DeviationEndOfLineMarker extends CommentDeviationMarker { DeviationEndOfLineMarker() { - commentMatches(this, "[[codingstandards::deviation(" + record.getCodeIdentifier() + ")]]") + commentMatches(this, + "codeql::" + supportedStandard() + "_deviation(" + record.getCodeIdentifier() + ")") } } @@ -77,7 +90,7 @@ class DeviationEndOfLineMarker extends CommentDeviationMarker { class DeviationNextLineMarker extends CommentDeviationMarker { DeviationNextLineMarker() { commentMatches(this, - "[[codingstandards::deviation_next_line(" + record.getCodeIdentifier() + ")]]") + "codeql::" + supportedStandard() + "_deviation_next_line(" + record.getCodeIdentifier() + ")") } } @@ -91,7 +104,8 @@ abstract class CommentDeviationRangeMarker extends CommentDeviationMarker { } */ class DeviationBegin extends CommentDeviationRangeMarker { DeviationBegin() { - commentMatches(this, "[[codingstandards::deviation_begin(" + record.getCodeIdentifier() + ")]]") + commentMatches(this, + "codeql::" + supportedStandard() + "_deviation_begin(" + record.getCodeIdentifier() + ")") } } @@ -100,7 +114,8 @@ class DeviationBegin extends CommentDeviationRangeMarker { */ class DeviationEnd extends CommentDeviationRangeMarker { DeviationEnd() { - commentMatches(this, "[[codingstandards::deviation_end(" + record.getCodeIdentifier() + ")]]") + commentMatches(this, + "codeql::" + supportedStandard() + "_deviation_end(" + record.getCodeIdentifier() + ")") } } @@ -184,7 +199,7 @@ class DeviationAttribute extends StdAttribute { DeviationRecord record; DeviationAttribute() { - this.hasQualifiedName("codingstandards", "deviation") and + this.hasQualifiedName("codeql", supportedStandard() + "_deviation") and // Support multiple argument deviations "\"" + record.getCodeIdentifier() + "\"" = this.getAnArgument().getValueText() } diff --git a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected index 99b3c89bfb..1786c4ce9e 100644 --- a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected +++ b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected @@ -1,7 +1,7 @@ | attribute_syntax.cpp:6:15:6:17 | dd1 | Use of long double type. | -| attribute_syntax.cpp:22:15:22:17 | d10 | Use of long double type. | -| attribute_syntax.cpp:30:15:30:17 | d14 | Use of long double type. | -| attribute_syntax.cpp:34:20:34:22 | d16 | Use of long double type. | +| attribute_syntax.cpp:21:15:21:17 | d10 | Use of long double type. | +| attribute_syntax.cpp:29:15:29:17 | d14 | Use of long double type. | +| attribute_syntax.cpp:33:20:33:22 | d16 | Use of long double type. | | main.cpp:13:15:13:16 | d1 | Use of long double type. | | main.cpp:18:15:18:16 | d4 | Use of long double type. | | main.cpp:21:15:21:16 | d6 | Use of long double type. | diff --git a/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected b/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected index 7538df2195..8b258328ab 100644 --- a/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected +++ b/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected @@ -1,10 +1,10 @@ | attribute_syntax.cpp:5:3:5:6 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | -| attribute_syntax.cpp:17:5:17:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | -| attribute_syntax.cpp:19:5:19:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | -| attribute_syntax.cpp:25:5:25:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | -| attribute_syntax.cpp:27:5:27:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | -| attribute_syntax.cpp:31:3:31:6 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | -| attribute_syntax.cpp:42:3:42:6 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | +| attribute_syntax.cpp:16:5:16:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | +| attribute_syntax.cpp:18:5:18:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | +| attribute_syntax.cpp:24:5:24:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | +| attribute_syntax.cpp:26:5:26:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | +| attribute_syntax.cpp:30:3:30:6 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | +| attribute_syntax.cpp:41:3:41:6 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | | main.cpp:12:3:12:6 | call to getX | Return value from call to $@ is unused. | main.cpp:8:5:8:8 | getX | getX | | main.cpp:25:3:25:6 | call to getX | Return value from call to $@ is unused. | main.cpp:8:5:8:8 | getX | getX | | main.cpp:27:3:27:6 | call to getX | Return value from call to $@ is unused. | main.cpp:8:5:8:8 | getX | getX | diff --git a/cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp b/cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp index 97b4ba987d..30acac3bfb 100644 --- a/cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp +++ b/cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp @@ -5,14 +5,13 @@ int alt() { getZ(); // NON_COMPLIANT long double dd1; // NON_COMPLIANT (A0-4-2) - long double [[codingstandards::deviation( - "a-0-4-2-deviation")]] dd3; // COMPLIANT[DEVIATED] - long double [[codingstandards::deviation("a")]] dd3a; // NON_COMPLIAT + long double [[codeql::autosar_deviation( + "a-0-4-2-deviation")]] dd3; // COMPLIANT[DEVIATED] - [[codingstandards::deviation( + [[codeql::autosar_deviation( "a-0-4-2-deviation")]] long double dd4; // COMPLIANT[DEVIATED] - [[codingstandards::deviation("a-0-4-2-deviation")]] { + [[codeql::autosar_deviation("a-0-4-2-deviation")]] { long double d7; // COMPLIANT[DEVIATED] getZ(); // NON_COMPLIANT (A0-1-2) long double d8; // COMPLIANT[DEVIATED] @@ -20,7 +19,7 @@ int alt() { long double d9; // COMPLIANT[DEVIATED] } long double d10; // NON_COMPLIANT (A0-4-2) - [[codingstandards::deviation("a-0-4-2-deviation")]] { + [[codeql::autosar_deviation("a-0-4-2-deviation")]] { long double d11; // COMPLIANT[DEVIATED] getZ(); // NON_COMPLIANT (A0-1-2) long double d12; // COMPLIANT[DEVIATED] @@ -29,16 +28,18 @@ int alt() { } long double d14; // NON_COMPLIANT (A0-4-2) getZ(); // NON_COMPLIANT (A0-1-2) - [[codingstandards::deviation("a-0-4-2-deviation")]] + [[codeql::autosar_deviation("a-0-4-2-deviation")]] for (long double d15 = 0.0; true;) {} // COMPLIANT[DEVIATED] for (long double d16 = 0.0; true;) { // NON_COMPLIANT (A0-4-2) } return 0; } -[[codingstandards::deviation("a-0-4-2-deviation")]] +[[codeql::autosar_deviation("a-0-4-2-deviation")]] int alt2() { int x = 0; // COMPLIANT[DEVIATED] getZ(); // NON_COMPLIANT long double dd1; // COMPLIANT[DEVIATED] + [[codeql::autosar_deviation( + "a-0-4-2-deviation")]] long double dd2; // COMPLIANT[DEVIATED] } \ No newline at end of file diff --git a/cpp/common/test/deviations/deviations_basic_test/main.cpp b/cpp/common/test/deviations/deviations_basic_test/main.cpp index e1faaec68c..aa389ed0ad 100644 --- a/cpp/common/test/deviations/deviations_basic_test/main.cpp +++ b/cpp/common/test/deviations/deviations_basic_test/main.cpp @@ -13,28 +13,28 @@ int main(int argc, char **argv) { long double d1; // NON_COMPLIANT (A0-4-2) long double d2; // a-0-4-2-deviation COMPLIANT[DEVIATED] - long double d3; // [[codingstandards::deviation(a-0-4-2-deviation)]] + long double d3; // codeql::autosar_deviation(a-0-4-2-deviation) // COMPLIANT[DEVIATED] long double d4; // NON_COMPLIANT (A0-4-2) - // [[codingstandards::deviation_next_line(a-0-4-2-deviation)]] + // codeql::autosar_deviation_next_line(a-0-4-2-deviation) long double d5; // COMPLIANT[DEVIATED] long double d6; // NON_COMPLIANT (A0-4-2) - // [[codingstandards::deviation_begin(a-0-4-2-deviation)]] + // codeql::autosar_deviation_begin(a-0-4-2-deviation) long double d7; // COMPLIANT[DEVIATED] getX(); // NON_COMPLIANT (A0-1-2) long double d8; // COMPLIANT[DEVIATED] getX(); // NON_COMPLIANT (A0-1-2) long double d9; // COMPLIANT[DEVIATED] - // [[codingstandards::deviation_end(a-0-4-2-deviation)]] + // codeql::autosar_deviation_end(a-0-4-2-deviation) long double d10; // NON_COMPLIANT (A0-4-2) - // [[codingstandards::deviation_begin(a-0-4-2-deviation)]] + // codeql::autosar_deviation_begin(a-0-4-2-deviation) long double d11; // COMPLIANT[DEVIATED] getX(); // NON_COMPLIANT (A0-1-2) long double d12; // COMPLIANT[DEVIATED] getX(); // NON_COMPLIANT (A0-1-2) long double d13; // COMPLIANT[DEVIATED] - // [[codingstandards::deviation_end(a-0-4-2-deviation)]] + // codeql::autosar_deviation_end(a-0-4-2-deviation) long double d14; // NON_COMPLIANT (A0-4-2) getX(); // NON_COMPLIANT (A0-1-2) return 0; diff --git a/docs/user_manual.md b/docs/user_manual.md index 5d2236ed10..34c675c4bc 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -426,10 +426,13 @@ The `process_coding_standards_config.py` has a dependency on the package `pyyaml A code identifier specified in a deviation record can be applied to certain results in the code by adding a C or C++ attribute of the following format: ``` -[[codingstandards::deviation("code-identifier")]] +[[codeql::_deviation("code-identifier")]] ``` +For example `[[codeql::misra_deviation("a1-2-4")]]` would apply a deviation of a rule in a MISRA standard, using the code identifier `a1-2-4`. The supported standard names are `misra`, `autosar` and `cert`. + This attribute may be added to the following program elements: + * Functions * Statements * Variables @@ -440,7 +443,7 @@ Deviation attributes are inherited from parents in the code structure. For examp Multiple code identifiers may be passed in a single attribute to apply multiple deviations, for example: ``` -[[codingstandards::deviation("code-identifier-1", "code-identifier-2")]] +[[codeql::misra_deviation("code-identifier-1", "code-identifier-2")]] ``` Note - considation should be taken to ensure the use of custom attributes for deviations is compatible with your chosen language version, compiler, compiler configuration and coding standard. @@ -461,10 +464,10 @@ If you cannot satisfy these condition, please use the deviation code identifier As an alternative to attributes, a code identifier specified in a deviation record can be applied to certain results in the code by adding a comment marker consisting of a `code-identifier` with some optional annotations. The supported marker annotation formats are: - `` - the deviation applies to results on the current line. - - `codingstandards::deviation()` - the deviation applies to results on the current line. - - `codingstandards::deviation_next_line()` - this deviation applies to results on the next line. - - `codingstandards::deviation_begin()` - marks the beginning of a range of lines where the deviation applies. - - `codingstandards::deviation_end()` - marks the end of a range of lines where the deviation applies. + - `codeql::_deviation()` - the deviation applies to results on the current line. + - `codeql::_deviation_next_line()` - this deviation applies to results on the next line. + - `codeql::_deviation_begin()` - marks the beginning of a range of lines where the deviation applies. + - `codeql::_deviation_end()` - marks the end of a range of lines where the deviation applies. Here are some examples, using the deviation record with the `a-0-4-2-deviation` code-identifier specified above: ```cpp @@ -473,32 +476,32 @@ Here are some examples, using the deviation record with the `a-0-4-2-deviation` long double x2; // a-0-4-2-deviation - COMPLIANT long double x3; // COMPLIANT - a-0-4-2-deviation - long double x4; // [[codingstandards::deviation(a-0-4-2-deviation)]] - COMPLIANT - long double x5; // COMPLIANT - [[codingstandards::deviation(a-0-4-2-deviation)]] + long double x4; // codeql::_deviation(a-0-4-2-deviation) - COMPLIANT + long double x5; // COMPLIANT - codeql::_deviation(a-0-4-2-deviation) - // [[codingstandards::deviation_next_line(a-0-4-2-deviation)]] + // codeql::_deviation_next_line(a-0-4-2-deviation) long double x6; // COMPLIANT - // [[codingstandards::deviation_begin(a-0-4-2-deviation)]] + // codeql::_deviation_begin(a-0-4-2-deviation) long double x7; // COMPLIANT - // [[codingstandards::deviation_end(a-0-4-2-deviation)]] + // codeql::_deviation_end(a-0-4-2-deviation) ``` -`codingstandards::deviation_end` markers will pair with the closest unmatched `codingstandards::deviation_begin` for the same `code-identifier`. Consider this example: +`codeql::_deviation_end` markers will pair with the closest unmatched `codeql::_deviation_begin` for the same `code-identifier`. Consider this example: ```cpp -1 | // [[codingstandards::deviation_begin(a-0-4-2-deviation)]] +1 | // codeql::_deviation_begin(a-0-4-2-deviation) 2 | -3 | // [[codingstandards::deviation_begin(a-0-4-2-deviation)]] +3 | // codeql::_deviation_begin(a-0-4-2-deviation) 4 | -5 | // [[codingstandards::deviation_end(a-0-4-2-deviation)]] +5 | // codeql::_deviation_end(a-0-4-2-deviation) 6 | -7 | // [[codingstandards::deviation_end(a-0-4-2-deviation)]] +7 | // codeql::_deviation_end(a-0-4-2-deviation) ``` Here, Line 1 will pair with Line 7, and Line 3 will pair with Line 8. -A `codingstandards::deviation_end` without a matching `codingstandards::deviation_begin`, or `codingstandards::deviation_begin` without a matching `codingstandards::deviation_end` is invalid and will be ignored. +A `codeql::_deviation_end` without a matching `codeql::_deviation_begin`, or `codeql::_deviation_begin` without a matching `codeql::_deviation_end` is invalid and will be ignored. -`codingstandards::deviation_begin` and `codingstandards::deviation_end` markers only apply within a single file. Markers cannot be paired across files, and deviations do not apply to included files. +`codeql::_deviation_begin` and `ccodeql::_deviation_end` markers only apply within a single file. Markers cannot be paired across files, and deviations do not apply to included files. Note: deviation markers cannot be applied to the body of a macro. Please apply the deviation to macro expansion, or use the attribute deviation format. From c65f635fc0740f45987f58a02dae5583b6bef2d3 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 10 Feb 2025 18:23:59 +0000 Subject: [PATCH 192/370] Remove deviation suppression query tests --- .../DeviationsSuppression.expected | 7 ------- .../deviations_report_deviated/DeviationsSuppression.qlref | 1 - 2 files changed, 8 deletions(-) delete mode 100644 cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected delete mode 100644 cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.qlref diff --git a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected deleted file mode 100644 index 50ceb35b9d..0000000000 --- a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected +++ /dev/null @@ -1,7 +0,0 @@ -| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:12:1:12:58 | Deviation of cpp/autosar/type-long-double-used for comment // a-0-4-2-deviation COMPLIANT[DEVIATED]. | -| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/unused-return-value] | lgtm[cpp/autosar/unused-return-value] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/unused-return-value for nested/nested2/test2.h. | -| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | coding-standards.xml:1:1:17:19 | Deviation of cpp/autosar/useless-assignment for coding-standards.xml. | -| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | main.cpp:1:1:14:1 | Deviation of cpp/autosar/useless-assignment for main.cpp. | -| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/coding-standards.xml:1:1:13:19 | Deviation of cpp/autosar/useless-assignment for nested/coding-standards.xml. | -| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/useless-assignment for nested/nested2/test2.h. | -| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/test.h:1:1:6:1 | Deviation of cpp/autosar/useless-assignment for nested/test.h. | diff --git a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.qlref b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.qlref deleted file mode 100644 index 6268ee7342..0000000000 --- a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.qlref +++ /dev/null @@ -1 +0,0 @@ -codingstandards/cpp/deviations/DeviationsSuppression.ql \ No newline at end of file From e176bb10607c5321edf5facc6f99056d7164fe40 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 10 Feb 2025 21:19:34 +0000 Subject: [PATCH 193/370] Remove redundant import --- c/cert/src/rules/PRE31-C/SideEffectsInArgumentsToUnsafeMacros.ql | 1 - 1 file changed, 1 deletion(-) diff --git a/c/cert/src/rules/PRE31-C/SideEffectsInArgumentsToUnsafeMacros.ql b/c/cert/src/rules/PRE31-C/SideEffectsInArgumentsToUnsafeMacros.ql index 4ae6619227..7974c4d601 100644 --- a/c/cert/src/rules/PRE31-C/SideEffectsInArgumentsToUnsafeMacros.ql +++ b/c/cert/src/rules/PRE31-C/SideEffectsInArgumentsToUnsafeMacros.ql @@ -15,7 +15,6 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.Macro import codingstandards.cpp.SideEffect -import codingstandards.cpp.StructuralEquivalence import codingstandards.cpp.sideeffect.DefaultEffects import codingstandards.cpp.sideeffect.Customizations import semmle.code.cpp.valuenumbering.HashCons From 92f5d5b8ea4d37141200dc6b563c197e2bb1c5d4 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 10 Feb 2025 22:32:50 +0000 Subject: [PATCH 194/370] A5-1-9: Address param confusion The hash cons value for parameters was incorrectly calculated with parameter uses (e.g accesses to the parameter). The correct approach is to use the variable name and type. This caused performance issues, because the hash cons for a function was made up of all combinations of the accesses to the parameters. For lambdas with many parameters and many accesses, this was problematic. --- .../src/rules/A5-1-9/LambdaEquivalence.qll | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/cpp/autosar/src/rules/A5-1-9/LambdaEquivalence.qll b/cpp/autosar/src/rules/A5-1-9/LambdaEquivalence.qll index 040777e321..c9ea4a0fd8 100644 --- a/cpp/autosar/src/rules/A5-1-9/LambdaEquivalence.qll +++ b/cpp/autosar/src/rules/A5-1-9/LambdaEquivalence.qll @@ -211,7 +211,7 @@ private module HashCons { private newtype HC_Params = HC_NoParams() or - HC_ParamCons(HashConsExpr hc, int i, HC_Params list) { mk_ParamCons(hc, i, list, _) } + HC_ParamCons(Type t, string name, int i, HC_Params list) { mk_ParamCons(t, name, i, list, _) } /** * HashConsExpr is the hash-cons of an expression. The relationship between `Expr` @@ -1275,13 +1275,14 @@ private module HashCons { mk_DeclConsInner(_, _, s.getNumDeclarations() - 1, hc, s) } - private predicate mk_ParamCons(HashConsExpr hc, int i, HC_Params list, Function f) { - hc = hashConsExpr(f.getParameter(i).getAnAccess()) and - ( - exists(HashConsExpr head, HC_Params tail | - mk_ParamConsInner(head, tail, i - 1, list, f) and - i > 0 - ) + private predicate mk_ParamCons(Type t, string name, int i, HC_Params list, Function f) { + exists(Parameter p | + p = f.getParameter(i) and + t = p.getType() and + name = p.getName() + | + mk_ParamConsInner(_, _, _, i - 1, list, f) and + i > 0 or i = 0 and list = HC_NoParams() @@ -1289,10 +1290,10 @@ private module HashCons { } private predicate mk_ParamConsInner( - HashConsExpr head, HC_Params tail, int i, HC_Params list, Function f + Type t, string name, HC_Params tail, int i, HC_Params list, Function f ) { - list = HC_ParamCons(head, i, tail) and - mk_ParamCons(head, i, tail, f) + list = HC_ParamCons(t, name, i, tail) and + mk_ParamCons(t, name, i, tail, f) } private predicate mk_FunctionCons( @@ -1302,7 +1303,7 @@ private module HashCons { name = f.getName() and body = hashConsStmt(f.getBlock()) and if f.getNumberOfParameters() > 0 - then mk_ParamConsInner(_, _, f.getNumberOfParameters() - 1, params, f) + then mk_ParamConsInner(_, _, _, f.getNumberOfParameters() - 1, params, f) else params = HC_NoParams() } From a568b887fda9945a2f40984a2034a23e9438f829 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 10 Feb 2025 23:09:05 +0000 Subject: [PATCH 195/370] A5-1-9: Filter blocks to lambdas in hash cons calc Move the exclusion of non-lambda blocks to the calculation of HC_BlockStmt, to avoid generating newtype instances for non-lambda instances. --- .../src/rules/A5-1-9/LambdaEquivalence.qll | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/cpp/autosar/src/rules/A5-1-9/LambdaEquivalence.qll b/cpp/autosar/src/rules/A5-1-9/LambdaEquivalence.qll index c9ea4a0fd8..cab93608c5 100644 --- a/cpp/autosar/src/rules/A5-1-9/LambdaEquivalence.qll +++ b/cpp/autosar/src/rules/A5-1-9/LambdaEquivalence.qll @@ -624,11 +624,21 @@ private module HashCons { strictcount(access.getTarget()) = 1 } + /** + * Gets the name of a variable. + * + * Extracted for performance reasons, to avoid magic, which was causing performance issues in getParameter(int i). + */ + pragma[nomagic] + private string getVariableName(Variable v) { result = v.getName() } + /* Note: This changed from the original HashCons module to be able to find structural equivalent expression. */ private predicate mk_Variable(Type t, string name, VariableAccess access) { analyzableVariable(access) and exists(Variable v | - v = access.getTarget() and t = v.getUnspecifiedType() and name = v.getName() + v = access.getTarget() and + t = v.getUnspecifiedType() and + name = getVariableName(v) ) } @@ -1104,7 +1114,14 @@ private module HashCons { nee.getExpr().getFullyConverted() = child.getAnExpr() } - private predicate mk_StmtCons(HashConsStmt hc, int i, HC_Stmts list, BlockStmt block) { + private class LambdaBlockStmt extends BlockStmt { + LambdaBlockStmt() { + // Restricting to statements inside a lambda expressions. + this.getParentScope*() = any(LambdaExpression le).getLambdaFunction() + } + } + + private predicate mk_StmtCons(HashConsStmt hc, int i, HC_Stmts list, LambdaBlockStmt block) { hc = hashConsStmt(block.getStmt(i)) and ( exists(HashConsStmt head, HC_Stmts tail | @@ -1118,13 +1135,13 @@ private module HashCons { } private predicate mk_StmtConsInner( - HashConsStmt head, HC_Stmts tail, int i, HC_Stmts list, BlockStmt block + HashConsStmt head, HC_Stmts tail, int i, HC_Stmts list, LambdaBlockStmt block ) { list = HC_StmtCons(head, i, tail) and mk_StmtCons(head, i, tail, block) } - private predicate mk_BlockStmtCons(HC_Stmts hc, BlockStmt s) { + private predicate mk_BlockStmtCons(HC_Stmts hc, LambdaBlockStmt s) { if s.getNumStmt() > 0 then exists(HashConsStmt head, HC_Stmts tail | @@ -1487,8 +1504,6 @@ private module HashCons { cached HashConsStmt hashConsStmt(Stmt s) { - // Restricting to statements inside a lambda expressions. - s.getParentScope*() = any(LambdaExpression le).getLambdaFunction() and exists(HC_Stmts list | mk_BlockStmtCons(list, s) and result = HC_BlockStmt(list) From c1d45c3411d23501c205bea8c6a521426187b4b9 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 10 Feb 2025 23:49:13 +0000 Subject: [PATCH 196/370] A5-1-9: Exclude duplication through macros --- .../src/rules/A5-1-9/IdenticalLambdaExpressions.ql | 10 +++++++++- cpp/autosar/test/rules/A5-1-9/test.cpp | 8 +++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/cpp/autosar/src/rules/A5-1-9/IdenticalLambdaExpressions.ql b/cpp/autosar/src/rules/A5-1-9/IdenticalLambdaExpressions.ql index 8717fd000e..1520955716 100644 --- a/cpp/autosar/src/rules/A5-1-9/IdenticalLambdaExpressions.ql +++ b/cpp/autosar/src/rules/A5-1-9/IdenticalLambdaExpressions.ql @@ -24,6 +24,14 @@ where not lambdaExpression = otherLambdaExpression and not lambdaExpression.isFromTemplateInstantiation(_) and not otherLambdaExpression.isFromTemplateInstantiation(_) and - getLambdaHashCons(lambdaExpression) = getLambdaHashCons(otherLambdaExpression) + getLambdaHashCons(lambdaExpression) = getLambdaHashCons(otherLambdaExpression) and + // Do not report lambdas produced by the same macro in different invocations + not exists(Macro m, MacroInvocation m1, MacroInvocation m2 | + m1 = m.getAnInvocation() and + m2 = m.getAnInvocation() and + not m1 = m2 and // Lambdas in the same macro can be reported + m1.getAnExpandedElement() = lambdaExpression and + m2.getAnExpandedElement() = otherLambdaExpression + ) select lambdaExpression, "Lambda expression is identical to $@ lambda expression.", otherLambdaExpression, "this" diff --git a/cpp/autosar/test/rules/A5-1-9/test.cpp b/cpp/autosar/test/rules/A5-1-9/test.cpp index 466cf14dfa..511be302a0 100644 --- a/cpp/autosar/test/rules/A5-1-9/test.cpp +++ b/cpp/autosar/test/rules/A5-1-9/test.cpp @@ -104,4 +104,10 @@ class Test_issue468 { LogError("Error"); LogFatal("Fatal"); } -}; \ No newline at end of file +}; + +#define MACRO() [](int i) -> int { return i + 3; } +void test_macros() { + MACRO(); // COMPLIANT + MACRO(); // COMPLIANT - no duplication +} \ No newline at end of file From 2d8beac88da84e404bddf654f53867934088b305 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 10 Feb 2025 23:52:18 +0000 Subject: [PATCH 197/370] Add change note --- change_notes/2025-02-10-improve-perf-a5-1-9.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 change_notes/2025-02-10-improve-perf-a5-1-9.md diff --git a/change_notes/2025-02-10-improve-perf-a5-1-9.md b/change_notes/2025-02-10-improve-perf-a5-1-9.md new file mode 100644 index 0000000000..ae7ea6f240 --- /dev/null +++ b/change_notes/2025-02-10-improve-perf-a5-1-9.md @@ -0,0 +1,2 @@ + - `A5-1-9` - `IdenticalLambdaExpressions.ql`: + - Performance has been improved. \ No newline at end of file From 1bd7dab926f5c94f13c3685e240af3e41385d01c Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 10 Feb 2025 23:53:26 +0000 Subject: [PATCH 198/370] Include fp update in change note --- change_notes/2025-02-10-improve-perf-a5-1-9.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/change_notes/2025-02-10-improve-perf-a5-1-9.md b/change_notes/2025-02-10-improve-perf-a5-1-9.md index ae7ea6f240..5d355bab49 100644 --- a/change_notes/2025-02-10-improve-perf-a5-1-9.md +++ b/change_notes/2025-02-10-improve-perf-a5-1-9.md @@ -1,2 +1,3 @@ - `A5-1-9` - `IdenticalLambdaExpressions.ql`: - - Performance has been improved. \ No newline at end of file + - Performance has been improved. + - False positives due to repeated invocation of macros containing lambdas have been excluded. \ No newline at end of file From 1ee79ac71f1858b054c65dd037c8cf9732ff1305 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 11 Feb 2025 23:45:03 +0000 Subject: [PATCH 199/370] A2-3-1: Address performance issue Address issue introduced in upgrade to 2.19.4. --- .../cpp/HardwareOrProtocolInterface.qll | 14 ++++++----- .../rules/A2-3-1/InvalidCharacterInComment.ql | 24 ++++++++++--------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/cpp/autosar/src/codingstandards/cpp/HardwareOrProtocolInterface.qll b/cpp/autosar/src/codingstandards/cpp/HardwareOrProtocolInterface.qll index d92a28e477..410fa1292f 100644 --- a/cpp/autosar/src/codingstandards/cpp/HardwareOrProtocolInterface.qll +++ b/cpp/autosar/src/codingstandards/cpp/HardwareOrProtocolInterface.qll @@ -3,14 +3,16 @@ import codingstandards.cpp.CommonTypes as CommonTypes abstract class HardwareOrProtocolInterfaceClass extends Class { } +class HardwareOrProtocolInterfaceComment extends Comment { + HardwareOrProtocolInterfaceComment() { + getContents().regexpMatch("(?m)^\\s*(//|\\*)\\s*@HardwareOrProtocolInterface\\s*$") + } +} + class AnnotatedHardwareOrProtocolInterfaceClass extends HardwareOrProtocolInterfaceClass { AnnotatedHardwareOrProtocolInterfaceClass() { - exists(Comment c, string contents | - c.getCommentedElement() = this.getADeclarationEntry() and - contents = - c.getContents() - .splitAt("\n") - .regexpFind("^\\s*(//|\\*)\\s*@HardwareOrProtocolInterface\\s*$", _, _) + exists(HardwareOrProtocolInterfaceComment c | + c.getCommentedElement() = this.getADeclarationEntry() ) } } diff --git a/cpp/autosar/src/rules/A2-3-1/InvalidCharacterInComment.ql b/cpp/autosar/src/rules/A2-3-1/InvalidCharacterInComment.ql index a3090003d3..fdcc74b115 100644 --- a/cpp/autosar/src/rules/A2-3-1/InvalidCharacterInComment.ql +++ b/cpp/autosar/src/rules/A2-3-1/InvalidCharacterInComment.ql @@ -18,21 +18,23 @@ import cpp import codingstandards.cpp.autosar -bindingset[s] -string getCharOutsideBasicSourceCharSet(string s) { - result = s.regexpFind("[\\u0000-\\u007f]", _, _) and - not result.regexpMatch("[\\p{Alnum}\\p{Space}_{}\\[\\]#()<>%:;.?*+-/^&|~!=,\\\\\"'@]") - or - result = s.regexpFind("[\\u00c0-\\u00df][\\u0080-\\u00bf]", _, _) - or - result = s.regexpFind("[\\u00e0-\\u00ef][\\u0080-\\u00bf]{2}", _, _) - or - result = s.regexpFind("[\\u00f0-\\u00f7][\\u0080-\\u00bf]{3}", _, _) +string getCharOutsideBasicSourceCharSet(Comment c) { + exists(string s | s = c.getContents() | + result = + s.regexpFind("(?![\\p{Alnum}\\p{Space}_{}\\[\\]#()<>%:;.?*+-/^&|~!=,\\\\\"'@])[\\u0000-\\u007f]", + _, _) + or + result = s.regexpFind("[\\u00c0-\\u00df][\\u0080-\\u00bf]", _, _) + or + result = s.regexpFind("[\\u00e0-\\u00ef][\\u0080-\\u00bf]{2}", _, _) + or + result = s.regexpFind("[\\u00f0-\\u00f7][\\u0080-\\u00bf]{3}", _, _) + ) } from Comment c, string ch where not isExcluded(c, NamingPackage::invalidCharacterInCommentQuery()) and - ch = getCharOutsideBasicSourceCharSet(c.getContents()) + ch = getCharOutsideBasicSourceCharSet(c) select c, "Comment uses the character '" + ch + "' that is outside the language basic character set." From cb4be0ff7e5b170556c4e0127828421861b9b1f4 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 11 Feb 2025 23:49:27 +0000 Subject: [PATCH 200/370] IsStrictlyWeak: Address performance issue --- .../OrderingPredicateMustBeStrictlyWeak.qll | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/rules/orderingpredicatemustbestrictlyweak/OrderingPredicateMustBeStrictlyWeak.qll b/cpp/common/src/codingstandards/cpp/rules/orderingpredicatemustbestrictlyweak/OrderingPredicateMustBeStrictlyWeak.qll index aa4b646ec6..66563bb9ff 100644 --- a/cpp/common/src/codingstandards/cpp/rules/orderingpredicatemustbestrictlyweak/OrderingPredicateMustBeStrictlyWeak.qll +++ b/cpp/common/src/codingstandards/cpp/rules/orderingpredicatemustbestrictlyweak/OrderingPredicateMustBeStrictlyWeak.qll @@ -14,19 +14,19 @@ abstract class OrderingPredicateMustBeStrictlyWeakSharedQuery extends Query { } Query getQuery() { result instanceof OrderingPredicateMustBeStrictlyWeakSharedQuery } +class IsStrictlyWeaklyOrderedComment extends Comment { + IsStrictlyWeaklyOrderedComment() { + getContents().regexpMatch("(?m)^\\s*(//|\\*)\\s*@IsStrictlyWeaklyOrdered\\s*$") + } +} + /** * User annotated class indicating a comparator is axiomatically strictly weakly * ordering. */ class UserDefinedStrictlyWeakOrderingComparator extends Class { UserDefinedStrictlyWeakOrderingComparator() { - exists(Comment c, string contents | - c.getCommentedElement() = this.getADeclarationEntry() and - contents = - c.getContents() - .splitAt("\n") - .regexpFind("^\\s*(//|\\*)\\s*@IsStrictlyWeaklyOrdered\\s*$", _, _) - ) + exists(IsStrictlyWeaklyOrderedComment c | c.getCommentedElement() = this.getADeclarationEntry()) } } From f56fa0f05bac0c78f1816a6cee4948eeea5b2bb5 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Wed, 12 Feb 2025 23:48:55 +0000 Subject: [PATCH 201/370] Detect invalid deviation markers --- .../deviations/CodeIdentifierDeviation.qll | 29 +++++++++++++-- .../InvalidDeviationCodeIdentifier.md | 19 ++++++++++ .../InvalidDeviationCodeIdentifier.ql | 35 +++++++++++++++++++ .../InvalidDeviationCodeIdentifier.expected | 10 ++++++ .../InvalidDeviationCodeIdentifier.qlref | 1 + .../invalid_deviations/coding-standards.xml | 5 +++ .../invalid_deviations/coding-standards.yml | 3 ++ .../deviations/invalid_deviations/dummy.cpp | 1 - .../invalidcodeidentifiers.cpp | 22 ++++++++++++ 9 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.md create mode 100644 cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.ql create mode 100644 cpp/common/test/deviations/invalid_deviations/InvalidDeviationCodeIdentifier.expected create mode 100644 cpp/common/test/deviations/invalid_deviations/InvalidDeviationCodeIdentifier.qlref delete mode 100644 cpp/common/test/deviations/invalid_deviations/dummy.cpp create mode 100644 cpp/common/test/deviations/invalid_deviations/invalidcodeidentifiers.cpp diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll index 731a04cfc7..8c55cc9428 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll @@ -74,6 +74,16 @@ abstract class CommentDeviationMarker extends Comment { DeviationRecord getRecord() { result = record } } +/** + * A deviation marker in a comment that is not a valid deviation marker. + */ +class InvalidCommentDeviationMarker extends Comment { + InvalidCommentDeviationMarker() { + not this instanceof CommentDeviationMarker and + commentMatches(this, "codeql::" + supportedStandard() + "_deviation") + } +} + /** * A deviation marker for a deviation that applies to the current line. */ @@ -182,9 +192,7 @@ private class BeginStack extends TBeginStack { } } -private predicate isDeviationRangePaired( - DeviationRecord record, DeviationBegin begin, DeviationEnd end -) { +predicate isDeviationRangePaired(DeviationRecord record, DeviationBegin begin, DeviationEnd end) { exists(File file, int index | record = end.getRecord() and hasDeviationCommentFileOrdering(record, end, file, index) and @@ -226,6 +234,21 @@ class DeviationAttribute extends StdAttribute { } } +/** + * A deviation attribute that is not associated with any deviation record. + */ +class InvalidDeviationAttribute extends StdAttribute { + string unknownCodeIdentifier; + + InvalidDeviationAttribute() { + this.hasQualifiedName("codeql", supportedStandard() + "_deviation") and + "\"" + unknownCodeIdentifier + "\"" = this.getAnArgument().getValueText() and + not exists(DeviationRecord record | record.getCodeIdentifier() = unknownCodeIdentifier) + } + + string getAnUnknownCodeIdentifier() { result = unknownCodeIdentifier } +} + newtype TCodeIndentifierDeviation = TSingleLineDeviation(DeviationRecord record, Comment comment, string filepath, int suppressedLine) { ( diff --git a/cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.md b/cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.md new file mode 100644 index 0000000000..9c128bab2d --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.md @@ -0,0 +1,19 @@ +# Invalid deviation dode identifier + +## Overview + +Invalid deviation markers in code have no effect on the results but may indicate confusion over which results will be suppressed. + +Deviation code markers are used to suppress CodeQL Coding Standards results, following the process specified in the "MISRA Compliance 2020" document. There are a range of different deviation markers, with specific syntactic requirements. If those syntactic requirements are not met, the marker is invalid and will not be applied, which is likely contrary to developer expectations. + +## Recommendation + +Ensure the following requirements are met: + + * All `codeql::_deviation_begin(..)` markers are paired with a matching `codeql::_deviation_end(..)` marker. + * All instances of `codeql::_deviation` in comments are correctly formatted comment markers, and reference a `code-identifier`s that is specified in a deviation record included in the analysis. + * All deviation attributes reference `code-identifier`s that are specified in a deviation record included in the analysis. + +## References + +* [MISRA Compliance 2020 document - Chapter 4.2 (page 12) - Deviations](https://www.misra.org.uk/app/uploads/2021/06/MISRA-Compliance-2020.pdf) \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.ql b/cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.ql new file mode 100644 index 0000000000..03e1ffc2b0 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.ql @@ -0,0 +1,35 @@ +/** + * @id cpp/coding-standards/invalid-deviation-code-identifiers + * @name Invalid deviation code identifiers + * @description Deviation code identifiers must be valid. + * @kind problem + * @problem.severity error + */ + +import cpp +import CodeIdentifierDeviation + +predicate deviationCodeIdentifierError(Element e, string message) { + exists(DeviationEnd end | + e = end and + not isDeviationRangePaired(_, _, end) and + message = "Deviation end block is unmatched." + ) + or + exists(InvalidDeviationAttribute b | + e = b and + message = + "Deviation attribute references unknown code identifier " + b.getAnUnknownCodeIdentifier() + + "." + ) + or + exists(InvalidCommentDeviationMarker m | + e = m and + message = + "Deviation marker does not match an expected format, or references an unknown code identifier." + ) +} + +from Element e, string message +where deviationCodeIdentifierError(e, message) +select e, message diff --git a/cpp/common/test/deviations/invalid_deviations/InvalidDeviationCodeIdentifier.expected b/cpp/common/test/deviations/invalid_deviations/InvalidDeviationCodeIdentifier.expected new file mode 100644 index 0000000000..eb81658007 --- /dev/null +++ b/cpp/common/test/deviations/invalid_deviations/InvalidDeviationCodeIdentifier.expected @@ -0,0 +1,10 @@ +| invalidcodeidentifiers.cpp:1:1:1:45 | // codeql::misra_deviation(x) - invalid, no x | Deviation marker does not match an expected format, or references an unknown code identifier. | +| invalidcodeidentifiers.cpp:2:1:2:47 | // codeql::autosar_deviation(x) - invalid, no x | Deviation marker does not match an expected format, or references an unknown code identifier. | +| invalidcodeidentifiers.cpp:3:1:3:44 | // codeql::cert_deviation(x) - invalid, no x | Deviation marker does not match an expected format, or references an unknown code identifier. | +| invalidcodeidentifiers.cpp:4:1:4:71 | // codeql::misra_deviation_next(a-0-4-2-deviation) - invalid, next_line | Deviation marker does not match an expected format, or references an unknown code identifier. | +| invalidcodeidentifiers.cpp:5:1:5:73 | // codeql::autosar_deviation_next(a-0-4-2-deviation) - invalid, next_line | Deviation marker does not match an expected format, or references an unknown code identifier. | +| invalidcodeidentifiers.cpp:6:1:6:70 | // codeql::cert_deviation_next(a-0-4-2-deviation) - invalid, next_line | Deviation marker does not match an expected format, or references an unknown code identifier. | +| invalidcodeidentifiers.cpp:14:1:14:74 | // codeql::misra_deviation_end(a-0-4-2-deviation) - invalid, unmatched end | Deviation end block is unmatched. | +| invalidcodeidentifiers.cpp:15:1:15:76 | // codeql::autosar_deviation_end(a-0-4-2-deviation) - invalid, unmatched end | Deviation end block is unmatched. | +| invalidcodeidentifiers.cpp:16:1:16:73 | // codeql::cert_deviation_end(a-0-4-2-deviation) - invalid, unmatched end | Deviation end block is unmatched. | +| invalidcodeidentifiers.cpp:18:3:18:25 | misra_deviation | Deviation attribute references unknown code identifier x. | diff --git a/cpp/common/test/deviations/invalid_deviations/InvalidDeviationCodeIdentifier.qlref b/cpp/common/test/deviations/invalid_deviations/InvalidDeviationCodeIdentifier.qlref new file mode 100644 index 0000000000..c70989966f --- /dev/null +++ b/cpp/common/test/deviations/invalid_deviations/InvalidDeviationCodeIdentifier.qlref @@ -0,0 +1 @@ +codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.ql \ No newline at end of file diff --git a/cpp/common/test/deviations/invalid_deviations/coding-standards.xml b/cpp/common/test/deviations/invalid_deviations/coding-standards.xml index 179227a13d..2b5d798b35 100644 --- a/cpp/common/test/deviations/invalid_deviations/coding-standards.xml +++ b/cpp/common/test/deviations/invalid_deviations/coding-standards.xml @@ -86,6 +86,11 @@ RULE-13-6 c/misra/sizeof-operand-with-side-effect + + A0-4-2 + long double is required for interaction with third-party libraries. + a-0-4-2-deviation + diff --git a/cpp/common/test/deviations/invalid_deviations/coding-standards.yml b/cpp/common/test/deviations/invalid_deviations/coding-standards.yml index 7b12c7a8c2..679ef8a31e 100644 --- a/cpp/common/test/deviations/invalid_deviations/coding-standards.yml +++ b/cpp/common/test/deviations/invalid_deviations/coding-standards.yml @@ -46,6 +46,9 @@ deviations: - permit-id: DP2 - rule-id: RULE-13-6 query-id: c/misra/sizeof-operand-with-side-effect + - rule-id: A0-4-2 + justification: long double is required for interaction with third-party libraries. + code-identifier: a-0-4-2-deviation deviation-permits: - permit-id: DP1 justification: foo bar baz diff --git a/cpp/common/test/deviations/invalid_deviations/dummy.cpp b/cpp/common/test/deviations/invalid_deviations/dummy.cpp deleted file mode 100644 index 4a3cb36e40..0000000000 --- a/cpp/common/test/deviations/invalid_deviations/dummy.cpp +++ /dev/null @@ -1 +0,0 @@ -// Deliberately blank \ No newline at end of file diff --git a/cpp/common/test/deviations/invalid_deviations/invalidcodeidentifiers.cpp b/cpp/common/test/deviations/invalid_deviations/invalidcodeidentifiers.cpp new file mode 100644 index 0000000000..714c83d264 --- /dev/null +++ b/cpp/common/test/deviations/invalid_deviations/invalidcodeidentifiers.cpp @@ -0,0 +1,22 @@ +// codeql::misra_deviation(x) - invalid, no x +// codeql::autosar_deviation(x) - invalid, no x +// codeql::cert_deviation(x) - invalid, no x +// codeql::misra_deviation_next(a-0-4-2-deviation) - invalid, next_line +// codeql::autosar_deviation_next(a-0-4-2-deviation) - invalid, next_line +// codeql::cert_deviation_next(a-0-4-2-deviation) - invalid, next_line + +// codeql::misra_deviation_begin(a-0-4-2-deviation) +// codeql::autosar_deviation_begin(a-0-4-2-deviation) +// codeql::cert_deviation_begin(a-0-4-2-deviation) +// codeql::misra_deviation_end(a-0-4-2-deviation) +// codeql::autosar_deviation_end(a-0-4-2-deviation) +// codeql::cert_deviation_end(a-0-4-2-deviation) +// codeql::misra_deviation_end(a-0-4-2-deviation) - invalid, unmatched end +// codeql::autosar_deviation_end(a-0-4-2-deviation) - invalid, unmatched end +// codeql::cert_deviation_end(a-0-4-2-deviation) - invalid, unmatched end + +[[codeql::misra_deviation("x")]] // invalid +void test() {} + +[[codeql::autosar_deviation("a-0-4-2-deviation")]] +void test2() {} From ef3104aa1dc91dadf938ffd0c01944df347dec89 Mon Sep 17 00:00:00 2001 From: Fernando Jose Date: Thu, 13 Feb 2025 18:11:51 +0900 Subject: [PATCH 202/370] Fix #718. Use % in string::matches to accept any sequence of characters after the group comment ending ///@}. --- change_notes/2025-02-13-fix-issue-718.md | 2 ++ .../src/rules/A2-7-3/UndocumentedUserDefinedType.ql | 2 +- cpp/autosar/test/rules/A2-7-3/test.cpp | 10 ++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 change_notes/2025-02-13-fix-issue-718.md diff --git a/change_notes/2025-02-13-fix-issue-718.md b/change_notes/2025-02-13-fix-issue-718.md new file mode 100644 index 0000000000..39e499d583 --- /dev/null +++ b/change_notes/2025-02-13-fix-issue-718.md @@ -0,0 +1,2 @@ +- `A2-7-3` - `UndocumentedUserDefinedType.ql` + - Fixes #718. Include trailing characters after group comment endings with ///@{ ... ///@}. diff --git a/cpp/autosar/src/rules/A2-7-3/UndocumentedUserDefinedType.ql b/cpp/autosar/src/rules/A2-7-3/UndocumentedUserDefinedType.ql index b38cf7d02c..f2dd0dc8bc 100644 --- a/cpp/autosar/src/rules/A2-7-3/UndocumentedUserDefinedType.ql +++ b/cpp/autosar/src/rules/A2-7-3/UndocumentedUserDefinedType.ql @@ -28,7 +28,7 @@ private predicate isInFunctionScope(Declaration d) { private string doxygenCommentGroupStrings(boolean opening) { opening = true and result = ["///@{", "/**@{*/"] or - opening = false and result = ["///@}", "/**@}*/"] + opening = false and result = ["///@}%", "/**@}*/"] } pragma[inline] diff --git a/cpp/autosar/test/rules/A2-7-3/test.cpp b/cpp/autosar/test/rules/A2-7-3/test.cpp index 01f7bad611..c062da4ee9 100644 --- a/cpp/autosar/test/rules/A2-7-3/test.cpp +++ b/cpp/autosar/test/rules/A2-7-3/test.cpp @@ -225,4 +225,14 @@ class ClassG2 { // COMPLIANT class ClassG3 { // COMPLIANT public: friend int foo3() { return 1; } // NON_COMPLIANT +}; + +/// @brief A Doxygen comment. +class ClassH { // COMPLIANT +public: + /// @brief Group with comment at the end. + ///@{ + void m(); // COMPLIANT + void n(); // COMPLIANT + ///@} End of group }; \ No newline at end of file From 5a6d7ca84f2dd1f00be7380d1800c095bc4a7439 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 13 Feb 2025 11:24:29 +0000 Subject: [PATCH 203/370] Deviations: Support attribute inheritence Attributes are inherited from their parent. Includes support for features which are not currently enabled, due to lack of support in CodeQL itself. --- .../deviations/CodeIdentifierDeviation.qll | 15 +++++++ .../TypeLongDoubleUsed.expected | 3 ++ .../UnusedReturnValue.expected | 2 + .../attribute_syntax.cpp | 39 +++++++++++++++++-- docs/user_manual.md | 5 +-- 5 files changed, 57 insertions(+), 7 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll index 8c55cc9428..2a2d0eec15 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll @@ -231,6 +231,21 @@ class DeviationAttribute extends StdAttribute { result.(Stmt).getEnclosingFunction() = this.getASuppressedElement() or result.(LocalVariable) = this.getASuppressedElement().(DeclStmt).getADeclaration() + or + result.(Function).getDeclaringType() = this.getASuppressedElement() + or + result.(Variable).getDeclaringType() = this.getASuppressedElement() + or + exists(LambdaExpression expr | + expr = this.getASuppressedElement() and + result = expr.getLambdaFunction() + ) + or + exists(Function f | + f = this.getASuppressedElement() and + // A suppression on the function should apply to the noexcept expression + result = f.getADeclarationEntry().getNoExceptExpr() + ) } } diff --git a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected index 1786c4ce9e..172b623195 100644 --- a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected +++ b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected @@ -2,6 +2,9 @@ | attribute_syntax.cpp:21:15:21:17 | d10 | Use of long double type. | | attribute_syntax.cpp:29:15:29:17 | d14 | Use of long double type. | | attribute_syntax.cpp:33:20:33:22 | d16 | Use of long double type. | +| attribute_syntax.cpp:55:15:55:16 | d1 | Use of long double type. | +| attribute_syntax.cpp:57:17:57:18 | d2 | Use of long double type. | +| attribute_syntax.cpp:60:17:60:18 | d3 | Use of long double type. | | main.cpp:13:15:13:16 | d1 | Use of long double type. | | main.cpp:18:15:18:16 | d4 | Use of long double type. | | main.cpp:21:15:21:16 | d6 | Use of long double type. | diff --git a/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected b/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected index 8b258328ab..120337ffdc 100644 --- a/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected +++ b/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected @@ -5,6 +5,8 @@ | attribute_syntax.cpp:26:5:26:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | | attribute_syntax.cpp:30:3:30:6 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | | attribute_syntax.cpp:41:3:41:6 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | +| attribute_syntax.cpp:49:5:49:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | +| attribute_syntax.cpp:61:5:61:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | | main.cpp:12:3:12:6 | call to getX | Return value from call to $@ is unused. | main.cpp:8:5:8:8 | getX | getX | | main.cpp:25:3:25:6 | call to getX | Return value from call to $@ is unused. | main.cpp:8:5:8:8 | getX | getX | | main.cpp:27:3:27:6 | call to getX | Return value from call to $@ is unused. | main.cpp:8:5:8:8 | getX | getX | diff --git a/cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp b/cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp index 30acac3bfb..12a21e9673 100644 --- a/cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp +++ b/cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp @@ -36,10 +36,41 @@ int alt() { } [[codeql::autosar_deviation("a-0-4-2-deviation")]] -int alt2() { +int test_function_deviation() { int x = 0; // COMPLIANT[DEVIATED] getZ(); // NON_COMPLIANT long double dd1; // COMPLIANT[DEVIATED] - [[codeql::autosar_deviation( - "a-0-4-2-deviation")]] long double dd2; // COMPLIANT[DEVIATED] -} \ No newline at end of file +} + +[[codeql::autosar_deviation("a-0-4-2-deviation")]] +void test_lambdas() { + auto l = []() { + long double d4; // COMPLIANT[DEVIATED] + getZ(); // NON_COMPLIANT + }; +} + +// Attributes are not supported on a class level at the moment +[[codeql::autosar_deviation("a-0-4-2-deviation")]] class ClassA { + long double d1; // COMPLIANT[DEVIATED - false positive] + class ClassNested { + long double d2; // COMPLIANT[DEVIATED - false positive] + }; + void test() { + long double d3; // COMPLIANT[DEVIATED - false positive] + getZ(); // NON_COMPLIANT + } +}; + +// static_assert, templates, noexcept, multiple declarations + +// Namespaces not currently supported by attributes +// [[codeql::autosar_deviation("a-0-4-2-deviation")]] namespace NS { +// long double d1; // COMPLIANT[DEVIATED] +// class ClassA { +// long double d1; // COMPLIANT[DEVIATED] +// }; +// void test() { +// long double d1; // COMPLIANT[DEVIATED] +// } +// } \ No newline at end of file diff --git a/docs/user_manual.md b/docs/user_manual.md index 9b58764eb8..a9b119f0da 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -446,9 +446,8 @@ This attribute may be added to the following program elements: * Functions * Statements * Variables - * Type declarations -Deviation attributes are inherited from parents in the code structure. For example, a deviation attribute applied to a function will apply the deviation to all code within the function. Note: deviations are not inherited by lambda expressions. +Deviation attributes are inherited from parents in the code structure. For example, a deviation attribute applied to a function will apply the deviation to all code within the function. Multiple code identifiers may be passed in a single attribute to apply multiple deviations, for example: @@ -507,7 +506,7 @@ Here are some examples, using the deviation record with the `a-0-4-2-deviation` 6 | 7 | // codeql::_deviation_end(a-0-4-2-deviation) ``` -Here, Line 1 will pair with Line 7, and Line 3 will pair with Line 8. +Here, Line 1 will pair with Line 7, and Line 3 will pair with Line 5. A `codeql::_deviation_end` without a matching `codeql::_deviation_begin`, or `codeql::_deviation_begin` without a matching `codeql::_deviation_end` is invalid and will be ignored. From e38e416dc60edcd4093146984c777f58fdfa7ffe Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 13 Feb 2025 11:30:50 +0000 Subject: [PATCH 204/370] Reformatting test file --- .../deviations_basic_test/attribute_syntax.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp b/cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp index 12a21e9673..e363de55af 100644 --- a/cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp +++ b/cpp/common/test/deviations/deviations_basic_test/attribute_syntax.cpp @@ -28,22 +28,22 @@ int alt() { } long double d14; // NON_COMPLIANT (A0-4-2) getZ(); // NON_COMPLIANT (A0-1-2) - [[codeql::autosar_deviation("a-0-4-2-deviation")]] - for (long double d15 = 0.0; true;) {} // COMPLIANT[DEVIATED] - for (long double d16 = 0.0; true;) { // NON_COMPLIANT (A0-4-2) + [[codeql::autosar_deviation("a-0-4-2-deviation")]] for (long double d15 = 0.0; + true;) { + } // COMPLIANT[DEVIATED] + for (long double d16 = 0.0; true;) { // NON_COMPLIANT (A0-4-2) } return 0; } -[[codeql::autosar_deviation("a-0-4-2-deviation")]] -int test_function_deviation() { +[[codeql::autosar_deviation("a-0-4-2-deviation")]] int +test_function_deviation() { int x = 0; // COMPLIANT[DEVIATED] getZ(); // NON_COMPLIANT long double dd1; // COMPLIANT[DEVIATED] } -[[codeql::autosar_deviation("a-0-4-2-deviation")]] -void test_lambdas() { +[[codeql::autosar_deviation("a-0-4-2-deviation")]] void test_lambdas() { auto l = []() { long double d4; // COMPLIANT[DEVIATED] getZ(); // NON_COMPLIANT From 9f35565b83aae672819b16a30b709de7a11de89d Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 13 Feb 2025 11:37:36 +0000 Subject: [PATCH 205/370] Add change note, update manual. --- change_notes/2025-02-13-deviations.md | 13 +++++++++++++ docs/user_manual.md | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 change_notes/2025-02-13-deviations.md diff --git a/change_notes/2025-02-13-deviations.md b/change_notes/2025-02-13-deviations.md new file mode 100644 index 0000000000..fb01cdf596 --- /dev/null +++ b/change_notes/2025-02-13-deviations.md @@ -0,0 +1,13 @@ + - A new in code deviation format has been introduced, using the C/C++ attribute syntax: + ``` + [[codeql::_deviation("")]] + ``` + This can be applied to functions, statements and variables to apply a deviation from the Coding Standards configuration file. The user manual has been updated to describe the new format. + - For those codebases that cannot use standard attributes, we have also introduced a comment based syntax + ``` + // codeql::_deviation() + // codeql::_deviation_next_line() + // codeql::_deviation_begin() + // codeql::_deviation_end() + ``` + Further information is available in the user manual. \ No newline at end of file diff --git a/docs/user_manual.md b/docs/user_manual.md index a9b119f0da..8bbb900682 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -439,7 +439,7 @@ A code identifier specified in a deviation record can be applied to certain resu [[codeql::_deviation("code-identifier")]] ``` -For example `[[codeql::misra_deviation("a1-2-4")]]` would apply a deviation of a rule in a MISRA standard, using the code identifier `a1-2-4`. The supported standard names are `misra`, `autosar` and `cert`. +For example `[[codeql::autosar_deviation("a1-2-4")]]` would apply a deviation of a rule in the AUTOSAR standard, using the code identifier `a1-2-4`. The supported standard names are `misra`, `autosar` and `cert`. This attribute may be added to the following program elements: From d2f8670f4e2ae6d1e625a19dd867b3f2be876765 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 13 Feb 2025 11:40:56 +0000 Subject: [PATCH 206/370] Reformat file --- .../deviations/invalid_deviations/invalidcodeidentifiers.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cpp/common/test/deviations/invalid_deviations/invalidcodeidentifiers.cpp b/cpp/common/test/deviations/invalid_deviations/invalidcodeidentifiers.cpp index 714c83d264..07a12eb713 100644 --- a/cpp/common/test/deviations/invalid_deviations/invalidcodeidentifiers.cpp +++ b/cpp/common/test/deviations/invalid_deviations/invalidcodeidentifiers.cpp @@ -18,5 +18,4 @@ [[codeql::misra_deviation("x")]] // invalid void test() {} -[[codeql::autosar_deviation("a-0-4-2-deviation")]] -void test2() {} +[[codeql::autosar_deviation("a-0-4-2-deviation")]] void test2() {} From 0de32d39b093d59e6f3c857cd39cdb5cd91224bd Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 13 Feb 2025 15:15:35 +0000 Subject: [PATCH 207/370] Update expected results --- .../invalid_deviations/InvalidDeviationPermits.expected | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/common/test/deviations/invalid_deviations/InvalidDeviationPermits.expected b/cpp/common/test/deviations/invalid_deviations/InvalidDeviationPermits.expected index 609d517c05..4378fdf11d 100644 --- a/cpp/common/test/deviations/invalid_deviations/InvalidDeviationPermits.expected +++ b/cpp/common/test/deviations/invalid_deviations/InvalidDeviationPermits.expected @@ -1,2 +1,2 @@ -| coding-standards.xml:100:7:103:33 | deviation-permits-entry | coding-standards.xml: Deviation permit does not specify a permit identifier. | -| coding-standards.xml:104:7:107:33 | deviation-permits-entry | coding-standards.xml: Deviation permit specifies unknown property `invalid-property`. | +| coding-standards.xml:105:7:108:33 | deviation-permits-entry | coding-standards.xml: Deviation permit does not specify a permit identifier. | +| coding-standards.xml:109:7:112:33 | deviation-permits-entry | coding-standards.xml: Deviation permit specifies unknown property `invalid-property`. | From 3b1ee2edb14d8e8a4eb6dc2ea30a2ec29c8a9b8d Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 14 Feb 2025 18:55:46 -0800 Subject: [PATCH 208/370] Fix test expectations --- ...riateThreadObjectStorageDurations.expected | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected b/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected index 085083228b..503a01bdad 100644 --- a/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected +++ b/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected @@ -1,16 +1,16 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:31,14-22) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:33,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:35,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:38,45-53) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:48,33-41) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:48,58-66) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:49,42-50) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:30,14-22) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:32,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:34,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:37,45-53) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:47,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:47,58-66) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:48,42-50) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:51,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:51,34-42) WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:52,9-17) WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:52,34-42) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:53,9-17) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:53,34-42) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:38,9-22) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:48,7-20) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:37,9-22) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:47,7-20) | test.c:23:3:23:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:23:24:23:29 | & ... | Shared object | | test.c:74:3:74:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:74:24:74:24 | p | Shared object | | test.c:85:3:85:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:85:24:85:24 | p | Shared object | From 3882e8754fc578874b1c77cd524f580807d1d179 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 14 Feb 2025 21:29:38 -0800 Subject: [PATCH 209/370] Address feedback --- .../TimedlockOnInappropriateMutexType.ql | 4 +- .../RULE-9-7/UninitializedAtomicObject.ql | 21 ++-- ...TimedlockOnInappropriateMutexType.expected | 16 +-- .../UninitializedAtomicObject.expected | 7 +- c/misra/test/rules/RULE-9-7/test.c | 12 ++ .../cpp/StdFunctionOrMacro.qll | 111 ++++++++++++++++++ rule_packages/c/Concurrency7.json | 6 +- 7 files changed, 155 insertions(+), 22 deletions(-) create mode 100644 cpp/common/src/codingstandards/cpp/StdFunctionOrMacro.qll diff --git a/c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql b/c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql index e6dda61d79..4401d06e2c 100644 --- a/c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql +++ b/c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql @@ -71,4 +71,6 @@ where not isExcluded(sink.getNode().asExpr(), Concurrency7Package::timedlockOnInappropriateMutexTypeQuery()) and Flow::flowPath(source, sink) -select sink.getNode(), source, sink, "Call to mtx_timedlock with mutex not of type 'mtx_timed'." +select sink.getNode(), source, sink, + "Call to mtx_timedlock with mutex which is $@ without flag 'mtx_timed'.", + source.getNode(), "initialized" diff --git a/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql b/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql index 006e8e8178..b6e8bc82bc 100644 --- a/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql +++ b/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql @@ -14,6 +14,7 @@ import cpp import codingstandards.c.misra +import codingstandards.cpp.StdFunctionOrMacro import semmle.code.cpp.controlflow.Dominance class ThreadSpawningFunction extends Function { @@ -29,18 +30,14 @@ class ThreadSpawningFunction extends Function { } } -class AtomicInitAddressOfExpr extends FunctionCall { - Expr addressedExpr; +private string atomicInit() { result = "atomic_init" } +class AtomicInitAddressOfExpr extends AddressOfExpr { AtomicInitAddressOfExpr() { - exists(AddressOfExpr addrOf | - getArgument(0) = addrOf and - addrOf.getOperand() = addressedExpr and - getTarget().getName() = "__c11_atomic_init" + exists(StdFunctionOrMacro::Call c | + this = c.getArgument(0) ) } - - Expr getAddressedExpr() { result = addressedExpr } } ControlFlowNode getARequiredInitializationPoint(LocalScopeVariable v) { @@ -66,9 +63,15 @@ where not exists(v.getInitializer()) and exists(ControlFlowNode missingInitPoint | missingInitPoint = getARequiredInitializationPoint(v) and + // Check for `atomic_init(&v)` not exists(AtomicInitAddressOfExpr initialization | - initialization.getAddressedExpr().(VariableAccess).getTarget() = v and + initialization.getOperand().(VariableAccess).getTarget() = v and dominates(initialization, missingInitPoint) + ) and + // Check for `unknown_func(&v)` which may call `atomic_init` on `v`. + not exists(FunctionCall fc | + fc.getAnArgument().(AddressOfExpr).getOperand().(VariableAccess).getTarget() = v and + dominates(fc, missingInitPoint) ) ) select decl, diff --git a/c/misra/test/rules/RULE-21-26/TimedlockOnInappropriateMutexType.expected b/c/misra/test/rules/RULE-21-26/TimedlockOnInappropriateMutexType.expected index 442f20bf73..0a4c0a496a 100644 --- a/c/misra/test/rules/RULE-21-26/TimedlockOnInappropriateMutexType.expected +++ b/c/misra/test/rules/RULE-21-26/TimedlockOnInappropriateMutexType.expected @@ -35,11 +35,11 @@ nodes | test.c:44:15:44:16 | *l3 [m] | semmle.label | *l3 [m] | subpaths #select -| test.c:10:43:10:43 | *m | test.c:13:12:13:14 | mtx_init output argument | test.c:10:43:10:43 | *m | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | -| test.c:10:43:10:43 | *m | test.c:17:12:17:14 | mtx_init output argument | test.c:10:43:10:43 | *m | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | -| test.c:10:43:10:43 | *m | test.c:30:12:30:14 | mtx_init output argument | test.c:10:43:10:43 | *m | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | -| test.c:10:43:10:43 | *m | test.c:42:12:42:16 | mtx_init output argument | test.c:10:43:10:43 | *m | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | -| test.c:14:17:14:19 | *& ... | test.c:13:12:13:14 | mtx_init output argument | test.c:14:17:14:19 | *& ... | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | -| test.c:18:17:18:19 | *& ... | test.c:17:12:17:14 | mtx_init output argument | test.c:18:17:18:19 | *& ... | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | -| test.c:31:17:31:19 | *& ... | test.c:30:12:30:14 | mtx_init output argument | test.c:31:17:31:19 | *& ... | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | -| test.c:43:17:43:21 | *& ... | test.c:42:12:42:16 | mtx_init output argument | test.c:43:17:43:21 | *& ... | Call to mtx_timedlock with mutex not of type 'mtx_timed'. | +| test.c:10:43:10:43 | *m | test.c:13:12:13:14 | mtx_init output argument | test.c:10:43:10:43 | *m | Call to mtx_timedlock with mutex which is $@ without flag 'mtx_timed'. | test.c:13:12:13:14 | mtx_init output argument | initialized | +| test.c:10:43:10:43 | *m | test.c:17:12:17:14 | mtx_init output argument | test.c:10:43:10:43 | *m | Call to mtx_timedlock with mutex which is $@ without flag 'mtx_timed'. | test.c:17:12:17:14 | mtx_init output argument | initialized | +| test.c:10:43:10:43 | *m | test.c:30:12:30:14 | mtx_init output argument | test.c:10:43:10:43 | *m | Call to mtx_timedlock with mutex which is $@ without flag 'mtx_timed'. | test.c:30:12:30:14 | mtx_init output argument | initialized | +| test.c:10:43:10:43 | *m | test.c:42:12:42:16 | mtx_init output argument | test.c:10:43:10:43 | *m | Call to mtx_timedlock with mutex which is $@ without flag 'mtx_timed'. | test.c:42:12:42:16 | mtx_init output argument | initialized | +| test.c:14:17:14:19 | *& ... | test.c:13:12:13:14 | mtx_init output argument | test.c:14:17:14:19 | *& ... | Call to mtx_timedlock with mutex which is $@ without flag 'mtx_timed'. | test.c:13:12:13:14 | mtx_init output argument | initialized | +| test.c:18:17:18:19 | *& ... | test.c:17:12:17:14 | mtx_init output argument | test.c:18:17:18:19 | *& ... | Call to mtx_timedlock with mutex which is $@ without flag 'mtx_timed'. | test.c:17:12:17:14 | mtx_init output argument | initialized | +| test.c:31:17:31:19 | *& ... | test.c:30:12:30:14 | mtx_init output argument | test.c:31:17:31:19 | *& ... | Call to mtx_timedlock with mutex which is $@ without flag 'mtx_timed'. | test.c:30:12:30:14 | mtx_init output argument | initialized | +| test.c:43:17:43:21 | *& ... | test.c:42:12:42:16 | mtx_init output argument | test.c:43:17:43:21 | *& ... | Call to mtx_timedlock with mutex which is $@ without flag 'mtx_timed'. | test.c:42:12:42:16 | mtx_init output argument | initialized | diff --git a/c/misra/test/rules/RULE-9-7/UninitializedAtomicObject.expected b/c/misra/test/rules/RULE-9-7/UninitializedAtomicObject.expected index 89facda9bb..f96fc6aa13 100644 --- a/c/misra/test/rules/RULE-9-7/UninitializedAtomicObject.expected +++ b/c/misra/test/rules/RULE-9-7/UninitializedAtomicObject.expected @@ -1,3 +1,4 @@ -| test.c:22:15:22:16 | definition of l3 | Atomic object 'l3' has no initializer or corresponding use of 'atomic_init()'. | -| test.c:25:15:25:16 | definition of l4 | Atomic object 'l4' has no initializer or corresponding use of 'atomic_init()'. | -| test.c:29:15:29:16 | definition of l5 | Atomic object 'l5' has no initializer or corresponding use of 'atomic_init()'. | +| test.c:24:15:24:16 | definition of l3 | Atomic object 'l3' has no initializer or corresponding use of 'atomic_init()'. | +| test.c:27:15:27:16 | definition of l4 | Atomic object 'l4' has no initializer or corresponding use of 'atomic_init()'. | +| test.c:31:15:31:16 | definition of l5 | Atomic object 'l5' has no initializer or corresponding use of 'atomic_init()'. | +| test.c:41:15:41:16 | definition of l7 | Atomic object 'l7' has no initializer or corresponding use of 'atomic_init()'. | diff --git a/c/misra/test/rules/RULE-9-7/test.c b/c/misra/test/rules/RULE-9-7/test.c index 5b3d8e36ec..da367c0bd1 100644 --- a/c/misra/test/rules/RULE-9-7/test.c +++ b/c/misra/test/rules/RULE-9-7/test.c @@ -11,6 +11,8 @@ void f_starts_thread() { thrd_create(&t, f_thread, 0); } +void f_may_initialize_argument(void *p1) {} + void main() { _Atomic int l1 = 1; // COMPLIANT f_starts_thread(); @@ -31,4 +33,14 @@ void main() { atomic_init(&l5, 0); } f_starts_thread(); + + _Atomic int l6; // COMPLIANT + f_may_initialize_argument(&l6); + f_starts_thread(); + + _Atomic int l7; // NON_COMPLIANT + if (g1 == 0) { + f_may_initialize_argument(&l7); + } + f_starts_thread(); } \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/StdFunctionOrMacro.qll b/cpp/common/src/codingstandards/cpp/StdFunctionOrMacro.qll new file mode 100644 index 0000000000..5ae370183d --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/StdFunctionOrMacro.qll @@ -0,0 +1,111 @@ +/** + * This module intends to reduce the difficulty of handling the pattern where implementations + * implement a function as a macro: the class `StdFunctionOrMacro<...>::Call` matches both std + * function calls as well as std function macro expansions. + * + * For instance, `atomic_init` may be implemented as a function, but is also implemented as + * `#DEFINE atomic_init(x) __c11_atomic_init(x)` on some platforms. This module aids in finding + * calls to any standard function which may be a macro, and has predefined behavior for + * handling `__c11_*` macros. + * + * Since a macro can be defined to expand to any expression, we cannot know generally which + * expanded expressions in `f(x, y)` correspond to arguments `x` or `y`. To handle this, the + * following inference options are available: + * - `NoMacroExpansionInference`: Assume any expression in the macro expansion could correspond to + * any macro argument. + * - `C11FunctionWrapperMacro`: Check if the macro expands to a function call prefixed with + * `__c11_` and if so, return the corresponding argument. Otherwise, fall back to + * `NoMacroExpansionInference`. + * - `InferMacroExpansionArguments`: Implement your own logic for inferring the argument. + * + * To use this module, pick one of the above inference strategies, and then create a predicate for + * the name you wish to match. For instance: + * + * ```codeql + * private string atomicInit() { result = "atomic_init" } + * + * from StdFunctionOrMacro::Call c + * select c.getArgument(0) + * ``` + */ + +import cpp as cpp + +/** Specify the name of your function as a predicate */ +signature string getName(); + +/** Signature module to implement custom argument resolution behavior in expanded macros */ +signature module InferMacroExpansionArguments { + bindingset[mi, argumentIdx] + cpp::Expr inferArgument(cpp::MacroInvocation mi, int argumentIdx); +} + +/** Assume all subexpressions of an expanded macro may be the result of any ith argument */ +module NoMacroExpansionInference implements InferMacroExpansionArguments { + bindingset[mi, argumentIdx] + cpp::Expr inferArgument(cpp::MacroInvocation mi, int argumentIdx) { + result.getParent*() = mi.getExpr() + } +} + +/** Assume macro `f(x, y, ...)` expands to `__c11_f(x, y, ...)`. */ +module C11FunctionWrapperMacro implements InferMacroExpansionArguments { + bindingset[mi, argumentIdx] + cpp::Expr inferArgument(cpp::MacroInvocation mi, int argumentIdx) { + if mi.getExpr().(cpp::FunctionCall).getTarget().hasName("__c11_" + mi.getMacroName()) + then result = mi.getExpr().(cpp::FunctionCall).getArgument(argumentIdx) + else result = NoMacroExpansionInference::inferArgument(mi, argumentIdx) + } +} + +/** + * A module to find calls to standard functions, or expansions of macros with the same name. + * + * To use this module, specify a name predicate and an inference strategy for correlating macro + * expansions to macro arguments. + * + * For example: + * + * ```codeql + * private string atomicInit() { result = "atomic_init" } + * from StdFunctionOrMacro::Call c + * select c.getArgument(0) + * ``` + */ +module StdFunctionOrMacro { + final private class Expr = cpp::Expr; + + final private class FunctionCall = cpp::FunctionCall; + + final private class MacroInvocation = cpp::MacroInvocation; + + private newtype TStdCall = + TStdFunctionCall(FunctionCall fc) { fc.getTarget().hasName(getStdName()) } or + TStdMacroInvocation(MacroInvocation mi) { mi.getMacro().hasName(getStdName()) } + + /** + * A call to a standard function or an expansion of a macro with the same name. + */ + class Call extends TStdCall { + bindingset[this, argumentIdx] + Expr getArgument(int argumentIdx) { + exists(FunctionCall fc | + this = TStdFunctionCall(fc) and + result = fc.getArgument(argumentIdx) + ) + or + exists(MacroInvocation mi | + this = TStdMacroInvocation(mi) and + result = InferExpansion::inferArgument(mi, argumentIdx) + ) + } + + string toString() { + this = TStdFunctionCall(_) and + result = "Standard function call" + or + this = TStdMacroInvocation(_) and + result = "Invocation of a standard function implemented as a macro" + } + } +} diff --git a/rule_packages/c/Concurrency7.json b/rule_packages/c/Concurrency7.json index 6fdc49984b..bda8881934 100644 --- a/rule_packages/c/Concurrency7.json +++ b/rule_packages/c/Concurrency7.json @@ -15,7 +15,11 @@ "tags": [ "concurrency", "external/misra/c/2012/amendment4" - ] + ], + "implementation_scope": { + "description": "This query tracks which functions may start threads, either indirectly or directly (\"thread spawning functions\"), and checks for local atomic variables that are not passed by address into `atomic_init` or other function calls, before such a thread spawning function is called.", + "items": [] + } } ], "title": "Atomic objects shall be appropriately initialized before being accessed" From b294477a2c2b79cf8242e8f12c0bc8e5a7689f3b Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 14 Feb 2025 21:37:26 -0800 Subject: [PATCH 210/370] CI/CD fixes: format, rules.csv package -> Concurrency8 for unhandled rules --- .../TimedlockOnInappropriateMutexType.ql | 4 ++-- rules.csv | 20 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql b/c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql index 4401d06e2c..929eb5bd0a 100644 --- a/c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql +++ b/c/misra/src/rules/RULE-21-26/TimedlockOnInappropriateMutexType.ql @@ -72,5 +72,5 @@ where Concurrency7Package::timedlockOnInappropriateMutexTypeQuery()) and Flow::flowPath(source, sink) select sink.getNode(), source, sink, - "Call to mtx_timedlock with mutex which is $@ without flag 'mtx_timed'.", - source.getNode(), "initialized" + "Call to mtx_timedlock with mutex which is $@ without flag 'mtx_timed'.", source.getNode(), + "initialized" diff --git a/rules.csv b/rules.csv index 10478a3da8..3f959542a7 100644 --- a/rules.csv +++ b/rules.csv @@ -617,7 +617,7 @@ c,MISRA-C-2012,DIR-4-12,Yes,Required,,,Dynamic memory allocation shall not be us c,MISRA-C-2012,DIR-4-13,No,Advisory,,,Functions which are designed to provide operations on a resource should be called in an appropriate sequence,,,,"Rule 22.1, 22.2 and 22.6 cover aspects of this rule. In other cases this is a design issue and needs to be checked manually." c,MISRA-C-2012,DIR-4-14,Yes,Required,,,The validity of values received from external sources shall be checked,,Contracts8,Hard,This is supported by CodeQLs default C security queries. c,MISRA-C-2012,DIR-4-15,Yes,Required,,,Evaluation of floating-point expressions shall not lead to the undetected generation of infinities and NaNs,FLP32-C and FLP04-C,FloatingTypes2,Medium, -c,MISRA-C-2012,DIR-5-1,Yes,Required,,,There shall be no data races between threads,CON43-C and CON32-C,Concurrency7,Very Hard, +c,MISRA-C-2012,DIR-5-1,Yes,Required,,,There shall be no data races between threads,CON43-C and CON32-C,Concurrency8,Very Hard, c,MISRA-C-2012,DIR-5-2,Yes,Required,,,There shall be no deadlocks between threads,CON35-C,Concurrency6,Import, c,MISRA-C-2012,DIR-5-3,Yes,Required,,,There shall be no dynamic thread creation,,Concurrency6,Easy, c,MISRA-C-2012,RULE-1-1,No,Required,,,"The program shall contain no violations of the standard C syntax and constraints, and shall not exceed the implementation's translation limits",,,Easy,"This should be checked via the compiler output, rather than CodeQL, which adds unnecessary steps." @@ -803,15 +803,15 @@ c,MISRA-C-2012,RULE-22-8,Yes,Required,,,The value of errno shall be set to zero c,MISRA-C-2012,RULE-22-9,Yes,Required,,,The value of errno shall be tested against zero after calling an errno-setting-function,,Contracts3,Medium, c,MISRA-C-2012,RULE-22-10,Yes,Required,,,The value of errno shall only be tested when the last function to be called was an errno-setting-function,,Contracts3,Medium, c,MISRA-C-2012,RULE-22-11,Yes,Required,,,A thread that was previously either joined or detached shall not be subsequently joined nor detached,CON39-C,Concurrency6,Import, -c,MISRA-C-2012,RULE-22-12,Yes,Mandatory,,,"Thread objects, thread synchronization objects, and thread-specific storage pointers shall only be accessed by the appropriate Standard Library functions",,Concurrency7,Medium, -c,MISRA-C-2012,RULE-22-13,Yes,Required,,,"Thread objects, thread synchronization objects, and thread specific storage pointers shall have appropriate storage duration",EXP54-CPP and CON34-C,Concurrency7,Medium, -c,MISRA-C-2012,RULE-22-14,Yes,Mandatory,,,Thread synchronization objects shall be initialized before being accessed,EXP53-CPP,Concurrency7,Hard, -c,MISRA-C-2012,RULE-22-15,Yes,Required,,,Thread synchronization objects and thread-specific storage pointers shall not be destroyed until after all threads accessing them have terminated,,Concurrency7,Hard, -c,MISRA-C-2012,RULE-22-16,Yes,Required,,,All mutex objects locked by a thread shall be explicitly unlocked by the same thread,MEM51-CPP,Concurrency7,Hard, -c,MISRA-C-2012,RULE-22-17,Yes,Required,,,No thread shall unlock a mutex or call cnd_wait() or cnd_timedwait() for a mutex it has not locked before,Rule 22.2,Concurrency7,Medium, -c,MISRA-C-2012,RULE-22-18,Yes,Required,,,Non-recursive mutexes shall not be recursively locked,CON56-CPP,Concurrency7,Medium, -c,MISRA-C-2012,RULE-22-19,Yes,Required,,,A condition variable shall be associated with at most one mutex object,,Concurrency7,Medium, -c,MISRA-C-2012,RULE-22-20,Yes,Mandatory,,,Thread-specific storage pointers shall be created before being accessed,,Concurrency7,Hard, +c,MISRA-C-2012,RULE-22-12,Yes,Mandatory,,,"Thread objects, thread synchronization objects, and thread-specific storage pointers shall only be accessed by the appropriate Standard Library functions",,Concurrency8,Medium, +c,MISRA-C-2012,RULE-22-13,Yes,Required,,,"Thread objects, thread synchronization objects, and thread specific storage pointers shall have appropriate storage duration",EXP54-CPP and CON34-C,Concurrency8,Medium, +c,MISRA-C-2012,RULE-22-14,Yes,Mandatory,,,Thread synchronization objects shall be initialized before being accessed,EXP53-CPP,Concurrency8,Hard, +c,MISRA-C-2012,RULE-22-15,Yes,Required,,,Thread synchronization objects and thread-specific storage pointers shall not be destroyed until after all threads accessing them have terminated,,Concurrency8,Hard, +c,MISRA-C-2012,RULE-22-16,Yes,Required,,,All mutex objects locked by a thread shall be explicitly unlocked by the same thread,MEM51-CPP,Concurrency8,Hard, +c,MISRA-C-2012,RULE-22-17,Yes,Required,,,No thread shall unlock a mutex or call cnd_wait() or cnd_timedwait() for a mutex it has not locked before,Rule 22.2,Concurrency8,Medium, +c,MISRA-C-2012,RULE-22-18,Yes,Required,,,Non-recursive mutexes shall not be recursively locked,CON56-CPP,Concurrency8,Medium, +c,MISRA-C-2012,RULE-22-19,Yes,Required,,,A condition variable shall be associated with at most one mutex object,,Concurrency8,Medium, +c,MISRA-C-2012,RULE-22-20,Yes,Mandatory,,,Thread-specific storage pointers shall be created before being accessed,,Concurrency8,Hard, c,MISRA-C-2012,RULE-23-1,Yes,Advisory,,,A generic selection should only be expanded from a macro,,Generics,Medium, c,MISRA-C-2012,RULE-23-2,Yes,Required,,,A generic selection that is not expanded from a macro shall not contain potential side effects in the controlling expression,,Generics,Hard, c,MISRA-C-2012,RULE-23-3,Yes,Advisory,,,A generic selection should contain at least one non-default association,,Generics,Easy, From 0b59317e33dd4f2512017f74950fa474c87319ff Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 17 Feb 2025 17:51:34 +0000 Subject: [PATCH 211/370] A27-0-3: Improve performance oppositeDirection was a performance problem, because it was not restricted to read write calls with the same source. --- change_notes/2025-02-17-iofstream-performance.md | 2 ++ .../IOFstreamMissingPositioning.qll | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 change_notes/2025-02-17-iofstream-performance.md diff --git a/change_notes/2025-02-17-iofstream-performance.md b/change_notes/2025-02-17-iofstream-performance.md new file mode 100644 index 0000000000..8a0be4c3ac --- /dev/null +++ b/change_notes/2025-02-17-iofstream-performance.md @@ -0,0 +1,2 @@ + - `A27-0-3`, `FIO309-C` `FIO50-CPP`, `RULE-30-0-2` - `InterleavedInputOutputWithoutFlush.ql`, `DoNotAlternatelyIOFromStreamWithoutPositioning.ql`,`InterleavedInputOutputWithoutPosition.ql`, `ReadsAndWritesOnStreamNotSeparatedByPositioning.ql`: + - Reduce evaluation time on complex codebases. \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll b/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll index 89f847c5aa..547c90daf5 100644 --- a/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll +++ b/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll @@ -57,17 +57,19 @@ predicate sameSource(FunctionCall a, FunctionCall b) { sameFileSource(a, b) } +bindingset[a, b] predicate sameAccessDirection(ReadWriteCall a, ReadWriteCall b) { a.getAccessDirection() = b.getAccessDirection() } +bindingset[a, b] predicate oppositeAccessDirection(ReadWriteCall a, ReadWriteCall b) { not sameAccessDirection(a, b) } /** * A write operation reaching a read and vice versa - * without intervening filepositioning + * without intervening file positioning calls. */ ControlFlowNode reachesInExOperator(ReadWriteCall op) { result = op From 029537df335fc3cd8dda1ec7a1d123a4f036114e Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 18 Feb 2025 13:36:22 +0000 Subject: [PATCH 212/370] Fix typos --- .../InvalidDeviationCodeIdentifier.md | 2 +- docs/user_manual.md | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.md b/cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.md index 9c128bab2d..364e1ae915 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.md +++ b/cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.md @@ -1,4 +1,4 @@ -# Invalid deviation dode identifier +# Invalid deviation code identifier ## Overview diff --git a/docs/user_manual.md b/docs/user_manual.md index 8bbb900682..fb36d30fb7 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -485,26 +485,26 @@ Here are some examples, using the deviation record with the `a-0-4-2-deviation` long double x2; // a-0-4-2-deviation - COMPLIANT long double x3; // COMPLIANT - a-0-4-2-deviation - long double x4; // codeql::_deviation(a-0-4-2-deviation) - COMPLIANT - long double x5; // COMPLIANT - codeql::_deviation(a-0-4-2-deviation) + long double x4; // codeql::autosar_deviation(a-0-4-2-deviation) - COMPLIANT + long double x5; // COMPLIANT - codeql::autosar_deviation(a-0-4-2-deviation) - // codeql::_deviation_next_line(a-0-4-2-deviation) + // codeql::autosar_deviation_next_line(a-0-4-2-deviation) long double x6; // COMPLIANT - // codeql::_deviation_begin(a-0-4-2-deviation) + // codeql::autosar_deviation_begin(a-0-4-2-deviation) long double x7; // COMPLIANT - // codeql::_deviation_end(a-0-4-2-deviation) + // codeql::autosar_deviation_end(a-0-4-2-deviation) ``` `codeql::_deviation_end` markers will pair with the closest unmatched `codeql::_deviation_begin` for the same `code-identifier`. Consider this example: ```cpp -1 | // codeql::_deviation_begin(a-0-4-2-deviation) +1 | // codeql::autosar_deviation_begin(a-0-4-2-deviation) 2 | -3 | // codeql::_deviation_begin(a-0-4-2-deviation) +3 | // codeql::autosar_deviation_begin(a-0-4-2-deviation) 4 | -5 | // codeql::_deviation_end(a-0-4-2-deviation) +5 | // codeql::autosar_deviation_end(a-0-4-2-deviation) 6 | -7 | // codeql::_deviation_end(a-0-4-2-deviation) +7 | // codeql::autosar_deviation_end(a-0-4-2-deviation) ``` Here, Line 1 will pair with Line 7, and Line 3 will pair with Line 5. From 3f1997b6ce3bac8e2c42d0d5f93f8f12430ed5e3 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 18 Feb 2025 13:36:40 +0000 Subject: [PATCH 213/370] Deviations: Highlight invalid starts --- .../cpp/deviations/InvalidDeviationCodeIdentifier.ql | 6 ++++++ .../InvalidDeviationCodeIdentifier.expected | 5 ++++- .../invalid_deviations/invalidcodeidentifiers.cpp | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.ql b/cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.ql index 03e1ffc2b0..87dafbba13 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.ql +++ b/cpp/common/src/codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.ql @@ -16,6 +16,12 @@ predicate deviationCodeIdentifierError(Element e, string message) { message = "Deviation end block is unmatched." ) or + exists(DeviationBegin begin | + e = begin and + not isDeviationRangePaired(_, begin, _) and + message = "Deviation start block is unmatched." + ) + or exists(InvalidDeviationAttribute b | e = b and message = diff --git a/cpp/common/test/deviations/invalid_deviations/InvalidDeviationCodeIdentifier.expected b/cpp/common/test/deviations/invalid_deviations/InvalidDeviationCodeIdentifier.expected index eb81658007..1d7153bafd 100644 --- a/cpp/common/test/deviations/invalid_deviations/InvalidDeviationCodeIdentifier.expected +++ b/cpp/common/test/deviations/invalid_deviations/InvalidDeviationCodeIdentifier.expected @@ -7,4 +7,7 @@ | invalidcodeidentifiers.cpp:14:1:14:74 | // codeql::misra_deviation_end(a-0-4-2-deviation) - invalid, unmatched end | Deviation end block is unmatched. | | invalidcodeidentifiers.cpp:15:1:15:76 | // codeql::autosar_deviation_end(a-0-4-2-deviation) - invalid, unmatched end | Deviation end block is unmatched. | | invalidcodeidentifiers.cpp:16:1:16:73 | // codeql::cert_deviation_end(a-0-4-2-deviation) - invalid, unmatched end | Deviation end block is unmatched. | -| invalidcodeidentifiers.cpp:18:3:18:25 | misra_deviation | Deviation attribute references unknown code identifier x. | +| invalidcodeidentifiers.cpp:17:1:17:78 | // codeql::misra_deviation_begin(a-0-4-2-deviation) - invalid, unmatched begin | Deviation start block is unmatched. | +| invalidcodeidentifiers.cpp:18:1:18:80 | // codeql::autosar_deviation_begin(a-0-4-2-deviation) - invalid, unmatched begin | Deviation start block is unmatched. | +| invalidcodeidentifiers.cpp:19:1:19:77 | // codeql::cert_deviation_begin(a-0-4-2-deviation) - invalid, unmatched begin | Deviation start block is unmatched. | +| invalidcodeidentifiers.cpp:21:3:21:25 | misra_deviation | Deviation attribute references unknown code identifier x. | diff --git a/cpp/common/test/deviations/invalid_deviations/invalidcodeidentifiers.cpp b/cpp/common/test/deviations/invalid_deviations/invalidcodeidentifiers.cpp index 07a12eb713..a4da098dcb 100644 --- a/cpp/common/test/deviations/invalid_deviations/invalidcodeidentifiers.cpp +++ b/cpp/common/test/deviations/invalid_deviations/invalidcodeidentifiers.cpp @@ -14,6 +14,9 @@ // codeql::misra_deviation_end(a-0-4-2-deviation) - invalid, unmatched end // codeql::autosar_deviation_end(a-0-4-2-deviation) - invalid, unmatched end // codeql::cert_deviation_end(a-0-4-2-deviation) - invalid, unmatched end +// codeql::misra_deviation_begin(a-0-4-2-deviation) - invalid, unmatched begin +// codeql::autosar_deviation_begin(a-0-4-2-deviation) - invalid, unmatched begin +// codeql::cert_deviation_begin(a-0-4-2-deviation) - invalid, unmatched begin [[codeql::misra_deviation("x")]] // invalid void test() {} From 665a7d16c8c0f2339075c3097b40405bb393fc97 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 18 Feb 2025 16:50:33 +0000 Subject: [PATCH 214/370] Improve documentation --- .../codingstandards/cpp/deviations/CodeIdentifierDeviation.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll index 2a2d0eec15..ab121f6095 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll @@ -145,6 +145,8 @@ private predicate mkBeginStack(DeviationRecord record, File file, BeginStack sta // Stack is empty at the start index = 0 and stack = TEmptyBeginStack() and + // Only initialize when there is at least one such comment marker for this file and record + // pairing exists(CommentDeviationRangeMarker marker | marker.getRecord() = record and marker.getLocation().getFile() = file ) From 8437c7cc76d011455580810501ccd7de2ce26190 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 18 Feb 2025 17:34:51 +0000 Subject: [PATCH 215/370] Deviation: Refactor begin/end for clarity. --- .../deviations/CodeIdentifierDeviation.qll | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll index ab121f6095..9a694ccc8f 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll @@ -141,10 +141,14 @@ private predicate hasDeviationCommentFileOrdering( ) } -private predicate mkBeginStack(DeviationRecord record, File file, BeginStack stack, int index) { +/** + * Calculate the stack of deviation begin markers related to the given deviation record, in the given file, + * at the given `markerRecordFileIndex` into the list of deviation markers for that record in that file. + */ +private BeginStack calculateBeginStack(DeviationRecord record, File file, int markerRecordFileIndex) { // Stack is empty at the start - index = 0 and - stack = TEmptyBeginStack() and + markerRecordFileIndex = 0 and + result = TEmptyBeginStack() and // Only initialize when there is at least one such comment marker for this file and record // pairing exists(CommentDeviationRangeMarker marker | @@ -154,23 +158,23 @@ private predicate mkBeginStack(DeviationRecord record, File file, BeginStack sta // Next token is begin, so push it to the stack exists(DeviationBegin begin, BeginStack prev | record = begin.getRecord() and - hasDeviationCommentFileOrdering(record, begin, file, index) and - mkBeginStack(record, file, prev, index - 1) and - stack = TConsBeginStack(begin, prev) + hasDeviationCommentFileOrdering(record, begin, file, markerRecordFileIndex) and + prev = calculateBeginStack(record, file, markerRecordFileIndex - 1) and + result = TConsBeginStack(begin, prev) ) or // Next token is end exists(DeviationEnd end, BeginStack prevStack | record = end.getRecord() and - hasDeviationCommentFileOrdering(record, end, file, index) and - mkBeginStack(record, file, prevStack, index - 1) + hasDeviationCommentFileOrdering(record, end, file, markerRecordFileIndex) and + prevStack = calculateBeginStack(record, file, markerRecordFileIndex - 1) | // There is, so pop the most recent begin off the stack - prevStack = TConsBeginStack(_, stack) + prevStack = TConsBeginStack(_, result) or - // Error, no begin on the stack, ignore and continue + // Error, no begin on the stack, ignore the end and continue prevStack = TEmptyBeginStack() and - stack = TEmptyBeginStack() + result = TEmptyBeginStack() ) } @@ -178,12 +182,18 @@ newtype TBeginStack = TConsBeginStack(DeviationBegin begin, TBeginStack prev) { exists(File file, int index | hasDeviationCommentFileOrdering(begin.getRecord(), begin, file, index) and - mkBeginStack(begin.getRecord(), file, prev, index - 1) + prev = calculateBeginStack(begin.getRecord(), file, index - 1) ) } or TEmptyBeginStack() +/** + * A stack of begin markers that occur in the same file, referring to the same record. + */ private class BeginStack extends TBeginStack { + /** Gets the top begin marker on the stack. */ + DeviationBegin peek() { this = TConsBeginStack(result, _) } + string toString() { exists(DeviationBegin begin, BeginStack prev | this = TConsBeginStack(begin, prev) | result = "(" + begin + ", " + prev.toString() + ")" @@ -198,7 +208,7 @@ predicate isDeviationRangePaired(DeviationRecord record, DeviationBegin begin, D exists(File file, int index | record = end.getRecord() and hasDeviationCommentFileOrdering(record, end, file, index) and - mkBeginStack(record, file, TConsBeginStack(begin, _), index - 1) + begin = calculateBeginStack(record, file, index - 1).peek() ) } From 20669c7cc43e2c5fb2b6ab6cb2e76a6196ad2102 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 18 Feb 2025 17:35:08 +0000 Subject: [PATCH 216/370] Deviation: Clarification in user manual. --- docs/user_manual.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user_manual.md b/docs/user_manual.md index fb36d30fb7..a04ba0814e 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -512,7 +512,7 @@ A `codeql::_deviation_end` without a matching `codeql::_devi `codeql::_deviation_begin` and `ccodeql::_deviation_end` markers only apply within a single file. Markers cannot be paired across files, and deviations do not apply to included files. -Note: deviation markers cannot be applied to the body of a macro. Please apply the deviation to macro expansion, or use the attribute deviation format. +Note: deviation comment markers cannot be applied to the body of a macro. Please apply the deviation to macro expansion, or use the attribute deviation format. ##### Deviation permits From 713c6756671b01ef8fec7acb3f03d940dc859ed4 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 9 Dec 2024 14:47:29 -0800 Subject: [PATCH 217/370] Implement Concurrency9 package on top of Concurrency8 work --- c/common/src/codingstandards/c/SubObjects.qll | 94 ++ .../GlobalInitializationAnalysis.qll | 93 ++ .../test/includes/standard-library/stdlib.h | 1 + .../DIR-5-1/PossibleDataRaceBetweenThreads.ql | 158 +++ .../MutexNotInitializedBeforeUse.ql | 128 +- ...readResourceDisposedBeforeThreadsJoined.ql | 113 ++ .../InvalidOperationOnUnlockedMutex.ql | 68 ++ .../NonRecursiveMutexRecursivelyLocked.ql | 37 + ...NonRecursiveMutexRecursivelyLockedAudit.ql | 60 + ...onditionVariableUsedWithMultipleMutexes.ql | 69 ++ .../ThreadStorageNotInitializedBeforeUse.ql | 44 + ...adStoragePointerInitializedInsideThread.ql | 27 + .../PossibleDataRaceBetweenThreads.expected | 24 + .../PossibleDataRaceBetweenThreads.qlref | 1 + c/misra/test/rules/DIR-5-1/test.c | 132 +++ ...sourceDisposedBeforeThreadsJoined.expected | 12 + ...dResourceDisposedBeforeThreadsJoined.qlref | 1 + c/misra/test/rules/RULE-22-15/test.c | 113 ++ .../InvalidOperationOnUnlockedMutex.expected | 16 + .../InvalidOperationOnUnlockedMutex.qlref | 1 + c/misra/test/rules/RULE-22-17/test.c | 70 ++ ...onRecursiveMutexRecursivelyLocked.expected | 2 + .../NonRecursiveMutexRecursivelyLocked.qlref | 1 + ...ursiveMutexRecursivelyLockedAudit.expected | 6 + ...RecursiveMutexRecursivelyLockedAudit.qlref | 1 + c/misra/test/rules/RULE-22-18/test.c | 122 ++ ...onVariableUsedWithMultipleMutexes.expected | 2 + ...itionVariableUsedWithMultipleMutexes.qlref | 1 + c/misra/test/rules/RULE-22-19/test.c | 46 + ...eadStorageNotInitializedBeforeUse.expected | 5 + ...ThreadStorageNotInitializedBeforeUse.qlref | 1 + ...agePointerInitializedInsideThread.expected | 1 + ...toragePointerInitializedInsideThread.qlref | 1 + c/misra/test/rules/RULE-22-20/test.c | 70 ++ ...2024-12-10-refactor-concurrency-library.md | 2 + .../src/codingstandards/cpp/Concurrency.qll | 1026 +---------------- .../cpp/concurrency/Atomic.qll | 43 + .../cpp/concurrency/CConditionOperation.qll | 31 + .../cpp/concurrency/ConditionalWait.qll | 26 + .../cpp/concurrency/ControlFlow.qll | 101 ++ .../concurrency/LockProtectedControlFlow.qll | 49 + .../cpp/concurrency/LockingOperation.qll | 240 ++++ .../cpp/concurrency/MutexDestroyer.qll | 73 ++ .../cpp/concurrency/ThreadCreation.qll | 62 + .../cpp/concurrency/ThreadDependentMutex.qll | 246 ++++ .../cpp/concurrency/ThreadSpecificStorage.qll | 59 + .../cpp/concurrency/ThreadWaitDetach.qll | 41 + .../cpp/concurrency/ThreadedFunction.qll | 37 + .../codingstandards/cpp/concurrency/Types.qll | 29 + .../cpp/dominance/BehavioralSet.qll | 47 + .../cpp/exclusions/c/Concurrency9.qll | 146 +++ .../cpp/exclusions/c/RuleMetadata.qll | 3 + rule_packages/c/Concurrency9.json | 158 +++ rules.csv | 12 +- 54 files changed, 2843 insertions(+), 1109 deletions(-) create mode 100644 c/common/src/codingstandards/c/SubObjects.qll create mode 100644 c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll create mode 100644 c/misra/src/rules/DIR-5-1/PossibleDataRaceBetweenThreads.ql create mode 100644 c/misra/src/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.ql create mode 100644 c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql create mode 100644 c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.ql create mode 100644 c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql create mode 100644 c/misra/src/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.ql create mode 100644 c/misra/src/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.ql create mode 100644 c/misra/src/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.ql create mode 100644 c/misra/test/rules/DIR-5-1/PossibleDataRaceBetweenThreads.expected create mode 100644 c/misra/test/rules/DIR-5-1/PossibleDataRaceBetweenThreads.qlref create mode 100644 c/misra/test/rules/DIR-5-1/test.c create mode 100644 c/misra/test/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.expected create mode 100644 c/misra/test/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.qlref create mode 100644 c/misra/test/rules/RULE-22-15/test.c create mode 100644 c/misra/test/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.expected create mode 100644 c/misra/test/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.qlref create mode 100644 c/misra/test/rules/RULE-22-17/test.c create mode 100644 c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.expected create mode 100644 c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.qlref create mode 100644 c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.expected create mode 100644 c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.qlref create mode 100644 c/misra/test/rules/RULE-22-18/test.c create mode 100644 c/misra/test/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.expected create mode 100644 c/misra/test/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.qlref create mode 100644 c/misra/test/rules/RULE-22-19/test.c create mode 100644 c/misra/test/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.expected create mode 100644 c/misra/test/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.qlref create mode 100644 c/misra/test/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.expected create mode 100644 c/misra/test/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.qlref create mode 100644 c/misra/test/rules/RULE-22-20/test.c create mode 100644 change_notes/2024-12-10-refactor-concurrency-library.md create mode 100644 cpp/common/src/codingstandards/cpp/concurrency/Atomic.qll create mode 100644 cpp/common/src/codingstandards/cpp/concurrency/CConditionOperation.qll create mode 100644 cpp/common/src/codingstandards/cpp/concurrency/ConditionalWait.qll create mode 100644 cpp/common/src/codingstandards/cpp/concurrency/ControlFlow.qll create mode 100644 cpp/common/src/codingstandards/cpp/concurrency/LockProtectedControlFlow.qll create mode 100644 cpp/common/src/codingstandards/cpp/concurrency/LockingOperation.qll create mode 100644 cpp/common/src/codingstandards/cpp/concurrency/MutexDestroyer.qll create mode 100644 cpp/common/src/codingstandards/cpp/concurrency/ThreadCreation.qll create mode 100644 cpp/common/src/codingstandards/cpp/concurrency/ThreadDependentMutex.qll create mode 100644 cpp/common/src/codingstandards/cpp/concurrency/ThreadSpecificStorage.qll create mode 100644 cpp/common/src/codingstandards/cpp/concurrency/ThreadWaitDetach.qll create mode 100644 cpp/common/src/codingstandards/cpp/concurrency/ThreadedFunction.qll create mode 100644 cpp/common/src/codingstandards/cpp/concurrency/Types.qll create mode 100644 cpp/common/src/codingstandards/cpp/dominance/BehavioralSet.qll create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency9.qll create mode 100644 rule_packages/c/Concurrency9.json diff --git a/c/common/src/codingstandards/c/SubObjects.qll b/c/common/src/codingstandards/c/SubObjects.qll new file mode 100644 index 0000000000..d7aa1e976b --- /dev/null +++ b/c/common/src/codingstandards/c/SubObjects.qll @@ -0,0 +1,94 @@ +import codingstandards.c.Objects + +newtype TSubObject = + TObjectRoot(ObjectIdentity i) or + TObjectMember(SubObject struct, MemberVariable m) { + m = struct.getType().(Struct).getAMemberVariable() + } or + TObjectIndex(SubObject array) { array.getType() instanceof ArrayType } + +class SubObject extends TSubObject { + string toString() { + exists(ObjectIdentity i | + this = TObjectRoot(i) and + result = i.toString() + ) + or + exists(SubObject struct, Variable m | + this = TObjectMember(struct, m) and + result = struct.toString() + "." + m.getName() + ) + or + exists(SubObject array | + this = TObjectIndex(array) and + result = array.toString() + ) + } + + Type getType() { + exists(ObjectIdentity i | + this = TObjectRoot(i) and + result = i.getType() + ) + or + exists(Variable m | + this = TObjectMember(_, m) and + result = m.getType() + ) + or + exists(SubObject array | + this = TObjectIndex(array) and + result = array.getType().(ArrayType).getBaseType() + ) + } + + /** + * Holds for object roots and for member accesses on that root, not for array accesses. + * + * This is useful for cases where we do not wish to treat `x[y]` and `x[z]` as the same object. + */ + predicate isPrecise() { + not getParent*() = TObjectIndex(_) + } + + SubObject getParent() { + exists(SubObject struct, MemberVariable m | + this = TObjectMember(struct, m) and + result = struct + ) + or + exists(SubObject array | + this = TObjectIndex(array) and + result = array + ) + } + + Expr getAnAccess() { + exists(ObjectIdentity i | + this = TObjectRoot(i) and + result = i.getAnAccess() + ) + or + exists(MemberVariable m | + this = TObjectMember(_, m) and + result = m.getAnAccess() and + result.(DotFieldAccess).getQualifier() = getParent().getAnAccess() + ) + or + this = TObjectIndex(_) and + result.(ArrayExpr).getArrayBase() = getParent().getAnAccess() + } + + AddressOfExpr getAnAddressOfExpr() { + result.getOperand() = this.getAnAccess() + } + + ObjectIdentity getRootIdentity() { + exists(ObjectIdentity i | + this = TObjectRoot(i) and + result = i + ) + or + result = getParent().getRootIdentity() + } +} diff --git a/c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll b/c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll new file mode 100644 index 0000000000..d2974f9924 --- /dev/null +++ b/c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll @@ -0,0 +1,93 @@ +import cpp +import codingstandards.c.Objects +import codingstandards.cpp.Concurrency +import codingstandards.cpp.Type + +signature module GlobalInitializationAnalysisConfigSig { + /** A function which is not called or started as a thread */ + default predicate isRootFunction(Function f) { + not exists(Function f2 | f2.calls(f)) and + not f instanceof ThreadedFunction + } + + ObjectIdentity getAnInitializedObject(Expr e); + + ObjectIdentity getAUsedObject(Expr e); +} + +module GlobalInitalizationAnalysis { + final class FinalFunction = Function; + + final class FinalExpr = Expr; + + class RootFunction extends FinalFunction { + RootFunction() { Config::isRootFunction(this) } + } + + /** A function call which initializes a mutex or a condition */ + class ObjectInit extends FinalExpr { + ObjectIdentity owningObject; + + ObjectInit() { owningObject = Config::getAnInitializedObject(this) } + + ObjectIdentity getOwningObject() { result = owningObject } + } + + /** + * A function argument where that argument is used as a mutex or condition object. + */ + class ObjectUse extends FinalExpr { + ObjectIdentity owningObject; + + ObjectUse() { owningObject = Config::getAUsedObject(this) } + + ObjectIdentity getOwningObject() { result = owningObject } + } + + predicate requiresInitializedMutexObject( + Function func, ObjectUse mutexUse, ObjectIdentity owningObject + ) { + mutexUse.getEnclosingFunction() = func and + owningObject = mutexUse.getOwningObject() and + not exists(ObjectInit init | + init.getEnclosingFunction() = func and + init.getOwningObject() = owningObject and + mutexUse.getAPredecessor+() = init + ) + or + exists(FunctionCall call | + func = call.getEnclosingFunction() and + requiresInitializedMutexObject(call.getTarget(), mutexUse, owningObject) and + not exists(ObjectInit init | + call.getAPredecessor*() = init and + init.getOwningObject() = owningObject + ) + ) + or + exists(C11ThreadCreateCall call | + func = call.getEnclosingFunction() and + not owningObject.getStorageDuration().isThread() and + requiresInitializedMutexObject(call.getFunction(), mutexUse, owningObject) and + not exists(ObjectInit init | + call.getAPredecessor*() = init and + init.getOwningObject() = owningObject + ) + ) + } + + predicate uninitializedFrom(Expr e, ObjectIdentity obj, Function callRoot) { + exists(ObjectUse use | use = e | + obj = use.getOwningObject() and + requiresInitializedMutexObject(callRoot, use, obj) and + ( + if obj.getStorageDuration().isAutomatic() + then obj.getEnclosingElement+() = callRoot + else ( + obj.getStorageDuration().isThread() and callRoot instanceof ThreadedFunction + or + callRoot instanceof RootFunction + ) + ) + ) + } +} diff --git a/c/common/test/includes/standard-library/stdlib.h b/c/common/test/includes/standard-library/stdlib.h index b54a051fe9..1af95223d1 100644 --- a/c/common/test/includes/standard-library/stdlib.h +++ b/c/common/test/includes/standard-library/stdlib.h @@ -49,6 +49,7 @@ int at_quick_exit (void (*) (void)); _Noreturn void quick_exit (int); char *getenv (const char *); +char *getenv_s (size_t *restrict len, char *restrict value, size_t valuesz, const char *restrict name); int system (const char *); diff --git a/c/misra/src/rules/DIR-5-1/PossibleDataRaceBetweenThreads.ql b/c/misra/src/rules/DIR-5-1/PossibleDataRaceBetweenThreads.ql new file mode 100644 index 0000000000..443dc284fd --- /dev/null +++ b/c/misra/src/rules/DIR-5-1/PossibleDataRaceBetweenThreads.ql @@ -0,0 +1,158 @@ +/** + * @id c/misra/possible-data-race-between-threads + * @name DIR-5-1: There shall be no data races between threads + * @description Threads shall not access the same memory location concurrently without utilization + * of thread synchronization objects. + * @kind problem + * @precision medium + * @problem.severity error + * @tags external/misra/id/dir-5-1 + * correctness + * concurrency + * external/misra/c/2012/amendment4 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.Objects +import codingstandards.c.SubObjects +import codingstandards.cpp.Concurrency + +newtype TNonReentrantOperation = + TReadWrite(SubObject object) { + object.getRootIdentity().getStorageDuration().isStatic() + or + object.getRootIdentity().getStorageDuration().isAllocated() + } or + TStdFunctionCall(FunctionCall call) { + call.getTarget() + .hasName([ + "setlocale", "tmpnam", "rand", "srand", "getenv", "getenv_s", "strok", "strerror", + "asctime", "ctime", "gmtime", "localtime", "mbrtoc16", "c16rtomb", "mbrtoc32", + "c32rtomb", "mbrlen", "mbrtowc", "wcrtomb", "mbsrtowcs", "wcsrtombs" + ]) + } + +class NonReentrantOperation extends TNonReentrantOperation { + string toString() { + exists(SubObject object | + this = TReadWrite(object) and + result = object.toString() + ) + or + exists(FunctionCall call | + this = TStdFunctionCall(call) and + result = call.getTarget().getName() + ) + } + + Expr getARead() { + exists(SubObject object | + this = TReadWrite(object) and + result = object.getAnAccess() + ) + or + this = TStdFunctionCall(result) + } + + Expr getAWrite() { + exists(SubObject object, Assignment assignment | + this = TReadWrite(object) and + result = assignment and + assignment.getLValue() = object.getAnAccess() + ) + or + this = TStdFunctionCall(result) + } + + string getReadString() { + this = TReadWrite(_) and + result = "read operation" + or + this = TStdFunctionCall(_) and + result = "call to non-reentrant function" + } + + string getWriteString() { + this = TReadWrite(_) and + result = "write to object" + or + this = TStdFunctionCall(_) and + result = "call to non-reentrant function" + } + + Element getSourceElement() { + exists(SubObject object | + this = TReadWrite(object) and + result = object.getRootIdentity() + ) + or + this = TStdFunctionCall(result) + } +} + +class WritingThread extends ThreadedFunction { + NonReentrantOperation aWriteObject; + Expr aWrite; + + WritingThread() { + aWrite = aWriteObject.getAWrite() and + this.calls*(aWrite.getEnclosingFunction()) and + not aWrite instanceof LockProtectedControlFlowNode and + not aWrite.getEnclosingFunction().getName().matches(["%init%", "%boot%", "%start%"]) + } + + Expr getAWrite() { result = aWrite } +} + +class ReadingThread extends ThreadedFunction { + Expr aReadExpr; + + ReadingThread() { + exists(NonReentrantOperation op | + aReadExpr = op.getARead() and + this.calls*(aReadExpr.getEnclosingFunction()) and + not aReadExpr instanceof LockProtectedControlFlowNode + ) + } + + Expr getARead() { result = aReadExpr } +} + +predicate mayBeDataRace(Expr write, Expr read, NonReentrantOperation operation) { + exists(WritingThread wt | + wt.getAWrite() = write and + write = operation.getAWrite() and + exists(ReadingThread rt | + read = rt.getARead() and + read = operation.getARead() and + ( + wt.isMultiplySpawned() or + not wt = rt + ) + ) + ) +} + +from + WritingThread wt, ReadingThread rt, Expr write, Expr read, NonReentrantOperation operation, + string message, string writeString, string readString +where + not isExcluded(write, Concurrency9Package::possibleDataRaceBetweenThreadsQuery()) and + mayBeDataRace(write, read, operation) and + wt = min(WritingThread f | f.getAWrite() = write | f order by f.getName()) and + rt = min(ReadingThread f | f.getARead() = read | f order by f.getName()) and + writeString = operation.getWriteString() and + readString = operation.getReadString() and + if wt.isMultiplySpawned() + then + message = + "Threaded " + writeString + + " $@ not synchronized, for example from thread function $@ spawned from a loop." + else + message = + "Threaded " + writeString + + " $@, for example from thread function $@, not synchronized with $@, for example from thread function $@." +select write, message, operation.getSourceElement(), operation.toString(), wt, wt.getName(), read, + "concurrent " + readString, rt, rt.getName() diff --git a/c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql b/c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql index f02891d5d0..f78c25f981 100644 --- a/c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql +++ b/c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql @@ -18,113 +18,61 @@ import codingstandards.c.misra import codingstandards.c.Objects import codingstandards.cpp.Concurrency import codingstandards.cpp.Type +import codingstandards.c.initialization.GlobalInitializationAnalysis -/** A function which is not called or started as a thread */ -class RootFunction extends Function { - RootFunction() { - not exists(Function f | f.calls(this)) and - not this instanceof ThreadedFunction +module MutexInitializationConfig implements GlobalInitializationAnalysisConfigSig { + ObjectIdentity getAnInitializedObject(Expr e) { + e.(C11MutexSource).getMutexExpr() = result.getASubobjectAddressExpr() } -} - -/** A function call which initializes a mutex or a condition */ -class ThreadObjectInitialization extends FunctionCall { - ObjectIdentity owningObject; - ThreadObjectInitialization() { - this.(C11MutexSource).getMutexExpr() = owningObject.getASubobjectAddressExpr() - or - exists(CConditionOperation condOp | - this = condOp and - condOp.isInit() and - condOp.getConditionExpr() = owningObject.getASubobjectAddressExpr() + ObjectIdentity getAUsedObject(Expr e) { + result.getASubobjectAddressExpr() = e and + ( + exists(CMutexFunctionCall mutexUse | e = mutexUse.getLockExpr()) + or + exists(CConditionOperation condOp | e = condOp.getMutexExpr()) ) } - - ObjectIdentity getOwningObject() { result = owningObject } } -/** - * A function argument where that argument is used as a mutex or condition object. - */ -class ThreadObjectUse extends Expr { - ObjectIdentity owningObject; - string typeString; - - ThreadObjectUse() { - owningObject.getASubobjectAddressExpr() = this and - ( - exists(CMutexFunctionCall mutexUse | this = mutexUse.getLockExpr()) and - typeString = "Mutex" - or - exists(CConditionOperation condOp | this = condOp.getMutexExpr()) and - typeString = "Mutex" - or - exists(CConditionOperation condOp | - condOp.isUse() and - this = condOp.getConditionExpr() and - typeString = "Condition" - ) +module ConditionInitializationConfig implements GlobalInitializationAnalysisConfigSig { + ObjectIdentity getAnInitializedObject(Expr e) { + exists(CConditionOperation condOp | + e = condOp and + condOp.isInit() and + condOp.getConditionExpr() = result.getASubobjectAddressExpr() ) } - ObjectIdentity getOwningObject() { result = owningObject } - - string getDescription() { - if - getOwningObject().getType() instanceof PossiblySpecified::Type or - getOwningObject().getType() instanceof PossiblySpecified::Type - then result = typeString - else result = typeString + " in object" + ObjectIdentity getAUsedObject(Expr e) { + result.getASubobjectAddressExpr() = e and + exists(CConditionOperation condOp | + condOp.isUse() and + e = condOp.getConditionExpr() + ) } } -predicate requiresInitializedMutexObject( - Function func, ThreadObjectUse mutexUse, ObjectIdentity owningObject -) { - mutexUse.getEnclosingFunction() = func and - owningObject = mutexUse.getOwningObject() and - not exists(ThreadObjectInitialization init | - init.getEnclosingFunction() = func and - init.getOwningObject() = owningObject and - mutexUse.getAPredecessor+() = init - ) - or - exists(FunctionCall call | - func = call.getEnclosingFunction() and - requiresInitializedMutexObject(call.getTarget(), mutexUse, owningObject) and - not exists(ThreadObjectInitialization init | - call.getAPredecessor*() = init and - init.getOwningObject() = owningObject - ) - ) - or - exists(C11ThreadCreateCall call | - func = call.getEnclosingFunction() and - not owningObject.getStorageDuration().isThread() and - requiresInitializedMutexObject(call.getFunction(), mutexUse, owningObject) and - not exists(ThreadObjectInitialization init | - call.getAPredecessor*() = init and - init.getOwningObject() = owningObject - ) - ) -} +import GlobalInitalizationAnalysis as MutexInitAnalysis +import GlobalInitalizationAnalysis as CondInitAnalysis -from ThreadObjectUse objUse, ObjectIdentity obj, Function callRoot +from Expr objUse, ObjectIdentity obj, Function callRoot, string typeString, string description where not isExcluded(objUse, Concurrency8Package::mutexNotInitializedBeforeUseQuery()) and - obj = objUse.getOwningObject() and - requiresInitializedMutexObject(callRoot, objUse, obj) and ( - if obj.getStorageDuration().isAutomatic() - then obj.getEnclosingElement+() = callRoot - else ( - obj.getStorageDuration().isThread() and callRoot instanceof ThreadedFunction - or - callRoot instanceof RootFunction - ) + MutexInitAnalysis::uninitializedFrom(objUse, obj, callRoot) and + typeString = "Mutex" + or + CondInitAnalysis::uninitializedFrom(objUse, obj, callRoot) and + typeString = "Condition" + ) and + ( + if + obj.getType() instanceof PossiblySpecified::Type or + obj.getType() instanceof PossiblySpecified::Type + then description = typeString + else description = typeString + " in object" ) select objUse, - objUse.getDescription() + - " '$@' possibly used before initialization, from entry point function '$@'.", obj, + description + " '$@' possibly used before initialization, from entry point function '$@'.", obj, obj.toString(), callRoot, callRoot.getName() diff --git a/c/misra/src/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.ql b/c/misra/src/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.ql new file mode 100644 index 0000000000..966b948d81 --- /dev/null +++ b/c/misra/src/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.ql @@ -0,0 +1,113 @@ +/** + * @id c/misra/thread-resource-disposed-before-threads-joined + * @name RULE-22-15: Thread synchronization objects and thread-specific storage pointers shall not be disposed unsafely + * @description Thread synchronization objects and thread-specific storage pointers shall not be + * destroyed until after all threads accessing them have terminated + * @kind problem + * @precision medium + * @problem.severity error + * @tags external/misra/id/rule-22-15 + * correctness + * concurrency + * external/misra/c/2012/amendment4 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.SubObjects +import codingstandards.cpp.Concurrency + +newtype TThreadKind = + TSpawned(C11ThreadCreateCall tcc) or + TMainThread() + +TThreadKind getThreadKind(FunctionCall operation) { + if + not exists(C11ThreadCreateCall tcc | + getAThreadContextAwareSuccessor(tcc.getFunction().getEntryPoint()) = operation + ) + then result = TMainThread() + else + exists(C11ThreadCreateCall tcc | + getAThreadContextAwareSuccessor(tcc.getFunction().getEntryPoint()) = operation and + result = TSpawned(tcc) + ) +} + +bindingset[tcc, thread] +predicate followsMainThreadTcc(C11ThreadCreateCall tcc, TThreadKind thread) { + thread = TMainThread() + or + exists(C11ThreadCreateCall tcc2 | + getAThreadContextAwareSuccessor(tcc) = tcc2 and + thread = TSpawned(tcc2) + ) +} + +string describeThread(TThreadKind thread) { + thread = TMainThread() and + result = "main thread" + or + exists(C11ThreadCreateCall tcc2 | + thread = TSpawned(tcc2) and + result = tcc2.getFunction().getName() + ) +} + +bindingset[alternative] +Element elementOr(TThreadKind thread, Element alternative) { + thread = TMainThread() and + result = alternative + or + exists(C11ThreadCreateCall tcc2 | + thread = TSpawned(tcc2) and + result = tcc2 + ) +} + +from + FunctionCall dispose, FunctionCall use, C11ThreadCreateCall tcc, TThreadKind disposeThread, + TThreadKind useThread, SubObject usedAndDestroyed +where + not isExcluded(dispose, Concurrency9Package::threadResourceDisposedBeforeThreadsJoinedQuery()) and + // `tcc` may be the thread that uses the resource, or the thread that disposes it. What matters + // for the query is that `tcc` is before the use and the dispose. + dispose = getAThreadContextAwareSuccessor(tcc) and + ( + // Lock and dispose of mtx_t: + exists(CMutexFunctionCall mfc, C11MutexDestroyer md | dispose = md and use = mfc | + mfc = getAThreadContextAwareSuccessor(tcc) and + mfc.getLockExpr() = usedAndDestroyed.getAnAddressOfExpr() and + md.getMutexExpr() = usedAndDestroyed.getAnAddressOfExpr() + ) + or + // Read/store and dispose of tss_t: + exists(ThreadSpecificStorageFunctionCall tssfc, TSSDeleteFunctionCall td | + dispose = td and use = tssfc + | + tssfc = getAThreadContextAwareSuccessor(tcc) and + tssfc.getKey() = usedAndDestroyed.getAnAddressOfExpr() and + td.getKey() = usedAndDestroyed.getAnAddressOfExpr() + ) + or + // Wait and dispose of cnd_t: + exists(CConditionOperation cndop, C11ConditionDestroyer cd | dispose = cd and use = cndop | + cndop = getAThreadContextAwareSuccessor(tcc) and + cndop.getConditionExpr() = usedAndDestroyed.getAnAddressOfExpr() and + cd.getConditionExpr() = usedAndDestroyed.getAnAddressOfExpr() + ) + ) and + // Dispose could be in the main thread or in a spawned thread. + disposeThread = getThreadKind(dispose) and + // Dispose could be in the main thread or in a spawned thread. + useThread = getThreadKind(use) and + // Exclude a thread that does not concurrently share the resource it disposed (unlikely). + not useThread = disposeThread and + followsMainThreadTcc(tcc, useThread) and + followsMainThreadTcc(tcc, disposeThread) and + // If there is a join between the use and the dispose, the code is compliant. + not getAThreadContextAwarePredecessor(elementOr(useThread, use), dispose) instanceof C11ThreadWait +select dispose, "Thread resource $@ disposed before joining thread $@ which uses it.", + usedAndDestroyed.getRootIdentity(), usedAndDestroyed.toString(), elementOr(useThread, use), + describeThread(useThread) diff --git a/c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql b/c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql new file mode 100644 index 0000000000..7c0b86f145 --- /dev/null +++ b/c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql @@ -0,0 +1,68 @@ +/** + * @id c/misra/invalid-operation-on-unlocked-mutex + * @name RULE-22-17: No thread shall unlock a mutex or call cnd_wait() or cnd_timedwait() for a mutex it has not locked + * @description No thread shall unlock a mutex or call cnd_wait() or cnd_timedwait() for a mutex it + * has not locked before. + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-22-17 + * correctness + * concurrency + * external/misra/c/2012/amendment4 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.SubObjects +import codingstandards.cpp.Concurrency +import codingstandards.cpp.dominance.BehavioralSet +import semmle.code.cpp.dataflow.new.DataFlow::DataFlow as NewDF + +/* A call to mtx_unlock() or cnd_wait() or cnd_timedwait(), which require a locked mutex */ +class RequiresLockOperation extends FunctionCall { + SubObject mutex; + + RequiresLockOperation() { + exists(CMutexFunctionCall mutexCall | this = mutexCall | + mutexCall.isUnlock() and + mutex.getAnAddressOfExpr() = mutexCall.getLockExpr() + ) + or + exists(CConditionOperation condOp | this = condOp | + mutex.getAnAddressOfExpr() = condOp.getMutexExpr() + ) + } + + SubObject getMutex() { result = mutex } +} + +/* A config to search for a dominating set that locks the mutex before the operation */ +module LockDominatingSetConfig implements DominatingSetConfigSig { + predicate isTargetBehavior(ControlFlowNode node, RequiresLockOperation op) { + exists(CMutexFunctionCall mutexCall | node = mutexCall | + mutexCall.isLock() and + mutexCall.getLockExpr() = op.getMutex().getAnAddressOfExpr() + ) + } + + predicate isBlockingBehavior(ControlFlowNode node, RequiresLockOperation op) { + // If we find a branch that explicitly unlocks the mutex, we should not look for an earlier + // call to lock that mutex. + exists(CMutexFunctionCall mutexCall | node = mutexCall | + mutexCall.isUnlock() and + mutexCall.getLockExpr() = op.getMutex().getAnAddressOfExpr() + ) + } +} + +import DominatingBehavioralSet as DominatingSet + +from RequiresLockOperation operation, SubObject mutex +where + not isExcluded(operation, Concurrency9Package::invalidOperationOnUnlockedMutexQuery()) and + mutex = operation.getMutex() and + not DominatingSet::isDominatedByBehavior(operation) +select operation, "Invalid operation on mutex '$@' not locked by the current thread", + mutex.getRootIdentity(), mutex.toString() diff --git a/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.ql b/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.ql new file mode 100644 index 0000000000..17762b3eee --- /dev/null +++ b/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.ql @@ -0,0 +1,37 @@ +/** + * @id c/misra/non-recursive-mutex-recursively-locked + * @name RULE-22-18: Non-recursive mutexes shall not be recursively locked + * @description Mutexes initialized with mtx_init() without mtx_recursive shall not be locked by a + * thread that has previously locked it. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-22-18 + * correctness + * concurrency + * external/misra/c/2012/amendment4 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.SubObjects +import codingstandards.cpp.Concurrency +import codingstandards.cpp.Type + +from + LockProtectedControlFlowNode n, CMutexFunctionCall lockCall, SubObject mutex, + CMutexFunctionCall coveredByLock +where + not isExcluded(n, Concurrency9Package::nonRecursiveMutexRecursivelyLockedQuery()) and + lockCall = n and + coveredByLock = n.coveredByLock() and + not coveredByLock = lockCall and + mutex.isPrecise() and + coveredByLock.getLockExpr() = mutex.getAnAddressOfExpr() and + lockCall.getLockExpr() = mutex.getAnAddressOfExpr() and + forex(C11MutexSource init | init.getMutexExpr() = mutex.getAnAddressOfExpr() | + not init.isRecursive() + ) +select n, "Non-recursive mutex " + mutex.toString() + " locked after it is $@.", coveredByLock, + "already locked" diff --git a/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql b/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql new file mode 100644 index 0000000000..5b848f9e1e --- /dev/null +++ b/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql @@ -0,0 +1,60 @@ +/** + * @id c/misra/non-recursive-mutex-recursively-locked-audit + * @name RULE-22-18: (Audit) Non-recursive mutexes shall not be recursively locked + * @description Mutex that may be initialized without mtx_recursive shall not be locked by a thread + * that has previous may havec locked it. + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-22-18 + * correctness + * concurrency + * external/misra/c/2012/amendment4 + * audit + * external/misra/obligation/required + */ + +import cpp +import codeql.util.Boolean +import codingstandards.c.misra +import codingstandards.c.SubObjects +import codingstandards.cpp.Concurrency +import codingstandards.cpp.Type + +predicate isTrackableMutex(CMutexFunctionCall lockCall, Boolean recursive) { + exists(SubObject mutex | + lockCall.getLockExpr() = mutex.getAnAddressOfExpr() and + mutex.isPrecise() and + forex(C11MutexSource init | init.getMutexExpr() = mutex.getAnAddressOfExpr() | + if init.isRecursive() then recursive = true else recursive = false + ) + ) +} + +predicate definitelyDifferentMutexes(CMutexFunctionCall lockCall, CMutexFunctionCall coveredByLock) { + exists(SubObject a, SubObject b | + lockCall.getLockExpr() = a.getAnAddressOfExpr() and + coveredByLock.getLockExpr() = b.getAnAddressOfExpr() and + not a = b + ) +} + +from LockProtectedControlFlowNode n, CMutexFunctionCall lockCall, CMutexFunctionCall coveredByLock +where + not isExcluded(n, Concurrency9Package::nonRecursiveMutexRecursivelyLockedAuditQuery()) and + lockCall = n and + coveredByLock = n.coveredByLock() and + not coveredByLock = lockCall and + // If mutexes are provably different objects, they do not need to be audited + not definitelyDifferentMutexes(lockCall, coveredByLock) and + ( + // If either mutex is not trackable, it should be audited + not isTrackableMutex(lockCall, _) or + not isTrackableMutex(coveredByLock, _) + ) and + not ( + // If either mutex is definitely recursive, it does not need to be audited + isTrackableMutex(lockCall, true) or + isTrackableMutex(coveredByLock, true) + ) +select n, "Mutex locked after previous $@.", coveredByLock, "already locked" diff --git a/c/misra/src/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.ql b/c/misra/src/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.ql new file mode 100644 index 0000000000..afa2556646 --- /dev/null +++ b/c/misra/src/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.ql @@ -0,0 +1,69 @@ +/** + * @id c/misra/condition-variable-used-with-multiple-mutexes + * @name RULE-22-19: A condition variable shall be associated with at most one mutex object + * @description Standard library functions cnd_wait() and cnd_timedwait() shall specify the same + * mutex object for each condition object in all calls. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-22-19 + * correctness + * concurrency + * external/misra/c/2012/amendment4 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.SubObjects +import codingstandards.cpp.Concurrency + +bindingset[cond, mutex] +int countMutexesForConditionVariable(SubObject cond, SubObject mutex) { + result = + count(CConditionOperation call | + call.getConditionExpr() = cond.getAnAddressOfExpr() and + call.getMutexExpr() = mutex.getAnAddressOfExpr() + ) +} + +bindingset[cond, mutex] +predicate conditionVariableUsesMutex(SubObject cond, SubObject mutex) { + countMutexesForConditionVariable(cond, mutex) > 0 +} + +bindingset[cond, n] +SubObject nthMutexForConditionVariable(SubObject cond, int n) { + result = + rank[n](SubObject mutex | + conditionVariableUsesMutex(cond, mutex) + | + mutex order by countMutexesForConditionVariable(cond, mutex), mutex.toString() + ) +} + +bindingset[cond, mutex] +CConditionOperation firstCallForConditionMutex(SubObject cond, SubObject mutex) { + result = + rank[1](CConditionOperation call | + call.getConditionExpr() = cond.getAnAddressOfExpr() and + call.getMutexExpr() = mutex.getAnAddressOfExpr() + | + call order by call.getFile().getAbsolutePath(), call.getLocation().getStartLine() + ) +} + +from + SubObject cond, CConditionOperation useOne, SubObject mutexOne, CConditionOperation useTwo, + SubObject mutexTwo +where + not isExcluded(cond.getRootIdentity(), + Concurrency9Package::conditionVariableUsedWithMultipleMutexesQuery()) and + mutexOne = nthMutexForConditionVariable(cond, 1) and + mutexTwo = nthMutexForConditionVariable(cond, 2) and + useOne = firstCallForConditionMutex(cond, mutexOne) and + useTwo = firstCallForConditionMutex(cond, mutexOne) +select useOne, + "Condition variable $@ associated with multiple mutexes, operation uses mutex $@ while $@ uses other mutex $@", + cond.getRootIdentity(), cond.toString(), mutexOne.getRootIdentity(), mutexOne.toString(), useTwo, + "another operation", mutexTwo.getRootIdentity(), mutexTwo.toString() diff --git a/c/misra/src/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.ql b/c/misra/src/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.ql new file mode 100644 index 0000000000..652b5d1f8c --- /dev/null +++ b/c/misra/src/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.ql @@ -0,0 +1,44 @@ +/** + * @id c/misra/thread-storage-not-initialized-before-use + * @name RULE-22-20: Thread-specific storage pointers shall be created before being accessed + * @description Thread specific storage pointers shall be initialized with the standard library + * functions before using them. + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-22-20 + * correctness + * concurrency + * external/misra/c/2012/amendment4 + * external/misra/obligation/mandatory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.Objects +import codingstandards.cpp.Concurrency +import codingstandards.cpp.Type +import codingstandards.c.initialization.GlobalInitializationAnalysis + +module ThreadStoreInitializationConfig implements GlobalInitializationAnalysisConfigSig { + ObjectIdentity getAnInitializedObject(Expr e) { + e.(TSSCreateFunctionCall).getKey() = result.getASubobjectAddressExpr() + } + + ObjectIdentity getAUsedObject(Expr e) { + result.getASubobjectAddressExpr() = e and + exists(ThreadSpecificStorageFunctionCall use | + not use instanceof TSSCreateFunctionCall and e = use.getKey() + ) + } +} + +import GlobalInitalizationAnalysis as InitAnalysis + +from Expr objUse, ObjectIdentity obj, Function callRoot +where + not isExcluded(objUse, Concurrency9Package::threadStorageNotInitializedBeforeUseQuery()) and + InitAnalysis::uninitializedFrom(objUse, obj, callRoot) +select objUse, + "Thread specific storage pointer '$@' possibly used before initialization, from entry point function '$@'.", + obj, obj.toString(), callRoot, callRoot.getName() diff --git a/c/misra/src/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.ql b/c/misra/src/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.ql new file mode 100644 index 0000000000..3c40ea7116 --- /dev/null +++ b/c/misra/src/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.ql @@ -0,0 +1,27 @@ +/** + * @id c/misra/thread-storage-pointer-initialized-inside-thread + * @name RULE-22-20: Thread specific storage pointers shall be initialized deterministically + * @description Thread specific storage pointers initialized inside of threads may result in + * indeterministic state. + * @kind problem + * @precision very-high + * @problem.severity recommendation + * @tags external/misra/id/rule-22-20 + * readability + * maintainability + * concurrency + * external/misra/c/2012/amendment4 + * external/misra/obligation/mandatory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.Concurrency + +from TSSCreateFunctionCall tssCreate, ThreadedFunction thread +where + not isExcluded(tssCreate, Concurrency8Package::mutexInitializedInsideThreadQuery()) and + thread.calls*(tssCreate.getEnclosingFunction()) +select tssCreate, + "Thread specific storage object initialization reachable from threaded function '$@'.", thread, + thread.getName() diff --git a/c/misra/test/rules/DIR-5-1/PossibleDataRaceBetweenThreads.expected b/c/misra/test/rules/DIR-5-1/PossibleDataRaceBetweenThreads.expected new file mode 100644 index 0000000000..3f32b09d5c --- /dev/null +++ b/c/misra/test/rules/DIR-5-1/PossibleDataRaceBetweenThreads.expected @@ -0,0 +1,24 @@ +| test.c:31:3:31:8 | ... = ... | Threaded write to object $@, for example from thread function $@, not synchronized with $@, for example from thread function $@. | test.c:11:5:11:6 | g2 | g2 | test.c:30:6:30:29 | single_thread4_writes_g2 | single_thread4_writes_g2 | test.c:27:3:27:4 | g2 | concurrent read operation | test.c:26:6:26:28 | single_thread3_reads_g2 | single_thread3_reads_g2 | +| test.c:35:3:35:8 | ... = ... | Threaded write to object $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:12:5:12:6 | g3 | g3 | test.c:34:6:34:27 | many_thread5_writes_g3 | many_thread5_writes_g3 | test.c:35:3:35:4 | g3 | concurrent read operation | test.c:34:6:34:27 | many_thread5_writes_g3 | many_thread5_writes_g3 | +| test.c:71:3:71:11 | ... = ... | Threaded write to object $@, for example from thread function $@, not synchronized with $@, for example from thread function $@. | test.c:68:3:68:4 | g7 | g7.m1 | test.c:70:6:70:33 | single_thread11_writes_g7_m1 | single_thread11_writes_g7_m1 | test.c:75:6:75:7 | m1 | concurrent read operation | test.c:74:6:74:33 | single_thread12_writes_g7_m1 | single_thread12_writes_g7_m1 | +| test.c:75:3:75:11 | ... = ... | Threaded write to object $@, for example from thread function $@, not synchronized with $@, for example from thread function $@. | test.c:68:3:68:4 | g7 | g7.m1 | test.c:74:6:74:33 | single_thread12_writes_g7_m1 | single_thread12_writes_g7_m1 | test.c:71:6:71:7 | m1 | concurrent read operation | test.c:70:6:70:33 | single_thread11_writes_g7_m1 | single_thread11_writes_g7_m1 | +| test.c:79:3:79:11 | call to setlocale | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:79:3:79:11 | call to setlocale | setlocale | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:79:3:79:11 | call to setlocale | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:80:3:80:8 | call to tmpnam | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:80:3:80:8 | call to tmpnam | tmpnam | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:80:3:80:8 | call to tmpnam | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:81:3:81:6 | call to rand | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:81:3:81:6 | call to rand | rand | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:81:3:81:6 | call to rand | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:82:3:82:7 | call to srand | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:82:3:82:7 | call to srand | srand | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:82:3:82:7 | call to srand | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:83:3:83:8 | call to getenv | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:83:3:83:8 | call to getenv | getenv | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:83:3:83:8 | call to getenv | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:84:3:84:10 | call to getenv_s | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:84:3:84:10 | call to getenv_s | getenv_s | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:84:3:84:10 | call to getenv_s | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:86:3:86:10 | call to strerror | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:86:3:86:10 | call to strerror | strerror | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:86:3:86:10 | call to strerror | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:87:3:87:9 | call to asctime | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:87:3:87:9 | call to asctime | asctime | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:87:3:87:9 | call to asctime | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:88:3:88:7 | call to ctime | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:88:3:88:7 | call to ctime | ctime | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:88:3:88:7 | call to ctime | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:89:3:89:8 | call to gmtime | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:89:3:89:8 | call to gmtime | gmtime | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:89:3:89:8 | call to gmtime | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:90:3:90:11 | call to localtime | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:90:3:90:11 | call to localtime | localtime | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:90:3:90:11 | call to localtime | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:91:3:91:10 | call to mbrtoc16 | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:91:3:91:10 | call to mbrtoc16 | mbrtoc16 | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:91:3:91:10 | call to mbrtoc16 | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:92:3:92:10 | call to mbrtoc32 | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:92:3:92:10 | call to mbrtoc32 | mbrtoc32 | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:92:3:92:10 | call to mbrtoc32 | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:93:3:93:10 | call to c16rtomb | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:93:3:93:10 | call to c16rtomb | c16rtomb | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:93:3:93:10 | call to c16rtomb | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:94:3:94:10 | call to c32rtomb | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:94:3:94:10 | call to c32rtomb | c32rtomb | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:94:3:94:10 | call to c32rtomb | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:95:3:95:8 | call to mbrlen | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:95:3:95:8 | call to mbrlen | mbrlen | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:95:3:95:8 | call to mbrlen | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:96:3:96:9 | call to mbrtowc | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:96:3:96:9 | call to mbrtowc | mbrtowc | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:96:3:96:9 | call to mbrtowc | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:97:3:97:9 | call to wcrtomb | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:97:3:97:9 | call to wcrtomb | wcrtomb | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:97:3:97:9 | call to wcrtomb | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:98:3:98:11 | call to mbsrtowcs | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:98:3:98:11 | call to mbsrtowcs | mbsrtowcs | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:98:3:98:11 | call to mbsrtowcs | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:99:3:99:11 | call to wcsrtombs | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:99:3:99:11 | call to wcsrtombs | wcsrtombs | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:99:3:99:11 | call to wcsrtombs | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | diff --git a/c/misra/test/rules/DIR-5-1/PossibleDataRaceBetweenThreads.qlref b/c/misra/test/rules/DIR-5-1/PossibleDataRaceBetweenThreads.qlref new file mode 100644 index 0000000000..737cf79505 --- /dev/null +++ b/c/misra/test/rules/DIR-5-1/PossibleDataRaceBetweenThreads.qlref @@ -0,0 +1 @@ +rules/DIR-5-1/PossibleDataRaceBetweenThreads.ql \ No newline at end of file diff --git a/c/misra/test/rules/DIR-5-1/test.c b/c/misra/test/rules/DIR-5-1/test.c new file mode 100644 index 0000000000..5e568cc95c --- /dev/null +++ b/c/misra/test/rules/DIR-5-1/test.c @@ -0,0 +1,132 @@ +#include "locale.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "threads.h" +#include "time.h" +#include "uchar.h" +#include "wchar.h" + +int g1; +int g2; +int g3; +int g4; +mtx_t g4_lock; +int g5; +mtx_t g5_lock; + +void single_thread1_reads_g1(void *p) { + g1; // COMPLIANT +} + +void many_thread2_reads_g1(void *p) { + g1; // COMPLIANT +} + +void single_thread3_reads_g2(void *p) { + g2; // COMPLIANT +} + +void single_thread4_writes_g2(void *p) { + g2 = 1; // NON-COMPLIANT +} + +void many_thread5_writes_g3(void *p) { + g3 = 1; // NON-COMPLIANT +} + +void single_thread6_reads_g4_locked(void *p) { + mtx_lock(&g4_lock); + g4; // COMPLIANT +} + +void single_thread7_writes_g4_locked(void *p) { + mtx_lock(&g4_lock); + g4 = 1; // COMPLIANT +} + +void many_thread8_writes_g5_locked(void *p) { + mtx_lock(&g5_lock); + g5 = 1; // COMPLIANT +} + +struct { + int m1; + int m2; +} g6; + +void single_thread9_writes_g6_m1(void *p) { + g6.m1 = 1; // COMPLIANT +} + +void single_thread10_writes_g6_m2(void *p) { + g6.m2 = 1; // COMPLIANT +} + +struct { + int m1; +} g7; + +void single_thread11_writes_g7_m1(void *p) { + g7.m1 = 1; // NON-COMPLIANT +} + +void single_thread12_writes_g7_m1(void *p) { + g7.m1 = 1; // NON-COMPLIANT +} + +void many_thread13_calls_nonreentrant_funcs(void *p) { + setlocale(LC_ALL, "C"); // NON-COMPLIANT + tmpnam(""); // NON-COMPLIANT + rand(); // NON-COMPLIANT + srand(0); // NON-COMPLIANT + getenv("PATH"); // NON-COMPLIANT + getenv_s(NULL, NULL, 0, NULL); // NON-COMPLIANT + strtok("a", "b"); // NON-COMPLIANT + strerror(0); // NON-COMPLIANT + asctime(NULL); // NON-COMPLIANT + ctime(NULL); // NON-COMPLIANT + gmtime(NULL); // NON-COMPLIANT + localtime(NULL); // NON-COMPLIANT + mbrtoc16(NULL, NULL, 0, NULL); // NON-COMPLIANT + mbrtoc32(NULL, NULL, 0, NULL); // NON-COMPLIANT + c16rtomb(NULL, 0, NULL); // NON-COMPLIANT + c32rtomb(NULL, 0, NULL); // NON-COMPLIANT + mbrlen(NULL, 0, NULL); // NON-COMPLIANT + mbrtowc(NULL, NULL, 0, NULL); // NON-COMPLIANT + wcrtomb(NULL, 0, NULL); // NON-COMPLIANT + mbsrtowcs(NULL, NULL, 0, NULL); // NON-COMPLIANT + wcsrtombs(NULL, NULL, 0, NULL); // NON-COMPLIANT +} + +void main() { + thrd_t single_thread1; + thrd_t many_thread2; + thrd_t single_thread3; + thrd_t single_thread4; + thrd_t many_thread5; + thrd_t single_thread6; + thrd_t single_thread7; + thrd_t many_thread8; + thrd_t single_thread9; + thrd_t single_thread10; + thrd_t single_thread11; + thrd_t single_thread12; + thrd_t many_thread13; + + thrd_create(&single_thread1, single_thread1_reads_g1, NULL); + thrd_create(&single_thread3, single_thread3_reads_g2, NULL); + thrd_create(&single_thread4, single_thread4_writes_g2, NULL); + thrd_create(&single_thread6, single_thread6_reads_g4_locked, NULL); + thrd_create(&single_thread7, single_thread7_writes_g4_locked, NULL); + thrd_create(&single_thread9, single_thread9_writes_g6_m1, NULL); + thrd_create(&single_thread10, single_thread10_writes_g6_m2, NULL); + thrd_create(&single_thread11, single_thread11_writes_g7_m1, NULL); + thrd_create(&single_thread12, single_thread12_writes_g7_m1, NULL); + for (;;) { + thrd_create(&many_thread2, many_thread2_reads_g1, NULL); + thrd_create(&many_thread5, many_thread5_writes_g3, NULL); + thrd_create(&many_thread8, many_thread8_writes_g5_locked, NULL); + thrd_create(&many_thread13, many_thread13_calls_nonreentrant_funcs, NULL); + } +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.expected b/c/misra/test/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.expected new file mode 100644 index 0000000000..49f1b74c15 --- /dev/null +++ b/c/misra/test/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.expected @@ -0,0 +1,12 @@ +| test.c:16:3:16:13 | call to mtx_destroy | Thread resource $@ disposed before joining thread $@ which uses it. | test.c:3:7:3:8 | g1 | g1 | test.c:64:3:64:13 | call to thrd_create | t2_use_all | +| test.c:16:3:16:13 | call to mtx_destroy | Thread resource $@ disposed before joining thread $@ which uses it. | test.c:3:7:3:8 | g1 | g1 | test.c:72:3:72:13 | call to thrd_create | t2_use_all | +| test.c:16:3:16:13 | call to mtx_destroy | Thread resource $@ disposed before joining thread $@ which uses it. | test.c:3:7:3:8 | g1 | g1 | test.c:91:3:91:10 | call to mtx_lock | main thread | +| test.c:17:3:17:12 | call to tss_delete | Thread resource $@ disposed before joining thread $@ which uses it. | test.c:4:7:4:8 | g2 | g2 | test.c:64:3:64:13 | call to thrd_create | t2_use_all | +| test.c:17:3:17:12 | call to tss_delete | Thread resource $@ disposed before joining thread $@ which uses it. | test.c:4:7:4:8 | g2 | g2 | test.c:72:3:72:13 | call to thrd_create | t2_use_all | +| test.c:17:3:17:12 | call to tss_delete | Thread resource $@ disposed before joining thread $@ which uses it. | test.c:4:7:4:8 | g2 | g2 | test.c:92:3:92:9 | call to tss_get | main thread | +| test.c:18:3:18:13 | call to cnd_destroy | Thread resource $@ disposed before joining thread $@ which uses it. | test.c:5:7:5:8 | g3 | g3 | test.c:64:3:64:13 | call to thrd_create | t2_use_all | +| test.c:18:3:18:13 | call to cnd_destroy | Thread resource $@ disposed before joining thread $@ which uses it. | test.c:5:7:5:8 | g3 | g3 | test.c:72:3:72:13 | call to thrd_create | t2_use_all | +| test.c:18:3:18:13 | call to cnd_destroy | Thread resource $@ disposed before joining thread $@ which uses it. | test.c:5:7:5:8 | g3 | g3 | test.c:93:3:93:10 | call to cnd_wait | main thread | +| test.c:42:3:42:13 | call to mtx_destroy | Thread resource $@ disposed before joining thread $@ which uses it. | test.c:3:7:3:8 | g1 | g1 | test.c:41:3:41:13 | call to thrd_create | t2_use_all | +| test.c:43:3:43:12 | call to tss_delete | Thread resource $@ disposed before joining thread $@ which uses it. | test.c:4:7:4:8 | g2 | g2 | test.c:41:3:41:13 | call to thrd_create | t2_use_all | +| test.c:44:3:44:13 | call to cnd_destroy | Thread resource $@ disposed before joining thread $@ which uses it. | test.c:5:7:5:8 | g3 | g3 | test.c:41:3:41:13 | call to thrd_create | t2_use_all | diff --git a/c/misra/test/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.qlref b/c/misra/test/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.qlref new file mode 100644 index 0000000000..809eae6faf --- /dev/null +++ b/c/misra/test/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.qlref @@ -0,0 +1 @@ +rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-15/test.c b/c/misra/test/rules/RULE-22-15/test.c new file mode 100644 index 0000000000..7679730fc9 --- /dev/null +++ b/c/misra/test/rules/RULE-22-15/test.c @@ -0,0 +1,113 @@ +#include "threads.h" + +mtx_t g1; +tss_t g2; +cnd_t g3; + +int t1_use_none(void *p) { return 0; } + +int t2_use_all(void *p) { + mtx_lock(&g1); + tss_get(&g2); + cnd_wait(&g3, &g1); +} + +int t3_dispose_all(void *p) { + mtx_destroy(&g1); + tss_delete(&g2); + cnd_destroy(&g3); +} + +int t4_use_then_dispose(void *p) { + mtx_lock(&g1); + tss_get(&g2); + cnd_wait(&g3, &g1); + + mtx_destroy(&g1); + tss_delete(&g2); + cnd_destroy(&g3); +} + +void f1() { + thrd_t t; + thrd_create(&t, t1_use_none, NULL); + mtx_destroy(&g1); + tss_delete(&g2); + cnd_destroy(&g3); +} + +void f2() { + thrd_t t; + thrd_create(&t, t2_use_all, NULL); + mtx_destroy(&g1); // NON-COMPLIANT + tss_delete(&g2); // NON-COMPLIANT + cnd_destroy(&g3); // NON-COMPLIANT +} + +void f3() { + thrd_t t; + thrd_create(&t, t2_use_all, NULL); // COMPLIANT +} + +void f4() { + thrd_t t; + thrd_create(&t, t2_use_all, NULL); // COMPLIANT + thrd_join(&t, NULL); + mtx_destroy(&g1); // COMPLIANT + tss_delete(&g2); // COMPLIANT + cnd_destroy(&g3); // COMPLIANT +} + +void f5() { + thrd_t t1; + thrd_t t2; + thrd_create(&t1, t2_use_all, NULL); // COMPLIANT + thrd_create(&t2, t3_dispose_all, NULL); // NON-COMPLIANT +} + +void f6() { + thrd_t t1; + thrd_t t2; + thrd_create(&t1, t3_dispose_all, NULL); // NON-COMPLIANT + thrd_create(&t2, t2_use_all, NULL); // COMPLIANT +} + +void f7() { + thrd_t t1; + thrd_t t2; + thrd_create(&t1, t2_use_all, NULL); // COMPLIANT + thrd_join(&t1, NULL); + thrd_create(&t2, t3_dispose_all, NULL); // COMPLIANT +} + +void f8() { + thrd_t t; + thrd_create(&t, t4_use_then_dispose, NULL); // COMPLIANT +} + +void f9() { + thrd_t t; + thrd_create(&t, t3_dispose_all, NULL); // NON-COMPLIANT + mtx_lock(&g1); + tss_get(&g2); + cnd_wait(&g3, &g1); +} + +void f10() { + thrd_t t; + mtx_lock(&g1); + tss_get(&g2); + cnd_wait(&g3, &g1); + thrd_create(&t, t3_dispose_all, NULL); // COMPLIANT +} + +void f11() { + thrd_t t; + thrd_create(&t, t1_use_none, NULL); + mtx_lock(&g1); + tss_get(&g2); + cnd_wait(&g3, &g1); + mtx_destroy(&g1); // COMPLIANT + tss_delete(&g2); // COMPLIANT + cnd_destroy(&g3); // COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.expected b/c/misra/test/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.expected new file mode 100644 index 0000000000..76d3ac1ba1 --- /dev/null +++ b/c/misra/test/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.expected @@ -0,0 +1,16 @@ +| test.c:19:3:19:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:11:9:11:10 | l1 | l1 | +| test.c:20:3:20:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:11:9:11:10 | l1 | l1 | +| test.c:25:3:25:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:14:5:14:6 | l2 | l2.m1 | +| test.c:26:3:26:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:14:5:14:6 | l2 | l2.m1 | +| test.c:31:3:31:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:3:7:3:8 | g1 | g1 | +| test.c:32:3:32:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:3:7:3:8 | g1 | g1 | +| test.c:37:3:37:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:6:3:6:4 | g2 | g2.m1 | +| test.c:38:3:38:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:6:3:6:4 | g2 | g2.m1 | +| test.c:47:3:47:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:11:9:11:10 | l1 | l1 | +| test.c:48:3:48:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:14:5:14:6 | l2 | l2.m1 | +| test.c:49:3:49:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:3:7:3:8 | g1 | g1 | +| test.c:50:3:50:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:6:3:6:4 | g2 | g2.m1 | +| test.c:51:3:51:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:11:9:11:10 | l1 | l1 | +| test.c:52:3:52:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:14:5:14:6 | l2 | l2.m1 | +| test.c:53:3:53:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:3:7:3:8 | g1 | g1 | +| test.c:54:3:54:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:6:3:6:4 | g2 | g2.m1 | diff --git a/c/misra/test/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.qlref b/c/misra/test/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.qlref new file mode 100644 index 0000000000..4ac06f10ed --- /dev/null +++ b/c/misra/test/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.qlref @@ -0,0 +1 @@ +rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-17/test.c b/c/misra/test/rules/RULE-22-17/test.c new file mode 100644 index 0000000000..fc841bb3e1 --- /dev/null +++ b/c/misra/test/rules/RULE-22-17/test.c @@ -0,0 +1,70 @@ +#include "threads.h" + +mtx_t g1; +struct { + mtx_t m1; +} g2; + +cnd_t cnd; + +void f1(int p) { + mtx_t l1; + struct { + mtx_t m1; + } l2; + + mtx_lock(&l1); + cnd_wait(&cnd, &l1); // COMPLIANT + mtx_unlock(&l1); // COMPLIANT + cnd_wait(&cnd, &l1); // NON-COMPLIANT + mtx_unlock(&l1); // NON-COMPLIANT + + mtx_lock(&l2.m1); + cnd_wait(&cnd, &l2.m1); // COMPLIANT + mtx_unlock(&l2.m1); // COMPLIANT + cnd_wait(&cnd, &l2.m1); // NON-COMPLIANT + mtx_unlock(&l2.m1); // NON-COMPLIANT + + mtx_lock(&g1); + cnd_wait(&cnd, &g1); // COMPLIANT + mtx_unlock(&g1); // COMPLIANT + cnd_wait(&cnd, &g1); // NON-COMPLIANT + mtx_unlock(&g1); // NON-COMPLIANT + + mtx_lock(&g2.m1); + cnd_wait(&cnd, &g2.m1); // COMPLIANT + mtx_unlock(&g2.m1); // COMPLIANT + cnd_wait(&cnd, &g2.m1); // NON-COMPLIANT + mtx_unlock(&g2.m1); // NON-COMPLIANT + + // We should report when a mutex is unlocked in the wrong block: + if (p) { + mtx_lock(&l1); + mtx_lock(&l2.m1); + mtx_lock(&g1); + mtx_lock(&g2.m1); + } + cnd_wait(&cnd, &l1); // NON-COMPLIANT + cnd_wait(&cnd, &l2.m1); // NON-COMPLIANT + cnd_wait(&cnd, &g1); // NON-COMPLIANT + cnd_wait(&cnd, &g2.m1); // NON-COMPLIANT + mtx_unlock(&l1); // NON-COMPLIANT + mtx_unlock(&l2.m1); // NON-COMPLIANT + mtx_unlock(&g1); // NON-COMPLIANT + mtx_unlock(&g2.m1); // NON-COMPLIANT + + // The above requires dominance analysis. Check dominator sets don't cause + // false positives: + if (p) { + mtx_lock(&l1); + } else { + mtx_lock(&l1); + } + mtx_unlock(&l1); // COMPLIANT + + // Invalid but satisfies the rule: + mtx_lock(&l1); + if (p) { + mtx_unlock(&l1); // COMPLIANT + } +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.expected b/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.expected new file mode 100644 index 0000000000..fd947dee51 --- /dev/null +++ b/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.expected @@ -0,0 +1,2 @@ +| test.c:19:3:19:10 | call to mtx_lock | Non-recursive mutex nonrec locked after it is $@. | test.c:18:3:18:10 | call to mtx_lock | already locked | +| test.c:22:3:22:10 | call to mtx_lock | Non-recursive mutex s.m locked after it is $@. | test.c:21:3:21:10 | call to mtx_lock | already locked | diff --git a/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.qlref b/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.qlref new file mode 100644 index 0000000000..131e0476bf --- /dev/null +++ b/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.qlref @@ -0,0 +1 @@ +rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.expected b/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.expected new file mode 100644 index 0000000000..8f359c90f8 --- /dev/null +++ b/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.expected @@ -0,0 +1,6 @@ +| test.c:44:3:44:10 | call to mtx_lock | Mutex locked after previous $@. | test.c:43:3:43:10 | call to mtx_lock | already locked | +| test.c:49:3:49:10 | call to mtx_lock | Mutex locked after previous $@. | test.c:48:3:48:10 | call to mtx_lock | already locked | +| test.c:54:3:54:10 | call to mtx_lock | Mutex locked after previous $@. | test.c:53:3:53:10 | call to mtx_lock | already locked | +| test.c:59:3:59:10 | call to mtx_lock | Mutex locked after previous $@. | test.c:58:3:58:10 | call to mtx_lock | already locked | +| test.c:76:3:76:10 | call to mtx_lock | Mutex locked after previous $@. | test.c:75:3:75:10 | call to mtx_lock | already locked | +| test.c:81:3:81:10 | call to mtx_lock | Mutex locked after previous $@. | test.c:80:3:80:10 | call to mtx_lock | already locked | diff --git a/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.qlref b/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.qlref new file mode 100644 index 0000000000..77a81deb69 --- /dev/null +++ b/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.qlref @@ -0,0 +1 @@ +rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-18/test.c b/c/misra/test/rules/RULE-22-18/test.c new file mode 100644 index 0000000000..f71066b1bc --- /dev/null +++ b/c/misra/test/rules/RULE-22-18/test.c @@ -0,0 +1,122 @@ +#include "threads.h" + +mtx_t rec; +mtx_t nonrec; +mtx_t both; +mtx_t unknown; + +struct { + mtx_t m; +} s; + +mtx_t arr[2]; + +int t1(void *arg) { + mtx_lock(&rec); // COMPLIANT + mtx_lock(&rec); // COMPLIANT + + mtx_lock(&nonrec); // COMPLIANT + mtx_lock(&nonrec); // NON-COMPLIANT + + mtx_lock(&s.m); // COMPLIANT + mtx_lock(&s.m); // NON-COMPLIANT +} + +void f1() { + mtx_init(&rec, mtx_plain | mtx_recursive); + mtx_init(&nonrec, mtx_plain); + mtx_init(&both, mtx_plain); + mtx_init(&both, mtx_plain | mtx_recursive); + // Do not initialize `unknown`. + mtx_init(&s.m, mtx_plain); + mtx_init(&arr[0], mtx_plain); + mtx_init(&arr[1], mtx_plain); + + thrd_t t; + thrd_create(t, t1, NULL); +} + +mtx_t *p; + +// Results for the audit query: +void t2(void *arg) { + mtx_lock(&arr[0]); + mtx_lock(&arr[(int)arg]); // NON-COMPLIANT +} + +void t3(void *arg) { + mtx_lock(arg); + mtx_lock(p); // NON-COMPLIANT +} + +void t4() { + mtx_lock(&both); + mtx_lock(&both); // NON-COMPLIANT +} + +void t5() { + mtx_lock(&unknown); + mtx_lock(&unknown); // NON-COMPLIANT +} + +void t6() { + // Cannot be locks of the same mutex: + mtx_lock(&nonrec); + mtx_lock(&unknown); // COMPLIANT +} + +void t7() { + mtx_lock(p); + // Definitely a recursive mutex: + mtx_lock(&rec); // COMPLIANT +} + +void t8() { + mtx_lock(p); + mtx_lock(&nonrec); // NON-COMPLIANT +} + +void t9() { + mtx_lock(&nonrec); + mtx_lock(p); // NON-COMPLIANT +} + +void f2() { + thrd_t t; + thrd_create(t, t2, NULL); +} + +void f3() { + thrd_t t; + thrd_create(t, t3, &rec); +} + +void f4() { + thrd_t t; + thrd_create(t, t4, NULL); +} + +void f5() { + thrd_t t; + thrd_create(t, t5, NULL); +} + +void f6() { + thrd_t t; + thrd_create(t, t6, NULL); +} + +void f7() { + thrd_t t; + thrd_create(t, t7, NULL); +} + +void f8() { + thrd_t t; + thrd_create(t, t8, NULL); +} + +void f9() { + thrd_t t; + thrd_create(t, t9, NULL); +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.expected b/c/misra/test/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.expected new file mode 100644 index 0000000000..ee9dff0be2 --- /dev/null +++ b/c/misra/test/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.expected @@ -0,0 +1,2 @@ +| test.c:19:3:19:10 | call to cnd_wait | Condition variable $@ associated with multiple mutexes, operation uses mutex $@ while $@ uses other mutex $@ | test.c:16:9:16:12 | cnd1 | cnd1 | test.c:17:9:17:12 | mtx1 | mtx1 | test.c:19:3:19:10 | call to cnd_wait | another operation | test.c:18:9:18:12 | mtx2 | mtx2 | +| test.c:41:3:41:10 | call to cnd_wait | Condition variable $@ associated with multiple mutexes, operation uses mutex $@ while $@ uses other mutex $@ | test.c:37:7:37:11 | gcnd1 | gcnd1 | test.c:38:7:38:11 | gmtx1 | gmtx1 | test.c:41:3:41:10 | call to cnd_wait | another operation | test.c:39:7:39:11 | gmtx2 | gmtx2 | diff --git a/c/misra/test/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.qlref b/c/misra/test/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.qlref new file mode 100644 index 0000000000..d43a824ec8 --- /dev/null +++ b/c/misra/test/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.qlref @@ -0,0 +1 @@ +rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-19/test.c b/c/misra/test/rules/RULE-22-19/test.c new file mode 100644 index 0000000000..f4b46d4077 --- /dev/null +++ b/c/misra/test/rules/RULE-22-19/test.c @@ -0,0 +1,46 @@ +#include "threads.h" + +void f1(void) { + cnd_t cnd1; + mtx_t mtx1; + cnd_wait(&cnd1, &mtx1); // COMPLIANT + cnd_wait(&cnd1, &mtx1); // COMPLIANT + + cnd_t cnd2; + mtx_t mtx2; + cnd_wait(&cnd2, &mtx2); // COMPLIANT + cnd_wait(&cnd2, &mtx2); // COMPLIANT +} + +void f2(void) { + cnd_t cnd1; + mtx_t mtx1; + mtx_t mtx2; + cnd_wait(&cnd1, &mtx1); // NON-COMPLIANT + cnd_wait(&cnd1, &mtx2); // NON-COMPLIANT +} + +void f3(void) { + cnd_t cnd1; + cnd_t cnd2; + mtx_t mtx1; + cnd_wait(&cnd1, &mtx1); // COMPLIANT + cnd_wait(&cnd2, &mtx1); // COMPLIANT +} + +void f4(cnd_t *cnd1, mtx_t *mtx1, mtx_t *mtx2) { + cnd_wait(cnd1, mtx1); // COMPLIANT + // Compliant, mtx1 and mtx2 may point to the same object + cnd_wait(cnd1, mtx2); // COMPLIANT +} + +cnd_t gcnd1; +mtx_t gmtx1; +mtx_t gmtx2; +void f5(void) { + cnd_wait(&gcnd1, &gmtx1); // NON-COMPLIANT +} + +void f6(void) { + cnd_wait(&gcnd1, &gmtx2); // NON-COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.expected b/c/misra/test/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.expected new file mode 100644 index 0000000000..9a9b86dfa2 --- /dev/null +++ b/c/misra/test/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.expected @@ -0,0 +1,5 @@ +| test.c:6:11:6:13 | & ... | Thread specific storage pointer '$@' possibly used before initialization, from entry point function '$@'. | test.c:5:9:5:10 | l1 | l1 | test.c:4:6:4:19 | use_local_mtxs | use_local_mtxs | +| test.c:11:11:11:12 | l4 | Thread specific storage pointer '$@' possibly used before initialization, from entry point function '$@'. | test.c:10:15:10:20 | call to malloc | call to malloc | test.c:16:6:16:31 | root1_calls_use_local_mtxs | root1_calls_use_local_mtxs | +| test.c:25:11:25:13 | & ... | Thread specific storage pointer '$@' possibly used before initialization, from entry point function '$@'. | test.c:22:7:22:8 | g1 | g1 | test.c:24:6:24:28 | root2_uses_global_tss_t | root2_uses_global_tss_t | +| test.c:38:11:38:13 | & ... | Thread specific storage pointer '$@' possibly used before initialization, from entry point function '$@'. | test.c:22:7:22:8 | g1 | g1 | test.c:41:6:41:45 | root4_call_thread_without_initialization | root4_call_thread_without_initialization | +| test.c:58:11:58:13 | & ... | Thread specific storage pointer '$@' possibly used before initialization, from entry point function '$@'. | test.c:56:7:56:8 | g5 | g5 | test.c:67:6:67:50 | root6_spawn_thread_uninitialized_thread_local | root6_spawn_thread_uninitialized_thread_local | diff --git a/c/misra/test/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.qlref b/c/misra/test/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.qlref new file mode 100644 index 0000000000..10d9aadf1b --- /dev/null +++ b/c/misra/test/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.qlref @@ -0,0 +1 @@ +rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.expected b/c/misra/test/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.expected new file mode 100644 index 0000000000..75e9825074 --- /dev/null +++ b/c/misra/test/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.expected @@ -0,0 +1 @@ +| test.c:61:3:61:12 | call to tss_create | Thread specific storage object initialization reachable from threaded function '$@'. | test.c:57:6:57:41 | from_root6_init_and_use_thread_local | from_root6_init_and_use_thread_local | diff --git a/c/misra/test/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.qlref b/c/misra/test/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.qlref new file mode 100644 index 0000000000..d299808814 --- /dev/null +++ b/c/misra/test/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.qlref @@ -0,0 +1 @@ +rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-20/test.c b/c/misra/test/rules/RULE-22-20/test.c new file mode 100644 index 0000000000..0fe58abdcd --- /dev/null +++ b/c/misra/test/rules/RULE-22-20/test.c @@ -0,0 +1,70 @@ +#include "stdlib.h" +#include "threads.h" + +void use_local_mtxs(int x, int y) { + tss_t l1; + tss_get(&l1); // NON-COMPLIANT + tss_create(&l1, NULL); + tss_get(&l1); // COMPLIANT + + tss_t *l4 = malloc(sizeof(tss_t)); + tss_get(l4); // NON-COMPLIANT + tss_create(l4, NULL); + tss_get(l4); // COMPLIANT +} + +void root1_calls_use_local_mtxs() { + // Since a function exists which calls use_local_mtxs(), that function is not + // a root function. The query should still report unused locals in this case. + use_local_mtxs(1, 2); +} + +tss_t g1; + +void root2_uses_global_tss_t() { + tss_get(&g1); // NON-COMPLIANT +} + +void from_root3_use_global_tss_t() { + tss_get(&g1); // COMPLIANT +} + +void root3_initializes_and_uses_global_tss_t() { + tss_create(&g1, NULL); + from_root3_use_global_tss_t(); +} + +void from_root4_use_global_tss_t(void *arg) { + tss_get(&g1); // NON-COMPLIANT +} + +void root4_call_thread_without_initialization() { + thrd_t t; + thrd_create(&t, &from_root4_use_global_tss_t, NULL); +} + +void from_root5_use_global_tss_t(void *arg) { + tss_get(&g1); // COMPLIANT +} + +void root5_thread_with_initialization() { + tss_create(&g1, NULL); + thrd_t t; + thrd_create(&t, &from_root5_use_global_tss_t, NULL); +} + +mtx_t g5; +void from_root6_init_and_use_thread_local() { + tss_get(&g5); // NON-COMPLIANT + + // Violates recommendation, tss_t initialized within a thread. + tss_create(&g5, NULL); // NON-COMPLIANT + + // Valid if we except the above initialization. + tss_get(&g5); // COMPLIANT +} + +void root6_spawn_thread_uninitialized_thread_local() { + thrd_t t; + thrd_create(&t, &from_root6_init_and_use_thread_local, NULL); +} \ No newline at end of file diff --git a/change_notes/2024-12-10-refactor-concurrency-library.md b/change_notes/2024-12-10-refactor-concurrency-library.md new file mode 100644 index 0000000000..ccefe85f19 --- /dev/null +++ b/change_notes/2024-12-10-refactor-concurrency-library.md @@ -0,0 +1,2 @@ + - `Concurrency.qll` - for all queries using this library + - This has been refactored into a set of smaller utility files. No impact on query results or performance expected. \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/Concurrency.qll b/cpp/common/src/codingstandards/cpp/Concurrency.qll index cfb0f03f72..0e2afb8ece 100644 --- a/cpp/common/src/codingstandards/cpp/Concurrency.qll +++ b/cpp/common/src/codingstandards/cpp/Concurrency.qll @@ -1,1015 +1,15 @@ import cpp import semmle.code.cpp.dataflow.TaintTracking - -/** - * Models CFG nodes which should be added to a thread context. - */ -abstract class ThreadedCFGPathExtension extends ControlFlowNode { - /** - * Returns the next `ControlFlowNode` in this thread context. - */ - abstract ControlFlowNode getNext(); -} - -/** - * Models a `FunctionCall` invoked from a threaded context. - */ -class ThreadContextFunctionCall extends FunctionCall, ThreadedCFGPathExtension { - override ControlFlowNode getNext() { getTarget().getEntryPoint() = result } -} - -/** - * Models a specialized `FunctionCall` that may create a thread. - */ -abstract class ThreadCreationFunction extends FunctionCall, ThreadedCFGPathExtension { - /** - * Returns the function that will be invoked. - */ - abstract Function getFunction(); -} - -/** - * Models a call to a thread constructor via `std::thread`. - */ -class ThreadConstructorCall extends ConstructorCall, ThreadCreationFunction { - Function f; - - ThreadConstructorCall() { - getTarget().getDeclaringType().hasQualifiedName("std", "thread") and - f = getArgument(0).(FunctionAccess).getTarget() - } - - /** - * Returns the function that will be invoked by this `std::thread`. - */ - override Function getFunction() { result = f } - - override ControlFlowNode getNext() { result = getFunction().getEntryPoint() } -} - -/** - * Models a call to a thread creation via `thrd_create` or `pthread_create`. - */ -class CThreadCreateCall extends FunctionCall { - Function f; - int fArgIdx; - - CThreadCreateCall() { - ( - getTarget().getName() = "thrd_create" and - fArgIdx = 1 - or - getTarget().getName() = "pthread_create" and - fArgIdx = 2 - ) and - ( - f = getArgument(fArgIdx).(FunctionAccess).getTarget() or - f = getArgument(fArgIdx).(AddressOfExpr).getOperand().(FunctionAccess).getTarget() - ) - } - - /** - * Returns the function that will be invoked by this thread. - */ - Function getFunction() { result = f } -} - -/** - * Models a call to a thread constructor via `thrd_create`. - */ -class C11ThreadCreateCall extends ThreadCreationFunction, CThreadCreateCall { - C11ThreadCreateCall() { getTarget().getName() = "thrd_create" } - - /** - * Returns the function that will be invoked by this thread. - */ - override Function getFunction() { result = f } - - override ControlFlowNode getNext() { result = getFunction().getEntryPoint() } -} - -class C11MutexType extends TypedefType { - C11MutexType() { this.hasName("mtx_t") } -} - -class C11ThreadType extends TypedefType { - C11ThreadType() { this.hasName("thrd_t") } -} - -class C11ConditionType extends TypedefType { - C11ConditionType() { this.hasName("cnd_t") } -} - -class C11ThreadStorageType extends TypedefType { - C11ThreadStorageType() { this.hasName("tss_t") } -} - -class C11ThreadingObjectType extends TypedefType { - C11ThreadingObjectType() { - this instanceof C11MutexType - or - this instanceof C11ThreadType - or - this instanceof C11ConditionType - or - this instanceof C11ThreadStorageType - } -} - -/** - * Common base class providing an interface into function call - * based mutex locks. - */ -abstract class MutexFunctionCall extends LockingOperation { - abstract predicate isRecursive(); - - abstract predicate isSpeculativeLock(); - - abstract predicate unlocks(MutexFunctionCall fc); -} - -/** - * Models calls to various mutex types found in CPP. - */ -class CPPMutexFunctionCall extends MutexFunctionCall { - VariableAccess var; - - CPPMutexFunctionCall() { - ( - // the non recursive kinds - getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "mutex") or - getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "timed_mutex") or - getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "shared_timed_mutex") or - // the recursive ones - getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "recursive_mutex") or - getTarget() - .(MemberFunction) - .getDeclaringType() - .hasQualifiedName("std", "recursive_timed_mutex") - ) and - var = getQualifier() - } - - /** - * Holds if this mutex is a recursive mutex. - */ - override predicate isRecursive() { - getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "recursive_mutex") or - getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "recursive_timed_mutex") - } - - /** - * Holds if this `CPPMutexFunctionCall` is a lock. - */ - override predicate isLock() { - not isLockingOperationWithinLockingOperation(this) and - getTarget().getName() = "lock" - } - - /** - * Holds if this `CPPMutexFunctionCall` is a speculative lock, defined as calling - * one of the speculative locking functions such as `try_lock`. - */ - override predicate isSpeculativeLock() { - getTarget().getName() in [ - "try_lock", "try_lock_for", "try_lock_until", "try_lock_shared_for", "try_lock_shared_until" - ] - } - - /** - * Returns the lock to which this `CPPMutexFunctionCall` refers to. - */ - override Variable getLock() { result = getQualifier().(VariableAccess).getTarget() } - - /** - * Returns the qualifier for this `CPPMutexFunctionCall`. - */ - override Expr getLockExpr() { result = var } - - /** - * Holds if this is a `unlock` and *may* unlock the previously locked `MutexFunctionCall`. - * This predicate does not check that the mutex is currently locked. - */ - override predicate unlocks(MutexFunctionCall fc) { - isUnlock() and - fc.getQualifier().(VariableAccess).getTarget() = getQualifier().(VariableAccess).getTarget() - } - - /** - * Holds if this is an unlock call. - */ - override predicate isUnlock() { getTarget().getName() = "unlock" } -} - -/** - * Models calls to various mutex types specialized to C code. - */ -class CMutexFunctionCall extends MutexFunctionCall { - Expr arg; - - CMutexFunctionCall() { - // the non recursive kinds - getTarget().getName() = ["mtx_lock", "mtx_unlock", "mtx_timedlock", "mtx_trylock"] and - arg = getArgument(0) - } - - /** - * Holds if this mutex is a recursive mutex. - */ - override predicate isRecursive() { none() } - - /** - * Holds if this `CMutexFunctionCall` is a lock. - */ - override predicate isLock() { - not isLockingOperationWithinLockingOperation(this) and - getTarget().getName() = ["mtx_lock", "mtx_timedlock", "mtx_trylock"] - } - - /** - * Holds if this `CMutexFunctionCall` is a speculative lock, defined as calling - * one of the speculative locking functions such as `try_lock`. - */ - override predicate isSpeculativeLock() { - getTarget().getName() in ["mtx_timedlock", "mtx_trylock"] - } - - /** - * Returns the `Variable` to which this `CMutexFunctionCall` refers to. For this - * style of lock it can reference a number of different variables. - */ - override Variable getLock() { - exists(VariableAccess va | - TaintTracking::localTaint(DataFlow::exprNode(va), DataFlow::exprNode(getLockExpr())) and - result = va.getTarget() - ) - } - - /** - * Returns the expression for this `CMutexFunctionCall`. - */ - override Expr getLockExpr() { result = arg } - - /** - * Holds if this is a `unlock` and *may* unlock the previously locked `CMutexFunctionCall`. - * This predicate does not check that the mutex is currently locked. - */ - override predicate unlocks(MutexFunctionCall fc) { - isUnlock() and - fc.getLock() = getLock() - } - - /** - * Holds if this is an unlock call. - */ - override predicate isUnlock() { getTarget().getName() = "mtx_unlock" } -} - -/** - * The thread-aware predecessor function is defined in terms of the thread aware - * successor function. This is because it is simpler to construct the forward - * paths of a thread's execution than the backwards paths. For this reason we - * require a `start` and `end` node. - * - * The logic of this function is that a thread aware predecessor is one that - * follows a `start` node, is not equal to the ending node, and does not follow - * the `end` node. Such nodes can only be predecessors of `end`. - * - * For this reason this function requires a `start` node from which to start - * considering something a predecessor of `end`. - */ -pragma[inline] -ControlFlowNode getAThreadContextAwarePredecessor(ControlFlowNode start, ControlFlowNode end) { - result = getAThreadContextAwareSuccessor(start) and - not result = getAThreadContextAwareSuccessor(end) and - not result = end -} - -/** - * A predicate for finding successors of `ControlFlowNode`s that are aware of - * the objects that my flow into a thread's context. This is achieved by adding - * additional edges to thread entry points and function calls. - */ -ControlFlowNode getAThreadContextAwareSuccessorR(ControlFlowNode cfn) { - result = cfn.getASuccessor() - or - result = cfn.(ThreadedCFGPathExtension).getNext() -} - -ControlFlowNode getAThreadContextAwareSuccessor(ControlFlowNode m) { - result = getAThreadContextAwareSuccessorR*(m) and - // for performance reasons we handle back edges by enforcing a lexical - // ordering restriction on these nodes if they are both in - // the same loop. One way of doing this is as follows: - // - // ````and ( - // exists(Loop loop | - // loop.getAChild*() = m and - // loop.getAChild*() = result - // ) - // implies - // not result.getLocation().isBefore(m.getLocation()) - // )``` - // In this implementation we opt for the more generic form below - // which seems to have reasonable performance. - ( - m.getEnclosingStmt().getParentStmt*() = result.getEnclosingStmt().getParentStmt*() - implies - not exists(Location l1, Location l2 | - l1 = result.getLocation() and - l2 = m.getLocation() - | - l1.getEndLine() < l2.getStartLine() - or - l1.getStartLine() = l2.getEndLine() and - l1.getEndColumn() < l2.getStartColumn() - ) - ) -} - -abstract class LockingOperation extends FunctionCall { - /** - * Returns the target of the lock underlying this RAII-style lock. - */ - abstract Variable getLock(); - - /** - * Returns the lock underlying this RAII-style lock. - */ - abstract Expr getLockExpr(); - - /** - * Holds if this is a lock operation - */ - abstract predicate isLock(); - - /** - * Holds if this is an unlock operation - */ - abstract predicate isUnlock(); - - /** - * Holds if this locking operation is really a locking operation within a - * designated locking operation. This library assumes the underlying locking - * operations are implemented correctly in that calling a `LockingOperation` - * results in the creation of a singular lock. - */ - predicate isLockingOperationWithinLockingOperation(LockingOperation inner) { - exists(LockingOperation outer | outer.getTarget() = inner.getEnclosingFunction()) - } -} - -/** - * Models a RAII-Style lock. - */ -class RAIIStyleLock extends LockingOperation { - VariableAccess lock; - - RAIIStyleLock() { - ( - getTarget().getDeclaringType().hasQualifiedName("std", "lock_guard") or - getTarget().getDeclaringType().hasQualifiedName("std", "unique_lock") or - getTarget().getDeclaringType().hasQualifiedName("std", "scoped_lock") - ) and - ( - lock = getArgument(0).getAChild*() - or - this instanceof DestructorCall and - exists(RAIIStyleLock constructor | - constructor = getQualifier().(VariableAccess).getTarget().getInitializer().getExpr() and - lock = constructor.getArgument(0).getAChild*() - ) - ) - } - - /** - * Holds if this is a lock operation - */ - override predicate isLock() { - not isLockingOperationWithinLockingOperation(this) and - this instanceof ConstructorCall and - lock = getArgument(0).getAChild*() and - // defer_locks don't cause a lock - not exists(Expr exp | - exp = getArgument(1) and - exp.(VariableAccess) - .getTarget() - .getUnderlyingType() - .(Class) - .hasQualifiedName("std", "defer_lock_t") - ) - } - - /** - * Holds if this is an unlock operation - */ - override predicate isUnlock() { this instanceof DestructorCall } - - /** - * Returns the target of the lock underlying this RAII-style lock. - */ - override Variable getLock() { result = lock.getTarget() } - - /** - * Returns the lock underlying this RAII-style lock. - */ - override Expr getLockExpr() { result = lock } -} - -/** - * Models a function that may be executed by some thread. - */ -abstract class ThreadedFunction extends Function { } - -/** - * Models a function that may be executed by some thread via - * C++ standard classes. - */ -class CPPThreadedFunction extends ThreadedFunction { - CPPThreadedFunction() { exists(ThreadConstructorCall tcc | tcc.getFunction() = this) } -} - -/** - * Models a function that may be executed by some thread via - * C11 standard functions. - */ -class C11ThreadedFunction extends ThreadedFunction { - C11ThreadedFunction() { exists(C11ThreadCreateCall cc | cc.getFunction() = this) } -} - -/** - * Models a control flow node within a function that may be executed by some - * thread. - */ -class ThreadedCFN extends ControlFlowNode { - ThreadedCFN() { - exists(ThreadedFunction tf | this = getAThreadContextAwareSuccessor(tf.getEntryPoint())) - } -} - -/** - * Models a `ControlFlowNode` that is protected by some sort of lock. - */ -class LockProtectedControlFlowNode extends ThreadedCFN { - FunctionCall lockingFunction; - - LockProtectedControlFlowNode() { - exists(LockingOperation lock | - // there is a node that is a lock - lockingFunction = lock and - lock.isLock() and - // this node should be a successor of this lock - this = getAThreadContextAwareSuccessor(lock) and - // and there should not exist a predecessor of this - // node that is an unlock. Since we are doing thread context - // aware tracking it is easier to go forwards than backwards - // in constructing the call graph. Thus we can define predecessor - // in terms of a node that is a successor of the lock but NOT a - // successor of the current node. - not exists(ControlFlowNode unlock | - // it's an unlock - unlock = getAThreadContextAwarePredecessor(lock, this) and - unlock.(MutexFunctionCall).isUnlock() and - // note that we don't check that it's the same lock -- this is left - // to the caller to enforce this condition. - // Because of the way that `getAThreadContextAwarePredecessor` works, it is possible - // for operations PAST it to be technically part of the predecessors. - // Thus, we need to make sure that this node is a - // successor of the unlock in the CFG - getAThreadContextAwareSuccessor(unlock) = this - ) and - (lock instanceof MutexFunctionCall implies not this.(MutexFunctionCall).isUnlock()) - ) - } - - /** - * The `MutexFunctionCall` holding the lock that locks this node. - */ - FunctionCall coveredByLock() { result = lockingFunction } - - /** - * The lock underlying this `LockProtectedControlFlowNode`. - */ - Variable getAProtectingLock() { result = lockingFunction.(LockingOperation).getLock() } -} - -/** - * Models a function that conditionally waits. - */ -abstract class ConditionalWait extends FunctionCall { } - -/** - * Models a function in CPP that will conditionally wait. - */ -class CPPConditionalWait extends ConditionalWait { - CPPConditionalWait() { - exists(MemberFunction mf | - mf = getTarget() and - mf.getDeclaringType().hasQualifiedName("std", "condition_variable") and - mf.getName() in ["wait", "wait_for", "wait_until"] - ) - } -} - -/** - * Models a function in C that will conditionally wait. - */ -class CConditionalWait extends ConditionalWait { - CConditionalWait() { getTarget().getName() in ["cnd_wait"] } -} - -/** - * Models a function which uses a c condition variable. Not integrated into the thread aware CFG. - */ -class CConditionOperation extends FunctionCall { - CConditionOperation() { - getTarget().hasName(["cnd_broadcast", "cnd_signal", "cnd_timedwait", "cnd_wait", "cnd_init"]) - } - - predicate isInit() { getTarget().hasName("cnd_init") } - - predicate isUse() { not isInit() } - - Expr getConditionExpr() { result = getArgument(0) } - - /* Note: only holds for `cnd_wait()` and `cnd_timedwait()` */ - Expr getMutexExpr() { result = getArgument(1) } -} - -/** - * Models a call to a `std::thread` constructor that depends on a mutex. - */ -class MutexDependentThreadConstructor extends ThreadConstructorCall { - Expr mutexExpr; - - MutexDependentThreadConstructor() { - mutexExpr = getAnArgument() and - mutexExpr.getUnderlyingType().stripType() instanceof MutexType - } - - Expr dependentMutex() { result = mutexExpr } -} - -/** - * Models thread waiting functions. - */ -abstract class ThreadWait extends FunctionCall { } - -/** - * Models a call to a `std::thread` join. - */ -class CPPThreadWait extends ThreadWait { - VariableAccess var; - - CPPThreadWait() { - getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "thread") and - getTarget().getName() = "join" - } -} - -/** - * Models a call to `thrd_join` in C11. - */ -class C11ThreadWait extends ThreadWait { - VariableAccess var; - - C11ThreadWait() { getTarget().getName() = "thrd_join" } -} - -/** - * Models thread detach functions. - */ -abstract class ThreadDetach extends FunctionCall { } - -/** - * Models a call to `thrd_detach` in C11. - */ -class C11ThreadDetach extends ThreadWait { - VariableAccess var; - - C11ThreadDetach() { getTarget().getName() = "thrd_detach" } -} - -abstract class MutexSource extends FunctionCall { } - -/** - * Models a C++ style mutex. - */ -class CPPMutexSource extends MutexSource, ConstructorCall { - CPPMutexSource() { getTarget().getDeclaringType().hasQualifiedName("std", "mutex") } -} - -/** - * Models a C11 style mutex. - */ -class C11MutexSource extends MutexSource, FunctionCall { - C11MutexSource() { getTarget().hasName("mtx_init") } - - Expr getMutexExpr() { result = getArgument(0) } - - Expr getMutexTypeExpr() { result = getArgument(1) } -} - -/** - * Models a thread dependent mutex. A thread dependent mutex is a mutex - * that is used by a thread. This dependency is established either by directly - * passing in a mutex or by referencing a mutex that is in the local scope. The utility - * of this class is it captures the `DataFlow::Node` source at which the mutex - * came from. For example, if it is passed in from a local function to a thread. - * This functionality is critical, since it allows one to inspect how the thread - * behaves with respect to the owner of a resource. - * - * To model the myriad ways this can happen, the subclasses of this class are - * responsible for implementing the various usage patterns. - */ -abstract class ThreadDependentMutex extends DataFlow::Node { - DataFlow::Node sink; - - DataFlow::Node getASource() { - // the source is either the thing that declared - // the mutex - result = this - or - // or the thread we are using it in - result = getAThreadSource() - } - - /** - * Gets the dataflow nodes corresponding to thread local usages of the - * dependent mutex. - */ - DataFlow::Node getAThreadSource() { - // here we line up the actual parameter at the thread creation - // site with the formal parameter in the target thread. - // Note that there are differences between the C and C++ versions - // of the argument ordering in the thread creation function. However, - // since the C version only takes one parameter (as opposed to multiple) - // we can simplify this search by considering only the first argument. - exists(FunctionCall fc, Function f, int n | - // Get the argument to which the mutex flowed. - fc.getArgument(n) = sink.asExpr() and - // Get the thread function we are calling. - f = fc.getArgument(0).(FunctionAccess).getTarget() and - // in C++, there is an extra argument to the `std::thread` call - // so we must subtract 1 since this is not passed to the thread. - ( - result = DataFlow::exprNode(f.getParameter(n - 1).getAnAccess()) - or - // In C, only one argument is allowed. Thus IF the flow predicate holds, - // it will be to the first argument - result = DataFlow::exprNode(f.getParameter(0).getAnAccess()) - ) - ) - } - - /** - * Produces the set of dataflow nodes to thread creation for threads - * that are dependent on this mutex. - */ - DataFlow::Node getADependentThreadCreationExpr() { - exists(FunctionCall fc | - fc.getAnArgument() = sink.asExpr() and - result = DataFlow::exprNode(fc) - ) - } - - /** - * Gets a set of usages of this mutex in both the local and thread scope. - * In the case of scoped usage, this also captures typical accesses of variables. - */ - DataFlow::Node getAUsage() { TaintTracking::localTaint(getASource(), result) } -} - -/** - * This class models the type of thread/mutex dependency that is established - * through the typical parameter passing mechanisms found in C++. - */ -class FlowBasedThreadDependentMutex extends ThreadDependentMutex { - FlowBasedThreadDependentMutex() { - // some sort of dataflow, likely through parameter passing. - ThreadDependentMutexFlow::flow(this, sink) - } -} - -/** - * This class models the type of thread/mutex dependency that is established by - * either scope based accesses (e.g., global variables) or block scope differences. - */ -class AccessBasedThreadDependentMutex extends ThreadDependentMutex { - Variable variableSource; - - AccessBasedThreadDependentMutex() { - // encapsulates usages from outside scopes not directly expressed - // in dataflow. - exists(MutexSource mutexSrc, ThreadedFunction f | - DataFlow::exprNode(mutexSrc) = this and - // find a variable that was assigned the mutex - TaintTracking::localTaint(DataFlow::exprNode(mutexSrc), - DataFlow::exprNode(variableSource.getAnAssignedValue())) and - // find all subsequent accesses of that variable that are within a - // function and set those to the sink - exists(VariableAccess va | - va = variableSource.getAnAccess() and - va.getEnclosingFunction() = f and - sink = DataFlow::exprNode(va) - ) - ) - } - - override DataFlow::Node getAUsage() { DataFlow::exprNode(variableSource.getAnAccess()) = result } -} - -/** - * In the typical C thread model, a mutex is a created by a function that is not responsible - * for creating the variable. Thus this class encodes a slightly different semantics - * wherein the usage pattern is that of variables that have been both initialized - * and then subsequently passed into a thread directly. - */ -class DeclarationInitBasedThreadDependentMutex extends ThreadDependentMutex { - Variable variableSource; - - DeclarationInitBasedThreadDependentMutex() { - exists(MutexSource ms, ThreadCreationFunction tcf | - this = DataFlow::exprNode(ms) and - // accessed as a mutex source - TaintTracking::localTaint(DataFlow::exprNode(variableSource.getAnAccess()), - DataFlow::exprNode(ms.getAnArgument())) and - // subsequently passed to a thread creation function (order not strictly - // enforced for performance reasons) - sink = DataFlow::exprNode(tcf.getAnArgument()) and - TaintTracking::localTaint(DataFlow::exprNode(variableSource.getAnAccess()), sink) - ) - } - - override DataFlow::Node getAUsage() { - TaintTracking::localTaint(getASource(), result) or - DataFlow::exprNode(variableSource.getAnAccess()) = result - } - - override DataFlow::Node getASource() { - // the source is either the thing that declared - // the mutex - result = this - or - // or the thread we are using it in - result = getAThreadSource() - } - - DataFlow::Node getSink() { result = sink } - - /** - * Gets the dataflow nodes corresponding to thread local usages of the - * dependent mutex. - */ - override DataFlow::Node getAThreadSource() { - // here we line up the actual parameter at the thread creation - // site with the formal parameter in the target thread. - // Note that there are differences between the C and C++ versions - // of the argument ordering in the thread creation function. However, - // since the C version only takes one parameter (as opposed to multiple) - // we can simplify this search by considering only the first argument. - exists( - FunctionCall fc, Function f, int n // CPP Version - | - fc.getArgument(n) = sink.asExpr() and - f = fc.getArgument(0).(FunctionAccess).getTarget() and - // in C++, there is an extra argument to the `std::thread` call - // so we must subtract 1 since this is not passed to the thread. - result = DataFlow::exprNode(f.getParameter(n - 1).getAnAccess()) - ) - or - exists( - FunctionCall fc, Function f // C Version - | - fc.getAnArgument() = sink.asExpr() and - // in C, the second argument is the function - f = fc.getArgument(1).(FunctionAccess).getTarget() and - // in C, the passed argument is always the zeroth argument - result = DataFlow::exprNode(f.getParameter(0).getAnAccess()) - ) - } -} - -/** - * In the typical C model, another way to use mutexes is to work with global variables - * that can be initialized at various points -- one of which must be inside a thread. - * This class encapsulates this pattern. - */ -class DeclarationInitAccessBasedThreadDependentMutex extends ThreadDependentMutex { - Variable variableSource; - - DeclarationInitAccessBasedThreadDependentMutex() { - exists(MutexSource ms, ThreadedFunction tf, VariableAccess va | - this = DataFlow::exprNode(ms) and - // accessed as a mutex source - TaintTracking::localTaint(DataFlow::exprNode(variableSource.getAnAccess()), - DataFlow::exprNode(ms.getAnArgument())) and - // is accessed somewhere else - va = variableSource.getAnAccess() and - sink = DataFlow::exprNode(va) and - // one of which must be a thread - va.getEnclosingFunction() = tf - ) - } - - override DataFlow::Node getAUsage() { result = DataFlow::exprNode(variableSource.getAnAccess()) } -} - -module ThreadDependentMutexConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node node) { node.asExpr() instanceof MutexSource } - - predicate isSink(DataFlow::Node node) { - exists(ThreadCreationFunction f | f.getAnArgument() = node.asExpr()) - } -} - -module ThreadDependentMutexFlow = TaintTracking::Global; - -/** - * Models expressions that destroy mutexes. - */ -abstract class MutexDestroyer extends StmtParent { - /** - * Gets the expression that references the mutex being destroyed. - */ - abstract Expr getMutexExpr(); -} - -/** - * Models C style mutex destruction via `mtx_destroy`. - */ -class C11MutexDestroyer extends MutexDestroyer, FunctionCall { - C11MutexDestroyer() { getTarget().getName() = "mtx_destroy" } - - /** - * Returns the `Expr` being destroyed. - */ - override Expr getMutexExpr() { result = getArgument(0) } -} - -/** - * Models a delete expression -- note it is necessary to add this in - * addition to destructors to handle certain implementations of the - * standard library which obscure the destructors of mutexes. - */ -class DeleteMutexDestroyer extends MutexDestroyer { - DeleteMutexDestroyer() { this instanceof DeleteExpr } - - override Expr getMutexExpr() { this.(DeleteExpr).getExpr() = result } -} - -/** - * Models a possible mutex variable that if it goes - * out of scope would destroy an underlying mutex. - */ -class LocalMutexDestroyer extends MutexDestroyer { - Expr assignedValue; - - LocalMutexDestroyer() { - exists(LocalVariable lv | - // static types aren't destroyers - not lv.isStatic() and - // neither are pointers - not lv.getType() instanceof PointerType and - lv.getAnAssignedValue() = assignedValue and - // map the location to the return statements of the - // enclosing function - exists(ReturnStmt rs | - rs.getEnclosingFunction() = assignedValue.getEnclosingFunction() and - rs = this - ) - ) - } - - override Expr getMutexExpr() { result = assignedValue } -} - -/** - * Models implicit or explicit calls to the destructor of a mutex, either via - * a `delete` statement or a variable going out of scope. - */ -class DestructorMutexDestroyer extends MutexDestroyer, DestructorCall { - DestructorMutexDestroyer() { getTarget().getDeclaringType().hasQualifiedName("std", "mutex") } - - /** - * Returns the `Expr` being deleted. - */ - override Expr getMutexExpr() { getQualifier() = result } -} - -/** - * Models a conditional variable denoted by `std::condition_variable`. - */ -class ConditionalVariable extends Variable { - ConditionalVariable() { - getUnderlyingType().(Class).hasQualifiedName("std", "condition_variable") - } -} - -/** - * Models a conditional function, which is a function that depends on the value - * of a conditional variable. - */ -class ConditionalFunction extends Function { - ConditionalFunction() { - exists(ConditionalVariable cv | cv.getAnAccess().getEnclosingFunction() = this) - } -} - -/** - * Models calls to thread specific storage function calls. - */ -abstract class ThreadSpecificStorageFunctionCall extends FunctionCall { - /** - * Gets the key to which this call references. - */ - Expr getKey() { getArgument(0) = result } -} - -/** - * Models calls to `tss_get`. - */ -class TSSGetFunctionCall extends ThreadSpecificStorageFunctionCall { - TSSGetFunctionCall() { getTarget().getName() = "tss_get" } -} - -/** - * Models calls to `tss_set`. - */ -class TSSSetFunctionCall extends ThreadSpecificStorageFunctionCall { - TSSSetFunctionCall() { getTarget().getName() = "tss_set" } -} - -/** - * Models calls to `tss_create` - */ -class TSSCreateFunctionCall extends ThreadSpecificStorageFunctionCall { - TSSCreateFunctionCall() { getTarget().getName() = "tss_create" } - - predicate hasDeallocator() { - not exists(MacroInvocation mi, NullMacro nm | - getArgument(1) = mi.getExpr() and - mi = nm.getAnInvocation() - ) - } -} - -/** - * Models calls to `tss_delete` - */ -class TSSDeleteFunctionCall extends ThreadSpecificStorageFunctionCall { - TSSDeleteFunctionCall() { getTarget().getName() = "tss_delete" } -} - -/** - * Gets a call to `DeallocationExpr` that deallocates memory owned by thread specific - * storage. - */ -predicate getAThreadSpecificStorageDeallocationCall(C11ThreadCreateCall tcc, DeallocationExpr dexp) { - exists(TSSGetFunctionCall tsg | - tcc.getFunction().getEntryPoint().getASuccessor*() = tsg and - DataFlow::localFlow(DataFlow::exprNode(tsg), DataFlow::exprNode(dexp.getFreedExpr())) - ) -} - -/** - * Models calls to routines `atomic_compare_exchange_weak` and - * `atomic_compare_exchange_weak_explicit` in the `stdatomic` library. - * Note that these are typically implemented as macros within Clang and - * GCC's standard libraries. - */ -class AtomicCompareExchange extends MacroInvocation { - AtomicCompareExchange() { - getMacroName() = "atomic_compare_exchange_weak" - or - // some compilers model `atomic_compare_exchange_weak` as a macro that - // expands to `atomic_compare_exchange_weak_explicit` so this defeats that - // and other similar modeling. - getMacroName() = "atomic_compare_exchange_weak_explicit" and - not exists(MacroInvocation m | - m.getMacroName() = "atomic_compare_exchange_weak" and - m.getAnExpandedElement() = getAnExpandedElement() - ) - } -} - -/** - * Models calls to routines `atomic_store` and - * `atomic_store_explicit` in the `stdatomic` library. - * Note that these are typically implemented as macros within Clang and - * GCC's standard libraries. - */ -class AtomicStore extends MacroInvocation { - AtomicStore() { - getMacroName() = "atomic_store" - or - // some compilers model `atomic_compare_exchange_weak` as a macro that - // expands to `atomic_compare_exchange_weak_explicit` so this defeats that - // and other similar modeling. - getMacroName() = "atomic_store_explicit" and - not exists(MacroInvocation m | - m.getMacroName() = "atomic_store" and - m.getAnExpandedElement() = getAnExpandedElement() - ) - } -} +import codingstandards.cpp.concurrency.Atomic +import codingstandards.cpp.concurrency.CConditionOperation +import codingstandards.cpp.concurrency.ControlFlow +import codingstandards.cpp.concurrency.ConditionalWait +import codingstandards.cpp.concurrency.LockingOperation +import codingstandards.cpp.concurrency.LockProtectedControlFlow +import codingstandards.cpp.concurrency.MutexDestroyer +import codingstandards.cpp.concurrency.ThreadCreation +import codingstandards.cpp.concurrency.ThreadedFunction +import codingstandards.cpp.concurrency.ThreadDependentMutex +import codingstandards.cpp.concurrency.ThreadSpecificStorage +import codingstandards.cpp.concurrency.ThreadWaitDetach +import codingstandards.cpp.concurrency.Types diff --git a/cpp/common/src/codingstandards/cpp/concurrency/Atomic.qll b/cpp/common/src/codingstandards/cpp/concurrency/Atomic.qll new file mode 100644 index 0000000000..44101f08bb --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/Atomic.qll @@ -0,0 +1,43 @@ +import cpp + +/** + * Models calls to routines `atomic_compare_exchange_weak` and + * `atomic_compare_exchange_weak_explicit` in the `stdatomic` library. + * Note that these are typically implemented as macros within Clang and + * GCC's standard libraries. + */ +class AtomicCompareExchange extends MacroInvocation { + AtomicCompareExchange() { + getMacroName() = "atomic_compare_exchange_weak" + or + // some compilers model `atomic_compare_exchange_weak` as a macro that + // expands to `atomic_compare_exchange_weak_explicit` so this defeats that + // and other similar modeling. + getMacroName() = "atomic_compare_exchange_weak_explicit" and + not exists(MacroInvocation m | + m.getMacroName() = "atomic_compare_exchange_weak" and + m.getAnExpandedElement() = getAnExpandedElement() + ) + } +} + +/** + * Models calls to routines `atomic_store` and + * `atomic_store_explicit` in the `stdatomic` library. + * Note that these are typically implemented as macros within Clang and + * GCC's standard libraries. + */ +class AtomicStore extends MacroInvocation { + AtomicStore() { + getMacroName() = "atomic_store" + or + // some compilers model `atomic_compare_exchange_weak` as a macro that + // expands to `atomic_compare_exchange_weak_explicit` so this defeats that + // and other similar modeling. + getMacroName() = "atomic_store_explicit" and + not exists(MacroInvocation m | + m.getMacroName() = "atomic_store" and + m.getAnExpandedElement() = getAnExpandedElement() + ) + } +} diff --git a/cpp/common/src/codingstandards/cpp/concurrency/CConditionOperation.qll b/cpp/common/src/codingstandards/cpp/concurrency/CConditionOperation.qll new file mode 100644 index 0000000000..adf230f08d --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/CConditionOperation.qll @@ -0,0 +1,31 @@ +import cpp + +/** + * Models a function which uses a c condition variable. Not integrated into the thread aware CFG. + */ +class CConditionOperation extends FunctionCall { + CConditionOperation() { + getTarget().hasName(["cnd_broadcast", "cnd_signal", "cnd_timedwait", "cnd_wait", "cnd_init"]) + } + + predicate isInit() { getTarget().hasName("cnd_init") } + + predicate isUse() { not isInit() } + + Expr getConditionExpr() { result = getArgument(0) } + + /* Note: only holds for `cnd_wait()` and `cnd_timedwait()` */ + Expr getMutexExpr() { result = getArgument(1) } +} + +/** + * Models C style condition destruction via `cnd_destroy`. + */ +class C11ConditionDestroyer extends FunctionCall { + C11ConditionDestroyer() { getTarget().getName() = "cnd_destroy" } + + /** + * Returns the `Expr` being destroyed. + */ + Expr getConditionExpr() { result = getArgument(0) } +} diff --git a/cpp/common/src/codingstandards/cpp/concurrency/ConditionalWait.qll b/cpp/common/src/codingstandards/cpp/concurrency/ConditionalWait.qll new file mode 100644 index 0000000000..e69ea2fee5 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/ConditionalWait.qll @@ -0,0 +1,26 @@ +import cpp + +/** + * Models a function that conditionally waits. + */ +abstract class ConditionalWait extends FunctionCall { } + +/** + * Models a function in CPP that will conditionally wait. + */ +class CPPConditionalWait extends ConditionalWait { + CPPConditionalWait() { + exists(MemberFunction mf | + mf = getTarget() and + mf.getDeclaringType().hasQualifiedName("std", "condition_variable") and + mf.getName() in ["wait", "wait_for", "wait_until"] + ) + } +} + +/** + * Models a function in C that will conditionally wait. + */ +class CConditionalWait extends ConditionalWait { + CConditionalWait() { getTarget().getName() in ["cnd_wait"] } +} diff --git a/cpp/common/src/codingstandards/cpp/concurrency/ControlFlow.qll b/cpp/common/src/codingstandards/cpp/concurrency/ControlFlow.qll new file mode 100644 index 0000000000..15f8ab5a61 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/ControlFlow.qll @@ -0,0 +1,101 @@ +import cpp +private import codingstandards.cpp.concurrency.ThreadedFunction + +/** + * Models a control flow node within a function that may be executed by some + * thread. + */ +class ThreadedCFN extends ControlFlowNode { + ThreadedCFN() { + exists(ThreadedFunction tf | this = getAThreadContextAwareSuccessor(tf.getEntryPoint())) + } +} + +/** + * Models CFG nodes which should be added to a thread context. + */ +abstract class ThreadedCFGPathExtension extends ControlFlowNode { + /** + * Returns the next `ControlFlowNode` in this thread context. + */ + abstract ControlFlowNode getNext(); +} + +/** + * Models a `FunctionCall` invoked from a threaded context. + */ +class ThreadContextFunctionCall extends FunctionCall, ThreadedCFGPathExtension { + override ControlFlowNode getNext() { getTarget().getEntryPoint() = result } +} + +/** + * Models a specialized `FunctionCall` that may create a thread. + */ +abstract class ThreadCreationFunction extends FunctionCall, ThreadedCFGPathExtension { + /** + * Returns the function that will be invoked. + */ + abstract Function getFunction(); +} + +/** + * The thread-aware predecessor function is defined in terms of the thread aware + * successor function. This is because it is simpler to construct the forward + * paths of a thread's execution than the backwards paths. For this reason we + * require a `start` and `end` node. + * + * The logic of this function is that a thread aware predecessor is one that + * follows a `start` node, is not equal to the ending node, and does not follow + * the `end` node. Such nodes can only be predecessors of `end`. + * + * For this reason this function requires a `start` node from which to start + * considering something a predecessor of `end`. + */ +pragma[inline] +ControlFlowNode getAThreadContextAwarePredecessor(ControlFlowNode start, ControlFlowNode end) { + result = getAThreadContextAwareSuccessor(start) and + not result = getAThreadContextAwareSuccessor(end) and + not result = end +} + +/** + * A predicate for finding successors of `ControlFlowNode`s that are aware of + * the objects that my flow into a thread's context. This is achieved by adding + * additional edges to thread entry points and function calls. + */ +ControlFlowNode getAThreadContextAwareSuccessorR(ControlFlowNode cfn) { + result = cfn.getASuccessor() + or + result = cfn.(ThreadedCFGPathExtension).getNext() +} + +ControlFlowNode getAThreadContextAwareSuccessor(ControlFlowNode m) { + result = getAThreadContextAwareSuccessorR*(m) and + // for performance reasons we handle back edges by enforcing a lexical + // ordering restriction on these nodes if they are both in + // the same loop. One way of doing this is as follows: + // + // ````and ( + // exists(Loop loop | + // loop.getAChild*() = m and + // loop.getAChild*() = result + // ) + // implies + // not result.getLocation().isBefore(m.getLocation()) + // )``` + // In this implementation we opt for the more generic form below + // which seems to have reasonable performance. + ( + m.getEnclosingStmt().getParentStmt*() = result.getEnclosingStmt().getParentStmt*() + implies + not exists(Location l1, Location l2 | + l1 = result.getLocation() and + l2 = m.getLocation() + | + l1.getEndLine() < l2.getStartLine() + or + l1.getStartLine() = l2.getEndLine() and + l1.getEndColumn() < l2.getStartColumn() + ) + ) +} diff --git a/cpp/common/src/codingstandards/cpp/concurrency/LockProtectedControlFlow.qll b/cpp/common/src/codingstandards/cpp/concurrency/LockProtectedControlFlow.qll new file mode 100644 index 0000000000..a828ec8768 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/LockProtectedControlFlow.qll @@ -0,0 +1,49 @@ +import cpp +private import codingstandards.cpp.concurrency.ControlFlow +private import codingstandards.cpp.concurrency.LockingOperation + +/** + * Models a `ControlFlowNode` that is protected by some sort of lock. + */ +class LockProtectedControlFlowNode extends ThreadedCFN { + FunctionCall lockingFunction; + + LockProtectedControlFlowNode() { + exists(LockingOperation lock | + // there is a node that is a lock + lockingFunction = lock and + lock.isLock() and + // this node should be a successor of this lock + this = getAThreadContextAwareSuccessor(lock) and + // and there should not exist a predecessor of this + // node that is an unlock. Since we are doing thread context + // aware tracking it is easier to go forwards than backwards + // in constructing the call graph. Thus we can define predecessor + // in terms of a node that is a successor of the lock but NOT a + // successor of the current node. + not exists(ControlFlowNode unlock | + // it's an unlock + unlock = getAThreadContextAwarePredecessor(lock, this) and + unlock.(MutexFunctionCall).isUnlock() and + // note that we don't check that it's the same lock -- this is left + // to the caller to enforce this condition. + // Because of the way that `getAThreadContextAwarePredecessor` works, it is possible + // for operations PAST it to be technically part of the predecessors. + // Thus, we need to make sure that this node is a + // successor of the unlock in the CFG + getAThreadContextAwareSuccessor(unlock) = this + ) and + (lock instanceof MutexFunctionCall implies not this.(MutexFunctionCall).isUnlock()) + ) + } + + /** + * The `MutexFunctionCall` holding the lock that locks this node. + */ + FunctionCall coveredByLock() { result = lockingFunction } + + /** + * The lock underlying this `LockProtectedControlFlowNode`. + */ + Variable getAProtectingLock() { result = lockingFunction.(LockingOperation).getLock() } +} diff --git a/cpp/common/src/codingstandards/cpp/concurrency/LockingOperation.qll b/cpp/common/src/codingstandards/cpp/concurrency/LockingOperation.qll new file mode 100644 index 0000000000..1dd753d122 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/LockingOperation.qll @@ -0,0 +1,240 @@ +import cpp +import semmle.code.cpp.dataflow.TaintTracking + +abstract class LockingOperation extends FunctionCall { + /** + * Returns the target of the lock underlying this RAII-style lock. + */ + abstract Variable getLock(); + + /** + * Returns the lock underlying this RAII-style lock. + */ + abstract Expr getLockExpr(); + + /** + * Holds if this is a lock operation + */ + abstract predicate isLock(); + + /** + * Holds if this is an unlock operation + */ + abstract predicate isUnlock(); + + /** + * Holds if this locking operation is really a locking operation within a + * designated locking operation. This library assumes the underlying locking + * operations are implemented correctly in that calling a `LockingOperation` + * results in the creation of a singular lock. + */ + predicate isLockingOperationWithinLockingOperation(LockingOperation inner) { + exists(LockingOperation outer | outer.getTarget() = inner.getEnclosingFunction()) + } +} + +/** + * Common base class providing an interface into function call + * based mutex locks. + */ +abstract class MutexFunctionCall extends LockingOperation { + abstract predicate isRecursive(); + + abstract predicate isSpeculativeLock(); + + abstract predicate unlocks(MutexFunctionCall fc); +} + +/** + * Models calls to various mutex types found in CPP. + */ +class CPPMutexFunctionCall extends MutexFunctionCall { + VariableAccess var; + + CPPMutexFunctionCall() { + ( + // the non recursive kinds + getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "mutex") or + getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "timed_mutex") or + getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "shared_timed_mutex") or + // the recursive ones + getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "recursive_mutex") or + getTarget() + .(MemberFunction) + .getDeclaringType() + .hasQualifiedName("std", "recursive_timed_mutex") + ) and + var = getQualifier() + } + + /** + * Holds if this mutex is a recursive mutex. + */ + override predicate isRecursive() { + getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "recursive_mutex") or + getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "recursive_timed_mutex") + } + + /** + * Holds if this `CPPMutexFunctionCall` is a lock. + */ + override predicate isLock() { + not isLockingOperationWithinLockingOperation(this) and + getTarget().getName() = "lock" + } + + /** + * Holds if this `CPPMutexFunctionCall` is a speculative lock, defined as calling + * one of the speculative locking functions such as `try_lock`. + */ + override predicate isSpeculativeLock() { + getTarget().getName() in [ + "try_lock", "try_lock_for", "try_lock_until", "try_lock_shared_for", "try_lock_shared_until" + ] + } + + /** + * Returns the lock to which this `CPPMutexFunctionCall` refers to. + */ + override Variable getLock() { result = getQualifier().(VariableAccess).getTarget() } + + /** + * Returns the qualifier for this `CPPMutexFunctionCall`. + */ + override Expr getLockExpr() { result = var } + + /** + * Holds if this is a `unlock` and *may* unlock the previously locked `MutexFunctionCall`. + * This predicate does not check that the mutex is currently locked. + */ + override predicate unlocks(MutexFunctionCall fc) { + isUnlock() and + fc.getQualifier().(VariableAccess).getTarget() = getQualifier().(VariableAccess).getTarget() + } + + /** + * Holds if this is an unlock call. + */ + override predicate isUnlock() { getTarget().getName() = "unlock" } +} + +/** + * Models calls to various mutex types specialized to C code. + */ +class CMutexFunctionCall extends MutexFunctionCall { + Expr arg; + + CMutexFunctionCall() { + // the non recursive kinds + getTarget().getName() = ["mtx_lock", "mtx_unlock", "mtx_timedlock", "mtx_trylock"] and + arg = getArgument(0) + } + + /** + * Holds if this mutex is a recursive mutex. + */ + override predicate isRecursive() { none() } + + /** + * Holds if this `CMutexFunctionCall` is a lock. + */ + override predicate isLock() { + not isLockingOperationWithinLockingOperation(this) and + getTarget().getName() = ["mtx_lock", "mtx_timedlock", "mtx_trylock"] + } + + /** + * Holds if this `CMutexFunctionCall` is a speculative lock, defined as calling + * one of the speculative locking functions such as `try_lock`. + */ + override predicate isSpeculativeLock() { + getTarget().getName() in ["mtx_timedlock", "mtx_trylock"] + } + + /** + * Returns the `Variable` to which this `CMutexFunctionCall` refers to. For this + * style of lock it can reference a number of different variables. + */ + override Variable getLock() { + exists(VariableAccess va | + TaintTracking::localTaint(DataFlow::exprNode(va), DataFlow::exprNode(getLockExpr())) and + result = va.getTarget() + ) + } + + /** + * Returns the expression for this `CMutexFunctionCall`. + */ + override Expr getLockExpr() { result = arg } + + /** + * Holds if this is a `unlock` and *may* unlock the previously locked `CMutexFunctionCall`. + * This predicate does not check that the mutex is currently locked. + */ + override predicate unlocks(MutexFunctionCall fc) { + isUnlock() and + fc.getLock() = getLock() + } + + /** + * Holds if this is an unlock call. + */ + override predicate isUnlock() { getTarget().getName() = "mtx_unlock" } +} + +/** + * Models a RAII-Style lock. + */ +class RAIIStyleLock extends LockingOperation { + VariableAccess lock; + + RAIIStyleLock() { + ( + getTarget().getDeclaringType().hasQualifiedName("std", "lock_guard") or + getTarget().getDeclaringType().hasQualifiedName("std", "unique_lock") or + getTarget().getDeclaringType().hasQualifiedName("std", "scoped_lock") + ) and + ( + lock = getArgument(0).getAChild*() + or + this instanceof DestructorCall and + exists(RAIIStyleLock constructor | + constructor = getQualifier().(VariableAccess).getTarget().getInitializer().getExpr() and + lock = constructor.getArgument(0).getAChild*() + ) + ) + } + + /** + * Holds if this is a lock operation + */ + override predicate isLock() { + not isLockingOperationWithinLockingOperation(this) and + this instanceof ConstructorCall and + lock = getArgument(0).getAChild*() and + // defer_locks don't cause a lock + not exists(Expr exp | + exp = getArgument(1) and + exp.(VariableAccess) + .getTarget() + .getUnderlyingType() + .(Class) + .hasQualifiedName("std", "defer_lock_t") + ) + } + + /** + * Holds if this is an unlock operation + */ + override predicate isUnlock() { this instanceof DestructorCall } + + /** + * Returns the target of the lock underlying this RAII-style lock. + */ + override Variable getLock() { result = lock.getTarget() } + + /** + * Returns the lock underlying this RAII-style lock. + */ + override Expr getLockExpr() { result = lock } +} diff --git a/cpp/common/src/codingstandards/cpp/concurrency/MutexDestroyer.qll b/cpp/common/src/codingstandards/cpp/concurrency/MutexDestroyer.qll new file mode 100644 index 0000000000..915efc6077 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/MutexDestroyer.qll @@ -0,0 +1,73 @@ +import cpp + +/** + * Models expressions that destroy mutexes. + */ +abstract class MutexDestroyer extends StmtParent { + /** + * Gets the expression that references the mutex being destroyed. + */ + abstract Expr getMutexExpr(); +} + +/** + * Models C style mutex destruction via `mtx_destroy`. + */ +class C11MutexDestroyer extends MutexDestroyer, FunctionCall { + C11MutexDestroyer() { getTarget().getName() = "mtx_destroy" } + + /** + * Returns the `Expr` being destroyed. + */ + override Expr getMutexExpr() { result = getArgument(0) } +} + +/** + * Models a delete expression -- note it is necessary to add this in + * addition to destructors to handle certain implementations of the + * standard library which obscure the destructors of mutexes. + */ +class DeleteMutexDestroyer extends MutexDestroyer { + DeleteMutexDestroyer() { this instanceof DeleteExpr } + + override Expr getMutexExpr() { this.(DeleteExpr).getExpr() = result } +} + +/** + * Models a possible mutex variable that if it goes + * out of scope would destroy an underlying mutex. + */ +class LocalMutexDestroyer extends MutexDestroyer { + Expr assignedValue; + + LocalMutexDestroyer() { + exists(LocalVariable lv | + // static types aren't destroyers + not lv.isStatic() and + // neither are pointers + not lv.getType() instanceof PointerType and + lv.getAnAssignedValue() = assignedValue and + // map the location to the return statements of the + // enclosing function + exists(ReturnStmt rs | + rs.getEnclosingFunction() = assignedValue.getEnclosingFunction() and + rs = this + ) + ) + } + + override Expr getMutexExpr() { result = assignedValue } +} + +/** + * Models implicit or explicit calls to the destructor of a mutex, either via + * a `delete` statement or a variable going out of scope. + */ +class DestructorMutexDestroyer extends MutexDestroyer, DestructorCall { + DestructorMutexDestroyer() { getTarget().getDeclaringType().hasQualifiedName("std", "mutex") } + + /** + * Returns the `Expr` being deleted. + */ + override Expr getMutexExpr() { getQualifier() = result } +} diff --git a/cpp/common/src/codingstandards/cpp/concurrency/ThreadCreation.qll b/cpp/common/src/codingstandards/cpp/concurrency/ThreadCreation.qll new file mode 100644 index 0000000000..4499b993ad --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/ThreadCreation.qll @@ -0,0 +1,62 @@ +import cpp +private import codingstandards.cpp.concurrency.ControlFlow + +/** + * Models a call to a thread constructor via `std::thread`. + */ +class ThreadConstructorCall extends ConstructorCall, ThreadCreationFunction { + Function f; + + ThreadConstructorCall() { + getTarget().getDeclaringType().hasQualifiedName("std", "thread") and + f = getArgument(0).(FunctionAccess).getTarget() + } + + /** + * Returns the function that will be invoked by this `std::thread`. + */ + override Function getFunction() { result = f } + + override ControlFlowNode getNext() { result = getFunction().getEntryPoint() } +} + +/** + * Models a call to a thread creation via `thrd_create` or `pthread_create`. + */ +class CThreadCreateCall extends FunctionCall { + Function f; + int fArgIdx; + + CThreadCreateCall() { + ( + getTarget().getName() = "thrd_create" and + fArgIdx = 1 + or + getTarget().getName() = "pthread_create" and + fArgIdx = 2 + ) and + ( + f = getArgument(fArgIdx).(FunctionAccess).getTarget() or + f = getArgument(fArgIdx).(AddressOfExpr).getOperand().(FunctionAccess).getTarget() + ) + } + + /** + * Returns the function that will be invoked by this thread. + */ + Function getFunction() { result = f } +} + +/** + * Models a call to a thread constructor via `thrd_create`. + */ +class C11ThreadCreateCall extends ThreadCreationFunction, CThreadCreateCall { + C11ThreadCreateCall() { getTarget().getName() = "thrd_create" } + + /** + * Returns the function that will be invoked by this thread. + */ + override Function getFunction() { result = f } + + override ControlFlowNode getNext() { result = getFunction().getEntryPoint() } +} diff --git a/cpp/common/src/codingstandards/cpp/concurrency/ThreadDependentMutex.qll b/cpp/common/src/codingstandards/cpp/concurrency/ThreadDependentMutex.qll new file mode 100644 index 0000000000..f86e94566f --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/ThreadDependentMutex.qll @@ -0,0 +1,246 @@ +import cpp +import semmle.code.cpp.dataflow.TaintTracking +private import codingstandards.cpp.concurrency.ControlFlow +private import codingstandards.cpp.concurrency.ThreadedFunction + +abstract class MutexSource extends FunctionCall { } + +/** + * Models a C++ style mutex. + */ +class CPPMutexSource extends MutexSource, ConstructorCall { + CPPMutexSource() { getTarget().getDeclaringType().hasQualifiedName("std", "mutex") } +} + +/** + * Models a C11 style mutex. + */ +class C11MutexSource extends MutexSource, FunctionCall { + C11MutexSource() { getTarget().hasName("mtx_init") } + + Expr getMutexExpr() { result = getArgument(0) } + + Expr getMutexTypeExpr() { result = getArgument(1) } + + predicate isRecursive() { + exists(EnumConstantAccess recursive | + recursive = getMutexTypeExpr().getAChild*() and + recursive.getTarget().hasName("mtx_recursive") + ) + } +} + +/** + * Models a thread dependent mutex. A thread dependent mutex is a mutex + * that is used by a thread. This dependency is established either by directly + * passing in a mutex or by referencing a mutex that is in the local scope. The utility + * of this class is it captures the `DataFlow::Node` source at which the mutex + * came from. For example, if it is passed in from a local function to a thread. + * This functionality is critical, since it allows one to inspect how the thread + * behaves with respect to the owner of a resource. + * + * To model the myriad ways this can happen, the subclasses of this class are + * responsible for implementing the various usage patterns. + */ +abstract class ThreadDependentMutex extends DataFlow::Node { + DataFlow::Node sink; + + DataFlow::Node getASource() { + // the source is either the thing that declared + // the mutex + result = this + or + // or the thread we are using it in + result = getAThreadSource() + } + + /** + * Gets the dataflow nodes corresponding to thread local usages of the + * dependent mutex. + */ + DataFlow::Node getAThreadSource() { + // here we line up the actual parameter at the thread creation + // site with the formal parameter in the target thread. + // Note that there are differences between the C and C++ versions + // of the argument ordering in the thread creation function. However, + // since the C version only takes one parameter (as opposed to multiple) + // we can simplify this search by considering only the first argument. + exists(FunctionCall fc, Function f, int n | + // Get the argument to which the mutex flowed. + fc.getArgument(n) = sink.asExpr() and + // Get the thread function we are calling. + f = fc.getArgument(0).(FunctionAccess).getTarget() and + // in C++, there is an extra argument to the `std::thread` call + // so we must subtract 1 since this is not passed to the thread. + ( + result = DataFlow::exprNode(f.getParameter(n - 1).getAnAccess()) + or + // In C, only one argument is allowed. Thus IF the flow predicate holds, + // it will be to the first argument + result = DataFlow::exprNode(f.getParameter(0).getAnAccess()) + ) + ) + } + + /** + * Produces the set of dataflow nodes to thread creation for threads + * that are dependent on this mutex. + */ + DataFlow::Node getADependentThreadCreationExpr() { + exists(FunctionCall fc | + fc.getAnArgument() = sink.asExpr() and + result = DataFlow::exprNode(fc) + ) + } + + /** + * Gets a set of usages of this mutex in both the local and thread scope. + * In the case of scoped usage, this also captures typical accesses of variables. + */ + DataFlow::Node getAUsage() { TaintTracking::localTaint(getASource(), result) } +} + +/** + * This class models the type of thread/mutex dependency that is established + * through the typical parameter passing mechanisms found in C++. + */ +class FlowBasedThreadDependentMutex extends ThreadDependentMutex { + FlowBasedThreadDependentMutex() { + // some sort of dataflow, likely through parameter passing. + ThreadDependentMutexFlow::flow(this, sink) + } +} + +/** + * This class models the type of thread/mutex dependency that is established by + * either scope based accesses (e.g., global variables) or block scope differences. + */ +class AccessBasedThreadDependentMutex extends ThreadDependentMutex { + Variable variableSource; + + AccessBasedThreadDependentMutex() { + // encapsulates usages from outside scopes not directly expressed + // in dataflow. + exists(MutexSource mutexSrc, ThreadedFunction f | + DataFlow::exprNode(mutexSrc) = this and + // find a variable that was assigned the mutex + TaintTracking::localTaint(DataFlow::exprNode(mutexSrc), + DataFlow::exprNode(variableSource.getAnAssignedValue())) and + // find all subsequent accesses of that variable that are within a + // function and set those to the sink + exists(VariableAccess va | + va = variableSource.getAnAccess() and + va.getEnclosingFunction() = f and + sink = DataFlow::exprNode(va) + ) + ) + } + + override DataFlow::Node getAUsage() { DataFlow::exprNode(variableSource.getAnAccess()) = result } +} + +/** + * In the typical C thread model, a mutex is a created by a function that is not responsible + * for creating the variable. Thus this class encodes a slightly different semantics + * wherein the usage pattern is that of variables that have been both initialized + * and then subsequently passed into a thread directly. + */ +class DeclarationInitBasedThreadDependentMutex extends ThreadDependentMutex { + Variable variableSource; + + DeclarationInitBasedThreadDependentMutex() { + exists(MutexSource ms, ThreadCreationFunction tcf | + this = DataFlow::exprNode(ms) and + // accessed as a mutex source + TaintTracking::localTaint(DataFlow::exprNode(variableSource.getAnAccess()), + DataFlow::exprNode(ms.getAnArgument())) and + // subsequently passed to a thread creation function (order not strictly + // enforced for performance reasons) + sink = DataFlow::exprNode(tcf.getAnArgument()) and + TaintTracking::localTaint(DataFlow::exprNode(variableSource.getAnAccess()), sink) + ) + } + + override DataFlow::Node getAUsage() { + TaintTracking::localTaint(getASource(), result) or + DataFlow::exprNode(variableSource.getAnAccess()) = result + } + + override DataFlow::Node getASource() { + // the source is either the thing that declared + // the mutex + result = this + or + // or the thread we are using it in + result = getAThreadSource() + } + + DataFlow::Node getSink() { result = sink } + + /** + * Gets the dataflow nodes corresponding to thread local usages of the + * dependent mutex. + */ + override DataFlow::Node getAThreadSource() { + // here we line up the actual parameter at the thread creation + // site with the formal parameter in the target thread. + // Note that there are differences between the C and C++ versions + // of the argument ordering in the thread creation function. However, + // since the C version only takes one parameter (as opposed to multiple) + // we can simplify this search by considering only the first argument. + exists( + FunctionCall fc, Function f, int n // CPP Version + | + fc.getArgument(n) = sink.asExpr() and + f = fc.getArgument(0).(FunctionAccess).getTarget() and + // in C++, there is an extra argument to the `std::thread` call + // so we must subtract 1 since this is not passed to the thread. + result = DataFlow::exprNode(f.getParameter(n - 1).getAnAccess()) + ) + or + exists( + FunctionCall fc, Function f // C Version + | + fc.getAnArgument() = sink.asExpr() and + // in C, the second argument is the function + f = fc.getArgument(1).(FunctionAccess).getTarget() and + // in C, the passed argument is always the zeroth argument + result = DataFlow::exprNode(f.getParameter(0).getAnAccess()) + ) + } +} + +/** + * In the typical C model, another way to use mutexes is to work with global variables + * that can be initialized at various points -- one of which must be inside a thread. + * This class encapsulates this pattern. + */ +class DeclarationInitAccessBasedThreadDependentMutex extends ThreadDependentMutex { + Variable variableSource; + + DeclarationInitAccessBasedThreadDependentMutex() { + exists(MutexSource ms, ThreadedFunction tf, VariableAccess va | + this = DataFlow::exprNode(ms) and + // accessed as a mutex source + TaintTracking::localTaint(DataFlow::exprNode(variableSource.getAnAccess()), + DataFlow::exprNode(ms.getAnArgument())) and + // is accessed somewhere else + va = variableSource.getAnAccess() and + sink = DataFlow::exprNode(va) and + // one of which must be a thread + va.getEnclosingFunction() = tf + ) + } + + override DataFlow::Node getAUsage() { result = DataFlow::exprNode(variableSource.getAnAccess()) } +} + +module ThreadDependentMutexConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node.asExpr() instanceof MutexSource } + + predicate isSink(DataFlow::Node node) { + exists(ThreadCreationFunction f | f.getAnArgument() = node.asExpr()) + } +} + +module ThreadDependentMutexFlow = TaintTracking::Global; diff --git a/cpp/common/src/codingstandards/cpp/concurrency/ThreadSpecificStorage.qll b/cpp/common/src/codingstandards/cpp/concurrency/ThreadSpecificStorage.qll new file mode 100644 index 0000000000..aa7daf972c --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/ThreadSpecificStorage.qll @@ -0,0 +1,59 @@ +import cpp +private import semmle.code.cpp.dataflow.DataFlow +private import codingstandards.cpp.concurrency.ThreadCreation + +/** + * Models calls to thread specific storage function calls. + */ +abstract class ThreadSpecificStorageFunctionCall extends FunctionCall { + /** + * Gets the key to which this call references. + */ + Expr getKey() { getArgument(0) = result } +} + +/** + * Models calls to `tss_get`. + */ +class TSSGetFunctionCall extends ThreadSpecificStorageFunctionCall { + TSSGetFunctionCall() { getTarget().getName() = "tss_get" } +} + +/** + * Models calls to `tss_set`. + */ +class TSSSetFunctionCall extends ThreadSpecificStorageFunctionCall { + TSSSetFunctionCall() { getTarget().getName() = "tss_set" } +} + +/** + * Models calls to `tss_create` + */ +class TSSCreateFunctionCall extends ThreadSpecificStorageFunctionCall { + TSSCreateFunctionCall() { getTarget().getName() = "tss_create" } + + predicate hasDeallocator() { + not exists(MacroInvocation mi, NullMacro nm | + getArgument(1) = mi.getExpr() and + mi = nm.getAnInvocation() + ) + } +} + +/** + * Models calls to `tss_delete` + */ +class TSSDeleteFunctionCall extends ThreadSpecificStorageFunctionCall { + TSSDeleteFunctionCall() { getTarget().getName() = "tss_delete" } +} + +/** + * Gets a call to `DeallocationExpr` that deallocates memory owned by thread specific + * storage. + */ +predicate getAThreadSpecificStorageDeallocationCall(C11ThreadCreateCall tcc, DeallocationExpr dexp) { + exists(TSSGetFunctionCall tsg | + tcc.getFunction().getEntryPoint().getASuccessor*() = tsg and + DataFlow::localFlow(DataFlow::exprNode(tsg), DataFlow::exprNode(dexp.getFreedExpr())) + ) +} diff --git a/cpp/common/src/codingstandards/cpp/concurrency/ThreadWaitDetach.qll b/cpp/common/src/codingstandards/cpp/concurrency/ThreadWaitDetach.qll new file mode 100644 index 0000000000..6898dc54df --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/ThreadWaitDetach.qll @@ -0,0 +1,41 @@ +import cpp + +/** + * Models thread waiting functions. + */ +abstract class ThreadWait extends FunctionCall { } + +/** + * Models a call to a `std::thread` join. + */ +class CPPThreadWait extends ThreadWait { + VariableAccess var; + + CPPThreadWait() { + getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "thread") and + getTarget().getName() = "join" + } +} + +/** + * Models a call to `thrd_join` in C11. + */ +class C11ThreadWait extends ThreadWait { + VariableAccess var; + + C11ThreadWait() { getTarget().getName() = "thrd_join" } +} + +/** + * Models thread detach functions. + */ +abstract class ThreadDetach extends FunctionCall { } + +/** + * Models a call to `thrd_detach` in C11. + */ +class C11ThreadDetach extends ThreadWait { + VariableAccess var; + + C11ThreadDetach() { getTarget().getName() = "thrd_detach" } +} diff --git a/cpp/common/src/codingstandards/cpp/concurrency/ThreadedFunction.qll b/cpp/common/src/codingstandards/cpp/concurrency/ThreadedFunction.qll new file mode 100644 index 0000000000..a8d2c609c5 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/ThreadedFunction.qll @@ -0,0 +1,37 @@ +import cpp +private import codingstandards.cpp.concurrency.ThreadCreation + +/** + * Models a function that may be executed by some thread. + */ +abstract class ThreadedFunctionBase extends Function { + abstract Expr getSpawnExpr(); + + predicate isMultiplySpawned() { getSpawnExpr().getBasicBlock().inLoop() } +} + +final class ThreadedFunction = ThreadedFunctionBase; + +/** + * Models a function that may be executed by some thread via + * C++ standard classes. + */ +class CPPThreadedFunction extends ThreadedFunctionBase { + ThreadConstructorCall tcc; + + CPPThreadedFunction() { tcc.getFunction() = this } + + override Expr getSpawnExpr() { result = tcc } +} + +/** + * Models a function that may be executed by some thread via + * C11 standard functions. + */ +class C11ThreadedFunction extends ThreadedFunctionBase { + C11ThreadCreateCall cc; + + C11ThreadedFunction() { cc.getFunction() = this } + + override Expr getSpawnExpr() { result = cc } +} diff --git a/cpp/common/src/codingstandards/cpp/concurrency/Types.qll b/cpp/common/src/codingstandards/cpp/concurrency/Types.qll new file mode 100644 index 0000000000..3b865d5171 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/Types.qll @@ -0,0 +1,29 @@ +import cpp + +class C11MutexType extends TypedefType { + C11MutexType() { this.hasName("mtx_t") } +} + +class C11ThreadType extends TypedefType { + C11ThreadType() { this.hasName("thrd_t") } +} + +class C11ConditionType extends TypedefType { + C11ConditionType() { this.hasName("cnd_t") } +} + +class C11ThreadStorageType extends TypedefType { + C11ThreadStorageType() { this.hasName("tss_t") } +} + +class C11ThreadingObjectType extends TypedefType { + C11ThreadingObjectType() { + this instanceof C11MutexType + or + this instanceof C11ThreadType + or + this instanceof C11ConditionType + or + this instanceof C11ThreadStorageType + } +} diff --git a/cpp/common/src/codingstandards/cpp/dominance/BehavioralSet.qll b/cpp/common/src/codingstandards/cpp/dominance/BehavioralSet.qll new file mode 100644 index 0000000000..ba42246e73 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/dominance/BehavioralSet.qll @@ -0,0 +1,47 @@ +import cpp +import semmle.code.cpp.controlflow.ControlFlowGraph + +signature class TargetNode extends ControlFlowNode; + +signature module DominatingSetConfigSig { + predicate isTargetBehavior(ControlFlowNode behavior, Target target); + + default predicate isBlockingBehavior(ControlFlowNode behavior, Target target) { + none() + } +} + +/** + * A module to find whether there exists a dominator set for a node which performs a relevant + * behavior. + * + * For instance, we may wish to see that all paths leading to an `abort()` statement include a + * logging call. In this case, the `abort()` statement is the `Target` node, and the config module + * predicate `isTargetBehavior` logging statements. + * + * Additionally, the config may specify `isBlockingBehavior` to prevent searching too far for the + * relevant behavior. For instance, if analyzing that all paths to an `fflush()` call are preceded + * by a write, we should ignore paths from write operations that have already been flushed through + * an intermediary `fflush()` call. + */ +module DominatingBehavioralSet Config> { + + /** + * Holds if this search step can reach the entry or a blocking node, without passing through a + * target behavior, indicating that the target is has no relevant dominator set. + */ + private predicate searchStep(ControlFlowNode node, Target target) { + Config::isBlockingBehavior(node, target) + or + not Config::isTargetBehavior(node, target) and + exists (ControlFlowNode prev | prev = node.getAPredecessor() | + searchStep(prev, target) + ) + } + + predicate isDominatedByBehavior(Target target) { + forex(ControlFlowNode prev | prev = target.getAPredecessor() | + not searchStep(prev, target) + ) + } +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency9.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency9.qll new file mode 100644 index 0000000000..b013bbdabb --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Concurrency9.qll @@ -0,0 +1,146 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype Concurrency9Query = + TPossibleDataRaceBetweenThreadsQuery() or + TThreadResourceDisposedBeforeThreadsJoinedQuery() or + TInvalidOperationOnUnlockedMutexQuery() or + TNonRecursiveMutexRecursivelyLockedQuery() or + TNonRecursiveMutexRecursivelyLockedAuditQuery() or + TConditionVariableUsedWithMultipleMutexesQuery() or + TThreadStorageNotInitializedBeforeUseQuery() or + TThreadStoragePointerInitializedInsideThreadQuery() + +predicate isConcurrency9QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `possibleDataRaceBetweenThreads` query + Concurrency9Package::possibleDataRaceBetweenThreadsQuery() and + queryId = + // `@id` for the `possibleDataRaceBetweenThreads` query + "c/misra/possible-data-race-between-threads" and + ruleId = "DIR-5-1" and + category = "required" + or + query = + // `Query` instance for the `threadResourceDisposedBeforeThreadsJoined` query + Concurrency9Package::threadResourceDisposedBeforeThreadsJoinedQuery() and + queryId = + // `@id` for the `threadResourceDisposedBeforeThreadsJoined` query + "c/misra/thread-resource-disposed-before-threads-joined" and + ruleId = "RULE-22-15" and + category = "required" + or + query = + // `Query` instance for the `invalidOperationOnUnlockedMutex` query + Concurrency9Package::invalidOperationOnUnlockedMutexQuery() and + queryId = + // `@id` for the `invalidOperationOnUnlockedMutex` query + "c/misra/invalid-operation-on-unlocked-mutex" and + ruleId = "RULE-22-17" and + category = "required" + or + query = + // `Query` instance for the `nonRecursiveMutexRecursivelyLocked` query + Concurrency9Package::nonRecursiveMutexRecursivelyLockedQuery() and + queryId = + // `@id` for the `nonRecursiveMutexRecursivelyLocked` query + "c/misra/non-recursive-mutex-recursively-locked" and + ruleId = "RULE-22-18" and + category = "required" + or + query = + // `Query` instance for the `nonRecursiveMutexRecursivelyLockedAudit` query + Concurrency9Package::nonRecursiveMutexRecursivelyLockedAuditQuery() and + queryId = + // `@id` for the `nonRecursiveMutexRecursivelyLockedAudit` query + "c/misra/non-recursive-mutex-recursively-locked-audit" and + ruleId = "RULE-22-18" and + category = "required" + or + query = + // `Query` instance for the `conditionVariableUsedWithMultipleMutexes` query + Concurrency9Package::conditionVariableUsedWithMultipleMutexesQuery() and + queryId = + // `@id` for the `conditionVariableUsedWithMultipleMutexes` query + "c/misra/condition-variable-used-with-multiple-mutexes" and + ruleId = "RULE-22-19" and + category = "required" + or + query = + // `Query` instance for the `threadStorageNotInitializedBeforeUse` query + Concurrency9Package::threadStorageNotInitializedBeforeUseQuery() and + queryId = + // `@id` for the `threadStorageNotInitializedBeforeUse` query + "c/misra/thread-storage-not-initialized-before-use" and + ruleId = "RULE-22-20" and + category = "mandatory" + or + query = + // `Query` instance for the `threadStoragePointerInitializedInsideThread` query + Concurrency9Package::threadStoragePointerInitializedInsideThreadQuery() and + queryId = + // `@id` for the `threadStoragePointerInitializedInsideThread` query + "c/misra/thread-storage-pointer-initialized-inside-thread" and + ruleId = "RULE-22-20" and + category = "mandatory" +} + +module Concurrency9Package { + Query possibleDataRaceBetweenThreadsQuery() { + //autogenerate `Query` type + result = + // `Query` type for `possibleDataRaceBetweenThreads` query + TQueryC(TConcurrency9PackageQuery(TPossibleDataRaceBetweenThreadsQuery())) + } + + Query threadResourceDisposedBeforeThreadsJoinedQuery() { + //autogenerate `Query` type + result = + // `Query` type for `threadResourceDisposedBeforeThreadsJoined` query + TQueryC(TConcurrency9PackageQuery(TThreadResourceDisposedBeforeThreadsJoinedQuery())) + } + + Query invalidOperationOnUnlockedMutexQuery() { + //autogenerate `Query` type + result = + // `Query` type for `invalidOperationOnUnlockedMutex` query + TQueryC(TConcurrency9PackageQuery(TInvalidOperationOnUnlockedMutexQuery())) + } + + Query nonRecursiveMutexRecursivelyLockedQuery() { + //autogenerate `Query` type + result = + // `Query` type for `nonRecursiveMutexRecursivelyLocked` query + TQueryC(TConcurrency9PackageQuery(TNonRecursiveMutexRecursivelyLockedQuery())) + } + + Query nonRecursiveMutexRecursivelyLockedAuditQuery() { + //autogenerate `Query` type + result = + // `Query` type for `nonRecursiveMutexRecursivelyLockedAudit` query + TQueryC(TConcurrency9PackageQuery(TNonRecursiveMutexRecursivelyLockedAuditQuery())) + } + + Query conditionVariableUsedWithMultipleMutexesQuery() { + //autogenerate `Query` type + result = + // `Query` type for `conditionVariableUsedWithMultipleMutexes` query + TQueryC(TConcurrency9PackageQuery(TConditionVariableUsedWithMultipleMutexesQuery())) + } + + Query threadStorageNotInitializedBeforeUseQuery() { + //autogenerate `Query` type + result = + // `Query` type for `threadStorageNotInitializedBeforeUse` query + TQueryC(TConcurrency9PackageQuery(TThreadStorageNotInitializedBeforeUseQuery())) + } + + Query threadStoragePointerInitializedInsideThreadQuery() { + //autogenerate `Query` type + result = + // `Query` type for `threadStoragePointerInitializedInsideThread` query + TQueryC(TConcurrency9PackageQuery(TThreadStoragePointerInitializedInsideThreadQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index bb0e324fd5..6923c1af31 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -14,6 +14,7 @@ import Concurrency4 import Concurrency5 import Concurrency6 import Concurrency8 +import Concurrency9 import Contracts import Contracts1 import Contracts2 @@ -97,6 +98,7 @@ newtype TCQuery = TConcurrency5PackageQuery(Concurrency5Query q) or TConcurrency6PackageQuery(Concurrency6Query q) or TConcurrency8PackageQuery(Concurrency8Query q) or + TConcurrency9PackageQuery(Concurrency9Query q) or TContractsPackageQuery(ContractsQuery q) or TContracts1PackageQuery(Contracts1Query q) or TContracts2PackageQuery(Contracts2Query q) or @@ -180,6 +182,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isConcurrency5QueryMetadata(query, queryId, ruleId, category) or isConcurrency6QueryMetadata(query, queryId, ruleId, category) or isConcurrency8QueryMetadata(query, queryId, ruleId, category) or + isConcurrency9QueryMetadata(query, queryId, ruleId, category) or isContractsQueryMetadata(query, queryId, ruleId, category) or isContracts1QueryMetadata(query, queryId, ruleId, category) or isContracts2QueryMetadata(query, queryId, ruleId, category) or diff --git a/rule_packages/c/Concurrency9.json b/rule_packages/c/Concurrency9.json new file mode 100644 index 0000000000..4bdd6d9a96 --- /dev/null +++ b/rule_packages/c/Concurrency9.json @@ -0,0 +1,158 @@ +{ + "MISRA-C-2012": { + "DIR-5-1": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Threads shall not access the same memory location concurrently without utilization of thread synchronization objects.", + "kind": "problem", + "name": "There shall be no data races between threads", + "precision": "medium", + "severity": "error", + "short_name": "PossibleDataRaceBetweenThreads", + "tags": [ + "correctness", + "concurrency", + "external/misra/c/2012/amendment4" + ] + } + ], + "title": "There shall be no data races between threads" + }, + "RULE-22-15": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Thread synchronization objects and thread-specific storage pointers shall not be destroyed until after all threads accessing them have terminated", + "kind": "problem", + "name": "Thread synchronization objects and thread-specific storage pointers shall not be disposed unsafely", + "precision": "medium", + "severity": "error", + "short_name": "ThreadResourceDisposedBeforeThreadsJoined", + "tags": [ + "correctness", + "concurrency", + "external/misra/c/2012/amendment4" + ] + } + ], + "title": "Thread synchronization objects and thread-specific storage pointers shall not be destroyed until after all threads accessing them have terminated" + }, + "RULE-22-17": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "No thread shall unlock a mutex or call cnd_wait() or cnd_timedwait() for a mutex it has not locked before.", + "kind": "problem", + "name": "No thread shall unlock a mutex or call cnd_wait() or cnd_timedwait() for a mutex it has not locked", + "precision": "high", + "severity": "error", + "short_name": "InvalidOperationOnUnlockedMutex", + "tags": [ + "correctness", + "concurrency", + "external/misra/c/2012/amendment4" + ] + } + ], + "title": "No thread shall unlock a mutex or call cnd_wait() or cnd_timedwait() for a mutex it has not locked before" + }, + "RULE-22-18": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Mutexes initialized with mtx_init() without mtx_recursive shall not be locked by a thread that has previously locked it.", + "kind": "problem", + "name": "Non-recursive mutexes shall not be recursively locked", + "precision": "very-high", + "severity": "error", + "short_name": "NonRecursiveMutexRecursivelyLocked", + "tags": [ + "correctness", + "concurrency", + "external/misra/c/2012/amendment4" + ] + }, + { + "description": "Mutex that may be initialized without mtx_recursive shall not be locked by a thread that has previous may havec locked it.", + "kind": "problem", + "name": "(Audit) Non-recursive mutexes shall not be recursively locked", + "precision": "high", + "severity": "error", + "short_name": "NonRecursiveMutexRecursivelyLockedAudit", + "tags": [ + "correctness", + "concurrency", + "external/misra/c/2012/amendment4", + "audit" + ] + } + ], + "title": "Non-recursive mutexes shall not be recursively locked" + }, + "RULE-22-19": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Standard library functions cnd_wait() and cnd_timedwait() shall specify the same mutex object for each condition object in all calls.", + "kind": "problem", + "name": "A condition variable shall be associated with at most one mutex object", + "precision": "very-high", + "severity": "error", + "short_name": "ConditionVariableUsedWithMultipleMutexes", + "tags": [ + "correctness", + "concurrency", + "external/misra/c/2012/amendment4" + ] + } + ], + "title": "A condition variable shall be associated with at most one mutex object" + }, + "RULE-22-20": { + "properties": { + "obligation": "mandatory" + }, + "queries": [ + { + "description": "Thread specific storage pointers shall be initialized with the standard library functions before using them.", + "kind": "problem", + "name": "Thread-specific storage pointers shall be created before being accessed", + "precision": "high", + "severity": "error", + "short_name": "ThreadStorageNotInitializedBeforeUse", + "tags": [ + "correctness", + "concurrency", + "external/misra/c/2012/amendment4" + ] + }, + { + "description": "Thread specific storage pointers initialized inside of threads may result in indeterministic state.", + "kind": "problem", + "name": "Thread specific storage pointers shall be initialized deterministically", + "precision": "very-high", + "severity": "recommendation", + "short_name": "ThreadStoragePointerInitializedInsideThread", + "tags": [ + "readability", + "maintainability", + "concurrency", + "external/misra/c/2012/amendment4" + ] + } + ], + "title": "Thread-specific storage pointers shall be created before being accessed" + } + } +} \ No newline at end of file diff --git a/rules.csv b/rules.csv index cb0551b586..44c2f00357 100644 --- a/rules.csv +++ b/rules.csv @@ -617,7 +617,7 @@ c,MISRA-C-2012,DIR-4-12,Yes,Required,,,Dynamic memory allocation shall not be us c,MISRA-C-2012,DIR-4-13,No,Advisory,,,Functions which are designed to provide operations on a resource should be called in an appropriate sequence,,,,"Rule 22.1, 22.2 and 22.6 cover aspects of this rule. In other cases this is a design issue and needs to be checked manually." c,MISRA-C-2012,DIR-4-14,Yes,Required,,,The validity of values received from external sources shall be checked,,Contracts8,Hard,This is supported by CodeQLs default C security queries. c,MISRA-C-2012,DIR-4-15,Yes,Required,,,Evaluation of floating-point expressions shall not lead to the undetected generation of infinities and NaNs,FLP32-C and FLP04-C,FloatingTypes2,Medium, -c,MISRA-C-2012,DIR-5-1,Yes,Required,,,There shall be no data races between threads,CON43-C and CON32-C,Concurrency7,Very Hard, +c,MISRA-C-2012,DIR-5-1,Yes,Required,,,There shall be no data races between threads,CON43-C and CON32-C,Concurrency9,Very Hard, c,MISRA-C-2012,DIR-5-2,Yes,Required,,,There shall be no deadlocks between threads,CON35-C,Concurrency6,Import, c,MISRA-C-2012,DIR-5-3,Yes,Required,,,There shall be no dynamic thread creation,,Concurrency6,Easy, c,MISRA-C-2012,RULE-1-1,No,Required,,,"The program shall contain no violations of the standard C syntax and constraints, and shall not exceed the implementation's translation limits",,,Easy,"This should be checked via the compiler output, rather than CodeQL, which adds unnecessary steps." @@ -806,12 +806,12 @@ c,MISRA-C-2012,RULE-22-11,Yes,Required,,,A thread that was previously either joi c,MISRA-C-2012,RULE-22-12,Yes,Mandatory,,,"Thread objects, thread synchronization objects, and thread-specific storage pointers shall only be accessed by the appropriate Standard Library functions",,Concurrency8,Medium, c,MISRA-C-2012,RULE-22-13,Yes,Required,,,"Thread objects, thread synchronization objects, and thread specific storage pointers shall have appropriate storage duration",EXP54-CPP and CON34-C,Concurrency8,Medium, c,MISRA-C-2012,RULE-22-14,Yes,Mandatory,,,Thread synchronization objects shall be initialized before being accessed,EXP53-CPP,Concurrency8,Hard, -c,MISRA-C-2012,RULE-22-15,Yes,Required,,,Thread synchronization objects and thread-specific storage pointers shall not be destroyed until after all threads accessing them have terminated,,Concurrency7,Hard, +c,MISRA-C-2012,RULE-22-15,Yes,Required,,,Thread synchronization objects and thread-specific storage pointers shall not be destroyed until after all threads accessing them have terminated,,Concurrency9,Hard, c,MISRA-C-2012,RULE-22-16,Yes,Required,,,All mutex objects locked by a thread shall be explicitly unlocked by the same thread,MEM51-CPP,Concurrency8,Hard, -c,MISRA-C-2012,RULE-22-17,Yes,Required,,,No thread shall unlock a mutex or call cnd_wait() or cnd_timedwait() for a mutex it has not locked before,Rule 22.2,Concurrency7,Medium, -c,MISRA-C-2012,RULE-22-18,Yes,Required,,,Non-recursive mutexes shall not be recursively locked,CON56-CPP,Concurrency7,Medium, -c,MISRA-C-2012,RULE-22-19,Yes,Required,,,A condition variable shall be associated with at most one mutex object,,Concurrency7,Medium, -c,MISRA-C-2012,RULE-22-20,Yes,Mandatory,,,Thread-specific storage pointers shall be created before being accessed,,Concurrency7,Hard, +c,MISRA-C-2012,RULE-22-17,Yes,Required,,,No thread shall unlock a mutex or call cnd_wait() or cnd_timedwait() for a mutex it has not locked before,Rule 22.2,Concurrency9,Medium, +c,MISRA-C-2012,RULE-22-18,Yes,Required,,,Non-recursive mutexes shall not be recursively locked,CON56-CPP,Concurrency9,Medium, +c,MISRA-C-2012,RULE-22-19,Yes,Required,,,A condition variable shall be associated with at most one mutex object,,Concurrency9,Medium, +c,MISRA-C-2012,RULE-22-20,Yes,Mandatory,,,Thread-specific storage pointers shall be created before being accessed,,Concurrency9,Hard, c,MISRA-C-2012,RULE-23-1,Yes,Advisory,,,A generic selection should only be expanded from a macro,,Generics,Medium, c,MISRA-C-2012,RULE-23-2,Yes,Required,,,A generic selection that is not expanded from a macro shall not contain potential side effects in the controlling expression,,Generics,Hard, c,MISRA-C-2012,RULE-23-3,Yes,Advisory,,,A generic selection should contain at least one non-default association,,Generics,Easy, From 9e35e593bd116a22ae8a9f1e2de2fc41a75c9072 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 18 Feb 2025 23:07:52 +0000 Subject: [PATCH 218/370] Deviations: use getADeviationRecord Deviation code identifier markers can have multiple records. --- .../cpp/deviations/CodeIdentifierDeviation.qll | 12 ++++++------ .../codingstandards/cpp/deviations/Deviations.qll | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll index 9a694ccc8f..310a2b678b 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll @@ -224,7 +224,7 @@ class DeviationAttribute extends StdAttribute { "\"" + record.getCodeIdentifier() + "\"" = this.getAnArgument().getValueText() } - DeviationRecord getDeviationRecord() { result = record } + DeviationRecord getADeviationRecord() { result = record } pragma[nomagic] Element getASuppressedElement() { @@ -296,12 +296,12 @@ newtype TCodeIndentifierDeviation = endComment.getLocation().hasLocationInfo(filepath, suppressedEndLine, _, _, _) } or TCodeIdentifierDeviation(DeviationRecord record, DeviationAttribute attribute) { - attribute.getDeviationRecord() = record + attribute.getADeviationRecord() = record } class CodeIdentifierDeviation extends TCodeIndentifierDeviation { /** The deviation record associated with the deviation comment. */ - DeviationRecord getDeviationRecord() { + DeviationRecord getADeviationRecord() { this = TSingleLineDeviation(result, _, _, _) or this = TMultiLineDeviation(result, _, _, _, _, _) @@ -341,21 +341,21 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation { exists(int suppressedLine | this = TSingleLineDeviation(_, _, filepath, suppressedLine) and result = - "Deviation record " + getDeviationRecord() + " applied to " + filepath + " Line " + + "Deviation record " + getADeviationRecord() + " applied to " + filepath + " Line " + suppressedLine ) or exists(int suppressedStartLine, int suppressedEndLine | this = TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine) and result = - "Deviation record " + getDeviationRecord() + " applied to " + filepath + " Line" + + "Deviation record " + getADeviationRecord() + " applied to " + filepath + " Line" + suppressedStartLine + ":" + suppressedEndLine ) ) or exists(DeviationAttribute attribute | this = TCodeIdentifierDeviation(_, attribute) and - result = "Deviation record " + getDeviationRecord() + " applied to " + attribute + result = "Deviation record " + getADeviationRecord() + " applied to " + attribute ) } } diff --git a/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll b/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll index 434d6988e9..e8c030cdd4 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/Deviations.qll @@ -221,7 +221,7 @@ class DeviationRecord extends XmlElement { } /** Gets a code identifier deviation in code which starts or ends with the code identifier comment. */ - CodeIdentifierDeviation getACodeIdentifierDeviation() { this = result.getDeviationRecord() } + CodeIdentifierDeviation getACodeIdentifierDeviation() { this = result.getADeviationRecord() } /** Gets the `rule-id` specified for this record, if any. */ private string getRawRuleId() { result = getAChild("rule-id").getTextValue() } From b273d0f66fbf252dcc5ab8bb865285fd79bdd3ed Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 18 Feb 2025 23:12:11 +0000 Subject: [PATCH 219/370] Deviations: Update expected tests --- .../deviations_basic_test/TypeLongDoubleUsed.expected | 2 +- .../deviations/deviations_basic_test/UnusedReturnValue.expected | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected index 172b623195..f2cfd03dc6 100644 --- a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected +++ b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected @@ -1,7 +1,7 @@ | attribute_syntax.cpp:6:15:6:17 | dd1 | Use of long double type. | | attribute_syntax.cpp:21:15:21:17 | d10 | Use of long double type. | | attribute_syntax.cpp:29:15:29:17 | d14 | Use of long double type. | -| attribute_syntax.cpp:33:20:33:22 | d16 | Use of long double type. | +| attribute_syntax.cpp:34:20:34:22 | d16 | Use of long double type. | | attribute_syntax.cpp:55:15:55:16 | d1 | Use of long double type. | | attribute_syntax.cpp:57:17:57:18 | d2 | Use of long double type. | | attribute_syntax.cpp:60:17:60:18 | d3 | Use of long double type. | diff --git a/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected b/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected index 120337ffdc..fc7af4b197 100644 --- a/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected +++ b/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.expected @@ -4,7 +4,7 @@ | attribute_syntax.cpp:24:5:24:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | | attribute_syntax.cpp:26:5:26:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | | attribute_syntax.cpp:30:3:30:6 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | -| attribute_syntax.cpp:41:3:41:6 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | +| attribute_syntax.cpp:42:3:42:6 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | | attribute_syntax.cpp:49:5:49:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | | attribute_syntax.cpp:61:5:61:8 | call to getZ | Return value from call to $@ is unused. | attribute_syntax.cpp:1:5:1:8 | getZ | getZ | | main.cpp:12:3:12:6 | call to getX | Return value from call to $@ is unused. | main.cpp:8:5:8:8 | getX | getX | From 3eecfa05ec5bea6900fbf149f4a3e070b4517afe Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 18 Feb 2025 20:55:16 -0800 Subject: [PATCH 220/370] Update StdFunctionOrMacro with feedback --- .../RULE-9-7/UninitializedAtomicObject.ql | 8 +---- .../cpp/StdFunctionOrMacro.qll | 29 +++++++++---------- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql b/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql index b6e8bc82bc..dfb096189f 100644 --- a/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql +++ b/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql @@ -30,14 +30,8 @@ class ThreadSpawningFunction extends Function { } } -private string atomicInit() { result = "atomic_init" } - class AtomicInitAddressOfExpr extends AddressOfExpr { - AtomicInitAddressOfExpr() { - exists(StdFunctionOrMacro::Call c | - this = c.getArgument(0) - ) - } + AtomicInitAddressOfExpr() { exists(AtomicInitCall c | this = c.getArgument(0)) } } ControlFlowNode getARequiredInitializationPoint(LocalScopeVariable v) { diff --git a/cpp/common/src/codingstandards/cpp/StdFunctionOrMacro.qll b/cpp/common/src/codingstandards/cpp/StdFunctionOrMacro.qll index 5ae370183d..1067b7ad09 100644 --- a/cpp/common/src/codingstandards/cpp/StdFunctionOrMacro.qll +++ b/cpp/common/src/codingstandards/cpp/StdFunctionOrMacro.qll @@ -31,30 +31,28 @@ import cpp as cpp +private string atomicInit() { result = "atomic_init" } + +class AtomicInitCall = StdFunctionOrMacro::Call; + /** Specify the name of your function as a predicate */ -signature string getName(); +private signature string getName(); /** Signature module to implement custom argument resolution behavior in expanded macros */ -signature module InferMacroExpansionArguments { +private signature module InferMacroExpansionArguments { bindingset[mi, argumentIdx] cpp::Expr inferArgument(cpp::MacroInvocation mi, int argumentIdx); } -/** Assume all subexpressions of an expanded macro may be the result of any ith argument */ -module NoMacroExpansionInference implements InferMacroExpansionArguments { - bindingset[mi, argumentIdx] - cpp::Expr inferArgument(cpp::MacroInvocation mi, int argumentIdx) { - result.getParent*() = mi.getExpr() - } -} - /** Assume macro `f(x, y, ...)` expands to `__c11_f(x, y, ...)`. */ -module C11FunctionWrapperMacro implements InferMacroExpansionArguments { +private module C11FunctionWrapperMacro implements InferMacroExpansionArguments { bindingset[mi, argumentIdx] cpp::Expr inferArgument(cpp::MacroInvocation mi, int argumentIdx) { - if mi.getExpr().(cpp::FunctionCall).getTarget().hasName("__c11_" + mi.getMacroName()) - then result = mi.getExpr().(cpp::FunctionCall).getArgument(argumentIdx) - else result = NoMacroExpansionInference::inferArgument(mi, argumentIdx) + exists(cpp::FunctionCall fc | + fc = mi.getExpr() and + fc.getTarget().hasName("__c11_" + mi.getMacroName()) and + result = mi.getExpr().(cpp::FunctionCall).getArgument(argumentIdx) + ) } } @@ -72,7 +70,8 @@ module C11FunctionWrapperMacro implements InferMacroExpansionArguments { * select c.getArgument(0) * ``` */ -module StdFunctionOrMacro { +private module StdFunctionOrMacro +{ final private class Expr = cpp::Expr; final private class FunctionCall = cpp::FunctionCall; From 42adff5fe8890f07a4f736a2f4a6d9be671bba11 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 18 Feb 2025 21:14:25 -0800 Subject: [PATCH 221/370] Formatting & json validation --- c/common/src/codingstandards/c/SubObjects.qll | 10 +++------- .../c/initialization/GlobalInitializationAnalysis.qll | 2 +- rule_packages/c/Concurrency9.json | 4 ++-- schemas/rule-package.schema.json | 1 + 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/c/common/src/codingstandards/c/SubObjects.qll b/c/common/src/codingstandards/c/SubObjects.qll index d7aa1e976b..282b0fb5eb 100644 --- a/c/common/src/codingstandards/c/SubObjects.qll +++ b/c/common/src/codingstandards/c/SubObjects.qll @@ -44,12 +44,10 @@ class SubObject extends TSubObject { /** * Holds for object roots and for member accesses on that root, not for array accesses. - * + * * This is useful for cases where we do not wish to treat `x[y]` and `x[z]` as the same object. */ - predicate isPrecise() { - not getParent*() = TObjectIndex(_) - } + predicate isPrecise() { not getParent*() = TObjectIndex(_) } SubObject getParent() { exists(SubObject struct, MemberVariable m | @@ -79,9 +77,7 @@ class SubObject extends TSubObject { result.(ArrayExpr).getArrayBase() = getParent().getAnAccess() } - AddressOfExpr getAnAddressOfExpr() { - result.getOperand() = this.getAnAccess() - } + AddressOfExpr getAnAddressOfExpr() { result.getOperand() = this.getAnAccess() } ObjectIdentity getRootIdentity() { exists(ObjectIdentity i | diff --git a/c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll b/c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll index d2974f9924..90d0a4630a 100644 --- a/c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll +++ b/c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll @@ -4,7 +4,7 @@ import codingstandards.cpp.Concurrency import codingstandards.cpp.Type signature module GlobalInitializationAnalysisConfigSig { - /** A function which is not called or started as a thread */ + /** A function which is not called or started as a thread */ default predicate isRootFunction(Function f) { not exists(Function f2 | f2.calls(f)) and not f instanceof ThreadedFunction diff --git a/rule_packages/c/Concurrency9.json b/rule_packages/c/Concurrency9.json index 4bdd6d9a96..39c5cc58a8 100644 --- a/rule_packages/c/Concurrency9.json +++ b/rule_packages/c/Concurrency9.json @@ -27,7 +27,7 @@ }, "queries": [ { - "description": "Thread synchronization objects and thread-specific storage pointers shall not be destroyed until after all threads accessing them have terminated", + "description": "Thread synchronization objects and thread-specific storage pointers shall not be destroyed until after all threads accessing them have terminated.", "kind": "problem", "name": "Thread synchronization objects and thread-specific storage pointers shall not be disposed unsafely", "precision": "medium", @@ -92,7 +92,7 @@ "correctness", "concurrency", "external/misra/c/2012/amendment4", - "audit" + "external/misra/audit" ] } ], diff --git a/schemas/rule-package.schema.json b/schemas/rule-package.schema.json index 64fac6f396..b4f729afe2 100644 --- a/schemas/rule-package.schema.json +++ b/schemas/rule-package.schema.json @@ -342,6 +342,7 @@ "external/autosar/strict", "scope/single-translation-unit", "scope/system", + "external/misra/audit", "external/misra/c/2012/third-edition-first-revision", "external/misra/c/2012/amendment2", "external/misra/c/2012/amendment3", From 96171eeea1df7f033c7fc03c75804d7113aa1d7f Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 18 Feb 2025 21:16:16 -0800 Subject: [PATCH 222/370] cpp format --- .../cpp/dominance/BehavioralSet.qll | 43 ++++++++----------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/dominance/BehavioralSet.qll b/cpp/common/src/codingstandards/cpp/dominance/BehavioralSet.qll index ba42246e73..8609e3213b 100644 --- a/cpp/common/src/codingstandards/cpp/dominance/BehavioralSet.qll +++ b/cpp/common/src/codingstandards/cpp/dominance/BehavioralSet.qll @@ -4,44 +4,37 @@ import semmle.code.cpp.controlflow.ControlFlowGraph signature class TargetNode extends ControlFlowNode; signature module DominatingSetConfigSig { - predicate isTargetBehavior(ControlFlowNode behavior, Target target); + predicate isTargetBehavior(ControlFlowNode behavior, Target target); - default predicate isBlockingBehavior(ControlFlowNode behavior, Target target) { - none() - } + default predicate isBlockingBehavior(ControlFlowNode behavior, Target target) { none() } } /** * A module to find whether there exists a dominator set for a node which performs a relevant * behavior. - * + * * For instance, we may wish to see that all paths leading to an `abort()` statement include a * logging call. In this case, the `abort()` statement is the `Target` node, and the config module * predicate `isTargetBehavior` logging statements. - * + * * Additionally, the config may specify `isBlockingBehavior` to prevent searching too far for the * relevant behavior. For instance, if analyzing that all paths to an `fflush()` call are preceded * by a write, we should ignore paths from write operations that have already been flushed through * an intermediary `fflush()` call. */ module DominatingBehavioralSet Config> { + /** + * Holds if this search step can reach the entry or a blocking node, without passing through a + * target behavior, indicating that the target is has no relevant dominator set. + */ + private predicate searchStep(ControlFlowNode node, Target target) { + Config::isBlockingBehavior(node, target) + or + not Config::isTargetBehavior(node, target) and + exists(ControlFlowNode prev | prev = node.getAPredecessor() | searchStep(prev, target)) + } - /** - * Holds if this search step can reach the entry or a blocking node, without passing through a - * target behavior, indicating that the target is has no relevant dominator set. - */ - private predicate searchStep(ControlFlowNode node, Target target) { - Config::isBlockingBehavior(node, target) - or - not Config::isTargetBehavior(node, target) and - exists (ControlFlowNode prev | prev = node.getAPredecessor() | - searchStep(prev, target) - ) - } - - predicate isDominatedByBehavior(Target target) { - forex(ControlFlowNode prev | prev = target.getAPredecessor() | - not searchStep(prev, target) - ) - } -} \ No newline at end of file + predicate isDominatedByBehavior(Target target) { + forex(ControlFlowNode prev | prev = target.getAPredecessor() | not searchStep(prev, target)) + } +} From 2f619a4a82e025154b03fdbf86a77931041a1445 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 20 Feb 2025 00:26:53 -0800 Subject: [PATCH 223/370] Fix performance issue in ResourceLeakAnalysis.qll --- .../codingstandards/cpp/resources/ResourceLeakAnalysis.qll | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll b/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll index 7d767b5cb4..d1c1a369ef 100644 --- a/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll +++ b/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll @@ -1,6 +1,6 @@ import cpp import semmle.code.cpp.dataflow.DataFlow -import semmle.code.cpp.valuenumbering.GlobalValueNumbering +import semmle.code.cpp.valuenumbering.HashCons import semmle.code.cpp.controlflow.Dominance import codeql.util.Boolean @@ -40,13 +40,14 @@ signature module ResourceLeakConfigSig { predicate isFree(ControlFlowNode node, DataFlow::Node resource); + bindingset[node] default DataFlow::Node getAnAlias(DataFlow::Node node) { DataFlow::localFlow(node, result) or exists(Expr current, Expr after | current in [node.asExpr(), node.asDefiningArgument()] and after in [result.asExpr(), result.asDefiningArgument()] and - globalValueNumber(current) = globalValueNumber(after) and + hashCons(current) = hashCons(after) and strictlyDominates(current, after) ) } From 1c86573cb785615a5e050b4556dc98b1209df743 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 20 Feb 2025 17:48:08 -0800 Subject: [PATCH 224/370] Remove getAnAliasRecursive() --- c/misra/test/rules/RULE-22-16/test.c | 8 ++++++++ .../cpp/resources/ResourceLeakAnalysis.qll | 15 +-------------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/c/misra/test/rules/RULE-22-16/test.c b/c/misra/test/rules/RULE-22-16/test.c index 00764645a4..d0d4f6ddcd 100644 --- a/c/misra/test/rules/RULE-22-16/test.c +++ b/c/misra/test/rules/RULE-22-16/test.c @@ -104,4 +104,12 @@ void f15(int p) { } mtx_unlock(&m); } +} + +void f16(int p) { + mtx_t* ptr; + mtx_t *ptr_m1 = ptr; + mtx_t *ptr_m2 = ptr; + mtx_lock(ptr_m1); // COMPLIANT[FALSE_POSITIVE] + mtx_unlock(ptr_m2); } \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll b/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll index d1c1a369ef..3dd61e934d 100644 --- a/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll +++ b/cpp/common/src/codingstandards/cpp/resources/ResourceLeakAnalysis.qll @@ -64,19 +64,6 @@ module ResourceLeak { Config::isAllocate(cfgNode, resource) } - /** - * Get an alias of a resource, and aliases of nodes that are aliased by a resource. - */ - private DataFlow::Node getAnAliasRecursive(DataFlow::Node node) { - result = Config::getAnAlias(node) and - Config::isAllocate(_, node) - or - exists(DataFlow::Node parent | - node = getAnAliasRecursive(parent) and - result = Config::getAnAlias(parent) - ) - } - private predicate isLeakedAtControlPoint(TResource resource, ControlFlowNode cfgNode) { // Holds if this control point is where the resource was allocated (and therefore not freed). resource = TJustResource(_, cfgNode) @@ -86,7 +73,7 @@ module ResourceLeak { isLeakedAtControlPoint(resource, cfgNode.getAPredecessor()) and not exists(DataFlow::Node freed, DataFlow::Node resourceNode | Config::isFree(cfgNode, freed) and - freed = getAnAliasRecursive(resourceNode) and + freed = Config::getAnAlias(resourceNode) and resource = TJustResource(resourceNode, _) ) } From 56f2996bb0758fe693c87cf87d645d975ae0ec1a Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 20 Feb 2025 18:21:12 -0800 Subject: [PATCH 225/370] Add change note --- .../2025-02-20-rule-22-16-update-aliasing-for-performance.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 change_notes/2025-02-20-rule-22-16-update-aliasing-for-performance.md diff --git a/change_notes/2025-02-20-rule-22-16-update-aliasing-for-performance.md b/change_notes/2025-02-20-rule-22-16-update-aliasing-for-performance.md new file mode 100644 index 0000000000..80ff92748f --- /dev/null +++ b/change_notes/2025-02-20-rule-22-16-update-aliasing-for-performance.md @@ -0,0 +1,3 @@ + - `RULE-22-16`, `ERR57-CPP`, `A15-1-4` - `MutexObjectsNotAlwaysUnlocked.ql`, `DoNotLeakResourcesWhenHandlingExceptions.ql`, `ValidResourcesStateBeforeThrow.ql`: + - Shared module `ResourceLeakAnalysis.qll` changed to not get aliases recursively for simplicity and improved performance. The recent update to these queries had logic intending to handle the case where an allocation node is an alias of a parent node, and the free operation releases that parent node. However, the behavior was incorrectly defined and not working, and in the presence of performance issues this behavior has been removed. + - (`RULE-22-16` only) The alias behavior has been updated to compare expressions with `HashCons` instead of `GlobalValueNumbering` for higher performance. GVN is more expensive generally, seemed to introduce low performance joins secondarily, and is stricter than `HashCons` in a contravening position, meaning a stricter analysis introduces a higher likelihood of false positives. \ No newline at end of file From 81663048818818eee39004e9d85f25a43ecad6ae Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 20 Feb 2025 18:48:40 -0800 Subject: [PATCH 226/370] format new test case --- c/misra/test/rules/RULE-22-16/test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/misra/test/rules/RULE-22-16/test.c b/c/misra/test/rules/RULE-22-16/test.c index d0d4f6ddcd..c97fb3d588 100644 --- a/c/misra/test/rules/RULE-22-16/test.c +++ b/c/misra/test/rules/RULE-22-16/test.c @@ -107,7 +107,7 @@ void f15(int p) { } void f16(int p) { - mtx_t* ptr; + mtx_t *ptr; mtx_t *ptr_m1 = ptr; mtx_t *ptr_m2 = ptr; mtx_lock(ptr_m1); // COMPLIANT[FALSE_POSITIVE] From 5a5f8b78901ff01ac12714b4c36576b5a23edce9 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 20 Feb 2025 22:55:24 -0800 Subject: [PATCH 227/370] Commit changed test expectations --- .../test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.expected | 1 + 1 file changed, 1 insertion(+) diff --git a/c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.expected b/c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.expected index dbee52ed58..46a295d75f 100644 --- a/c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.expected +++ b/c/misra/test/rules/RULE-22-16/MutexObjectsNotAlwaysUnlocked.expected @@ -7,3 +7,4 @@ WARNING: module 'DataFlow' has been deprecated and may be removed in future (Mut | test.c:72:3:72:10 | call to mtx_lock | Mutex 'g1' is locked here and may not always be subsequently unlocked. | | test.c:79:3:79:10 | call to mtx_lock | Mutex 'm' is locked here and may not always be subsequently unlocked. | | test.c:101:5:101:12 | call to mtx_lock | Mutex 'm' is locked here and may not always be subsequently unlocked. | +| test.c:113:3:113:10 | call to mtx_lock | Mutex 'ptr_m1' is locked here and may not always be subsequently unlocked. | From 614c7ab925faab73b9cf1aeb51a43c8cdf62b679 Mon Sep 17 00:00:00 2001 From: Luke Cartey <5377966+lcartey@users.noreply.github.com> Date: Wed, 5 Mar 2025 09:31:29 +0000 Subject: [PATCH 228/370] Update change_notes/2025-02-17-iofstream-performance.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- change_notes/2025-02-17-iofstream-performance.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change_notes/2025-02-17-iofstream-performance.md b/change_notes/2025-02-17-iofstream-performance.md index 8a0be4c3ac..8e566d3778 100644 --- a/change_notes/2025-02-17-iofstream-performance.md +++ b/change_notes/2025-02-17-iofstream-performance.md @@ -1,2 +1,2 @@ - - `A27-0-3`, `FIO309-C` `FIO50-CPP`, `RULE-30-0-2` - `InterleavedInputOutputWithoutFlush.ql`, `DoNotAlternatelyIOFromStreamWithoutPositioning.ql`,`InterleavedInputOutputWithoutPosition.ql`, `ReadsAndWritesOnStreamNotSeparatedByPositioning.ql`: + - `A27-0-3`, `FIO309-C`, `FIO50-CPP`, `RULE-30-0-2` - `InterleavedInputOutputWithoutFlush.ql`, `DoNotAlternatelyIOFromStreamWithoutPositioning.ql`, `InterleavedInputOutputWithoutPosition.ql`, `ReadsAndWritesOnStreamNotSeparatedByPositioning.ql`: - Reduce evaluation time on complex codebases. \ No newline at end of file From 70c776ae2148b7b4a66134ba9c9c47846d8345d0 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 9 Mar 2025 11:24:54 +0000 Subject: [PATCH 229/370] RULE-8-7: Restructure test Move single translation unit items into the translation unit, not the shared header. --- .../RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected | 6 +++--- c/misra/test/rules/RULE-8-7/test.c | 3 +++ c/misra/test/rules/RULE-8-7/test.h | 5 +---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected b/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected index b6a53071d9..fb0b975e88 100644 --- a/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected +++ b/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected @@ -1,3 +1,3 @@ -| test.h:2:12:2:13 | i1 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:4:3:4:4 | i1 | i1 | -| test.h:3:5:3:6 | i2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:5:3:5:4 | i2 | i2 | -| test.h:5:13:5:14 | f2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:7:3:7:4 | call to f2 | call to f2 | +| test.c:2:5:2:6 | i2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:8:3:8:4 | i2 | i2 | +| test.h:2:12:2:13 | i1 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:7:3:7:4 | i1 | i1 | +| test.h:4:13:4:14 | f2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:10:3:10:4 | call to f2 | call to f2 | diff --git a/c/misra/test/rules/RULE-8-7/test.c b/c/misra/test/rules/RULE-8-7/test.c index b2cc2a0684..5b83445944 100644 --- a/c/misra/test/rules/RULE-8-7/test.c +++ b/c/misra/test/rules/RULE-8-7/test.c @@ -1,4 +1,7 @@ #include "test.h" +int i2; // NON_COMPLIANT - accessed one translation unit +static void f3(); // COMPLIANT - internal linkage +extern void f3(); // COMPLIANT - internal linkage void f() { i = 0; i1 = 0; diff --git a/c/misra/test/rules/RULE-8-7/test.h b/c/misra/test/rules/RULE-8-7/test.h index 692bb8e3db..218ec18c23 100644 --- a/c/misra/test/rules/RULE-8-7/test.h +++ b/c/misra/test/rules/RULE-8-7/test.h @@ -1,7 +1,4 @@ extern int i; // COMPLIANT - accessed multiple translation units extern int i1; // NON_COMPLIANT - accessed one translation unit -int i2; // NON_COMPLIANT - accessed one translation unit extern void f1(); // COMPLIANT - accessed multiple translation units -extern void f2(); // NON_COMPLIANT - accessed one translation unit -static void f3(); // COMPLIANT - internal linkage -extern void f3(); // COMPLIANT - internal linkage \ No newline at end of file +extern void f2(); // NON_COMPLIANT - accessed one translation unit \ No newline at end of file From 32fd091717729020734010580bf4b5775851b765 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 9 Mar 2025 11:28:46 +0000 Subject: [PATCH 230/370] RULE-8-7: Add appropriate definitions to test Ensure definitions occur in one translation unit only. --- .../ShouldNotBeDefinedWithExternalLinkage.expected | 6 +++--- c/misra/test/rules/RULE-8-7/test.c | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected b/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected index fb0b975e88..5f04b41ac0 100644 --- a/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected +++ b/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected @@ -1,3 +1,3 @@ -| test.c:2:5:2:6 | i2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:8:3:8:4 | i2 | i2 | -| test.h:2:12:2:13 | i1 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:7:3:7:4 | i1 | i1 | -| test.h:4:13:4:14 | f2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:10:3:10:4 | call to f2 | call to f2 | +| test.c:3:5:3:6 | i1 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:10:3:10:4 | i1 | i1 | +| test.c:4:5:4:6 | i2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:11:3:11:4 | i2 | i2 | +| test.c:6:6:6:7 | f2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:13:3:13:4 | call to f2 | call to f2 | diff --git a/c/misra/test/rules/RULE-8-7/test.c b/c/misra/test/rules/RULE-8-7/test.c index 5b83445944..dc59be7394 100644 --- a/c/misra/test/rules/RULE-8-7/test.c +++ b/c/misra/test/rules/RULE-8-7/test.c @@ -1,7 +1,10 @@ #include "test.h" -int i2; // NON_COMPLIANT - accessed one translation unit -static void f3(); // COMPLIANT - internal linkage -extern void f3(); // COMPLIANT - internal linkage +int i = 0; +int i1 = 0; +int i2; // NON_COMPLIANT - accessed one translation unit +void f1() {} // Definition +void f2() {} // Definition +static void f3() {}; // COMPLIANT - internal linkage void f() { i = 0; i1 = 0; From 39f7c94a661c90c6903e092885e3c0d2b095330e Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 9 Mar 2025 11:34:36 +0000 Subject: [PATCH 231/370] RULE-8-7: Require the reference to exist in the same TU The translation unit of the definition needs to be the same as the translation unit of the reference, otherwise it is not eligible for internal linkage. --- .../rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql | 4 +++- .../RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected | 6 +++--- c/misra/test/rules/RULE-8-7/test.c | 1 + c/misra/test/rules/RULE-8-7/test.h | 3 ++- c/misra/test/rules/RULE-8-7/test1.c | 1 + 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql b/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql index faa915fdd5..7b882821b8 100644 --- a/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql +++ b/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql @@ -51,6 +51,8 @@ where not exists(TranslationUnit t2 | isReferencedInTranslationUnit(e, _, t2) and not t1 = t2 - ) + ) and + // Definition is also in the same translation unit + e.getDefinition().getFile() = t1.getAUserFile() select e, "Declaration with external linkage is accessed in only one translation unit $@.", a1, a1.toString() diff --git a/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected b/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected index 5f04b41ac0..d2a6b0e53f 100644 --- a/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected +++ b/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected @@ -1,3 +1,3 @@ -| test.c:3:5:3:6 | i1 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:10:3:10:4 | i1 | i1 | -| test.c:4:5:4:6 | i2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:11:3:11:4 | i2 | i2 | -| test.c:6:6:6:7 | f2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:13:3:13:4 | call to f2 | call to f2 | +| test.c:3:5:3:6 | i1 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:11:3:11:4 | i1 | i1 | +| test.c:4:5:4:6 | i2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:12:3:12:4 | i2 | i2 | +| test.c:6:6:6:7 | f2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:14:3:14:4 | call to f2 | call to f2 | diff --git a/c/misra/test/rules/RULE-8-7/test.c b/c/misra/test/rules/RULE-8-7/test.c index dc59be7394..591f15a2c4 100644 --- a/c/misra/test/rules/RULE-8-7/test.c +++ b/c/misra/test/rules/RULE-8-7/test.c @@ -5,6 +5,7 @@ int i2; // NON_COMPLIANT - accessed one translation unit void f1() {} // Definition void f2() {} // Definition static void f3() {}; // COMPLIANT - internal linkage +void f4() {} // Definition void f() { i = 0; i1 = 0; diff --git a/c/misra/test/rules/RULE-8-7/test.h b/c/misra/test/rules/RULE-8-7/test.h index 218ec18c23..2b997928bd 100644 --- a/c/misra/test/rules/RULE-8-7/test.h +++ b/c/misra/test/rules/RULE-8-7/test.h @@ -1,4 +1,5 @@ extern int i; // COMPLIANT - accessed multiple translation units extern int i1; // NON_COMPLIANT - accessed one translation unit extern void f1(); // COMPLIANT - accessed multiple translation units -extern void f2(); // NON_COMPLIANT - accessed one translation unit \ No newline at end of file +extern void f2(); // NON_COMPLIANT - accessed one translation unit +extern void f4(); // COMPLIANT - accessed across translation units \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-7/test1.c b/c/misra/test/rules/RULE-8-7/test1.c index 77377e78df..c0ed69c7d0 100644 --- a/c/misra/test/rules/RULE-8-7/test1.c +++ b/c/misra/test/rules/RULE-8-7/test1.c @@ -2,4 +2,5 @@ void f() { i = 0; f1(); + f4(); } \ No newline at end of file From d6710e0c64acb7ac72dc2bef72d48d17a0711e65 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 9 Mar 2025 11:37:42 +0000 Subject: [PATCH 232/370] RULE-8-7: Only report external identifiers with definitions --- .../rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql | 2 ++ c/misra/test/rules/RULE-8-7/test.h | 3 ++- c/misra/test/rules/RULE-8-7/test1.c | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql b/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql index 7b882821b8..db8623d9f2 100644 --- a/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql +++ b/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql @@ -46,6 +46,8 @@ predicate isReferencedInTranslationUnit( from ExternalIdentifiers e, ExternalIdentifierReference a1, TranslationUnit t1 where not isExcluded(e, Declarations6Package::shouldNotBeDefinedWithExternalLinkageQuery()) and + // Only report external identifiers where we see the definition + e.hasDefinition() and isReferencedInTranslationUnit(e, a1, t1) and // Not referenced in any other translation unit not exists(TranslationUnit t2 | diff --git a/c/misra/test/rules/RULE-8-7/test.h b/c/misra/test/rules/RULE-8-7/test.h index 2b997928bd..782099de02 100644 --- a/c/misra/test/rules/RULE-8-7/test.h +++ b/c/misra/test/rules/RULE-8-7/test.h @@ -2,4 +2,5 @@ extern int i; // COMPLIANT - accessed multiple translation units extern int i1; // NON_COMPLIANT - accessed one translation unit extern void f1(); // COMPLIANT - accessed multiple translation units extern void f2(); // NON_COMPLIANT - accessed one translation unit -extern void f4(); // COMPLIANT - accessed across translation units \ No newline at end of file +extern void f4(); // COMPLIANT - accessed across translation units +extern void f5(); // COMPLIANT - no definition \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-7/test1.c b/c/misra/test/rules/RULE-8-7/test1.c index c0ed69c7d0..6d1eab16d0 100644 --- a/c/misra/test/rules/RULE-8-7/test1.c +++ b/c/misra/test/rules/RULE-8-7/test1.c @@ -3,4 +3,5 @@ void f() { i = 0; f1(); f4(); + f5(); } \ No newline at end of file From 569fa76250457eb2a6e05081c4365e15c96181b4 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 9 Mar 2025 18:39:50 +0000 Subject: [PATCH 233/370] RULE-8-7: Support use in headers. --- .../rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql | 3 ++- .../RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected | 1 + c/misra/test/rules/RULE-8-7/test1.c | 2 +- c/misra/test/rules/RULE-8-7/test2.h | 3 +++ 4 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 c/misra/test/rules/RULE-8-7/test2.h diff --git a/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql b/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql index db8623d9f2..9cdd6532a9 100644 --- a/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql +++ b/c/misra/src/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.ql @@ -40,7 +40,8 @@ predicate isReferencedInTranslationUnit( ExternalIdentifiers e, ExternalIdentifierReference r, TranslationUnit t ) { r.getExternalIdentifierTarget() = e and - r.getFile() = t + // Used within the translation unit or an included header + r.getFile() = t.getAUserFile() } from ExternalIdentifiers e, ExternalIdentifierReference a1, TranslationUnit t1 diff --git a/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected b/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected index d2a6b0e53f..6610bf236e 100644 --- a/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected +++ b/c/misra/test/rules/RULE-8-7/ShouldNotBeDefinedWithExternalLinkage.expected @@ -1,3 +1,4 @@ +| test2.h:2:13:2:14 | f6 | Declaration with external linkage is accessed in only one translation unit $@. | test2.h:3:22:3:23 | call to f6 | call to f6 | | test.c:3:5:3:6 | i1 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:11:3:11:4 | i1 | i1 | | test.c:4:5:4:6 | i2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:12:3:12:4 | i2 | i2 | | test.c:6:6:6:7 | f2 | Declaration with external linkage is accessed in only one translation unit $@. | test.c:14:3:14:4 | call to f2 | call to f2 | diff --git a/c/misra/test/rules/RULE-8-7/test1.c b/c/misra/test/rules/RULE-8-7/test1.c index 6d1eab16d0..5c3b3759c9 100644 --- a/c/misra/test/rules/RULE-8-7/test1.c +++ b/c/misra/test/rules/RULE-8-7/test1.c @@ -1,4 +1,4 @@ -#include "test.h" +#include "test2.h" void f() { i = 0; f1(); diff --git a/c/misra/test/rules/RULE-8-7/test2.h b/c/misra/test/rules/RULE-8-7/test2.h new file mode 100644 index 0000000000..d203c3259a --- /dev/null +++ b/c/misra/test/rules/RULE-8-7/test2.h @@ -0,0 +1,3 @@ +#include "test.h" +extern void f6() {} // NON_COMPLIANT +static void test() { f6(); } \ No newline at end of file From 8e3109342d122a58ce32805fbca423df451dc0ce Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 9 Mar 2025 18:42:43 +0000 Subject: [PATCH 234/370] Add change note. --- change_notes/2025-03-09-rule-8-7.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 change_notes/2025-03-09-rule-8-7.md diff --git a/change_notes/2025-03-09-rule-8-7.md b/change_notes/2025-03-09-rule-8-7.md new file mode 100644 index 0000000000..5308c97ce3 --- /dev/null +++ b/change_notes/2025-03-09-rule-8-7.md @@ -0,0 +1,4 @@ + - `RULE-8-7` - `ShouldNotBeDefinedWithExternalLinkage.ql`: + - Remove false positives where the declation is not defined in the database. + - Remove false positives where the definition and reference are in different translation units. + - Remove false positives where the reference occurs in a header file. \ No newline at end of file From 190f1ae536c7ac14fc27268bdd14509b04dd650b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 05:03:57 +0000 Subject: [PATCH 235/370] Bump peter-evans/create-pull-request from 7.0.6 to 7.0.8 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.6 to 7.0.8. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/67ccf781d68cd99b580ae25a5c18a1cc84ffff1f...271a8d0340265f705b14b6d32b9829c1cb33d45e) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/upgrade_codeql_dependencies.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/upgrade_codeql_dependencies.yml b/.github/workflows/upgrade_codeql_dependencies.yml index ca6779871e..1ffc874bb4 100644 --- a/.github/workflows/upgrade_codeql_dependencies.yml +++ b/.github/workflows/upgrade_codeql_dependencies.yml @@ -53,7 +53,7 @@ jobs: find c \( -name '*.ql' -or -name '*.qll' \) -print0 | xargs -0 --max-procs "$XARGS_MAX_PROCS" codeql query format --in-place - name: Create Pull Request - uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 with: title: "Upgrade `github/codeql` dependency to ${{ github.event.inputs.codeql_cli_version }}" body: | From 64b7684697b055b17df9a054e9f8141ab625b58f Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 9 Mar 2025 22:42:15 -0700 Subject: [PATCH 236/370] Implement generics package --- ...otAddOrSubtractAScaledIntegerToAPointer.ql | 2 +- .../IncompatibleFunctionDeclarations.ql | 8 +- c/common/src/codingstandards/c/Generic.qll | 155 +++++++ .../src/codingstandards/c/OutOfBounds.qll | 2 +- .../codingstandards/c/UndefinedBehavior.qll | 2 +- .../c/misra/EssentialTypes.qll | 18 +- ...rsionBetweenFunctionPointerAndOtherType.ql | 2 +- ...etweenIncompleteTypePointerAndOtherType.ql | 2 +- ...weenObjectPointerAndDifferentObjectType.ql | 2 +- ...ionBetweenPointerToObjectAndIntegerType.ql | 2 +- ...ionFromPointerToVoidIntoPointerToObject.ql | 2 +- ...stBetweenPointerToVoidAndArithmeticType.ql | 2 +- ...nPointerToObjectAndNonIntArithmeticType.ql | 2 +- ...NullNotUsedAsIntegerNullPointerConstant.ql | 2 +- ...ointersToVariablyModifiedArrayTypesUsed.ql | 2 +- .../rules/RULE-2-4/UnusedTagDeclaration.ql | 2 +- .../rules/RULE-2-8/UnusedObjectDefinition.ql | 2 +- .../RULE-2-8/UnusedObjectDefinitionStrict.ql | 2 +- ...veMemcmpArgNotPointersToCompatibleTypes.ql | 2 +- ...ricSelectionDoesntDependOnMacroArgument.ql | 26 ++ .../GenericSelectionNotExpandedFromAMacro.ql | 25 ++ ...ricSelectionNotFromMacroWithSideEffects.ql | 87 ++++ .../GenericWithoutNonDefaultAssociation.ql | 35 ++ .../GenericAssociationWithUnselectableType.ql | 111 +++++ ...rousDefaultSelectionForPointerInGeneric.ql | 78 ++++ ...ricExpressionWithIncorrectEssentialType.ql | 62 +++ .../InvalidGenericMacroArgumentEvaluation.ql | 60 +++ .../DefaultGenericSelectionNotFirstOrLast.ql | 93 ++++ ...interShouldPointToConstTypeWhenPossible.ql | 2 +- .../DeclarationsOfAFunctionSameNameAndType.ql | 18 +- .../DeclarationsOfAnObjectSameNameAndType.ql | 30 +- .../CompatibleDeclarationFunctionDefined.ql | 10 +- .../CompatibleDeclarationObjectDefined.ql | 14 +- .../RULE-2-8/UnusedObjectDefinition.expected | 24 +- .../UnusedObjectDefinitionStrict.expected | 8 +- ...ectionDoesntDependOnMacroArgument.expected | 3 + ...SelectionDoesntDependOnMacroArgument.qlref | 1 + ...ricSelectionNotExpandedFromAMacro.expected | 1 + ...enericSelectionNotExpandedFromAMacro.qlref | 1 + c/misra/test/rules/RULE-23-1/test.c | 25 ++ ...ectionNotFromMacroWithSideEffects.expected | 3 + ...SelectionNotFromMacroWithSideEffects.qlref | 1 + c/misra/test/rules/RULE-23-2/test.c | 49 ++ ...nericWithoutNonDefaultAssociation.expected | 2 + .../GenericWithoutNonDefaultAssociation.qlref | 1 + c/misra/test/rules/RULE-23-3/test.c | 23 + ...icAssociationWithUnselectableType.expected | 13 + ...nericAssociationWithUnselectableType.qlref | 1 + c/misra/test/rules/RULE-23-4/test.c | 73 +++ ...faultSelectionForPointerInGeneric.expected | 84 ++++ ...sDefaultSelectionForPointerInGeneric.qlref | 1 + c/misra/test/rules/RULE-23-5/test.c | 236 ++++++++++ ...ressionWithIncorrectEssentialType.expected | 4 + ...ExpressionWithIncorrectEssentialType.qlref | 1 + c/misra/test/rules/RULE-23-6/test.c | 33 ++ ...lidGenericMacroArgumentEvaluation.expected | 12 + ...nvalidGenericMacroArgumentEvaluation.qlref | 1 + c/misra/test/rules/RULE-23-7/test.c | 71 +++ ...ultGenericSelectionNotFirstOrLast.expected | 4 + ...efaultGenericSelectionNotFirstOrLast.qlref | 1 + c/misra/test/rules/RULE-23-8/test.c | 49 ++ ...rationsOfAFunctionSameNameAndType.expected | 26 +- ...arationsOfAnObjectSameNameAndType.expected | 44 +- c/misra/test/rules/RULE-8-3/function1.c | 2 +- c/misra/test/rules/RULE-8-3/function2.c | 2 +- .../2025-02-25-move-type-related-libraries.md | 2 + ...2-25-update-macro-deduplication-library.md | 4 + ...sential-types-with-explicit-conversions.md | 2 + ...25-03-04-more-accurate-type-comparisons.md | 6 + ...plementationShallComplyWithIeeeStandard.ql | 2 +- .../MoveConstructorUsesCopySemantics.ql | 2 +- .../NonTemplateMemberDefinedInTemplate.ql | 2 +- .../rules/A7-1-2/VariableMissingConstexpr.ql | 2 +- .../A8-4-7/TriviallyCopyableSmallType.qll | 2 +- .../src/rules/M0-1-4/SingleUsePODVariable.qll | 2 +- .../MEM53-CPP/ManuallyManagedLifetime.qll | 2 +- ...ConstructorCallForManuallyManagedObject.ql | 2 +- .../src/codingstandards/cpp/Compatible.qll | 30 -- .../cpp/MatchingParenthesis.qll | 264 +++++++++++ cpp/common/src/codingstandards/cpp/Type.qll | 98 +--- .../DeduplicateMacroResults.qll | 28 +- .../cpp/deadcode/UnusedObjects.qll | 6 +- .../cpp/exclusions/c/Generics.qll | 163 +++++++ .../cpp/exclusions/c/RuleMetadata.qll | 3 + .../CatchExceptionsByLvalueReference.qll | 2 +- ...dPointerToRestrictQualifiedParamShared.qll | 2 +- .../UnusedTypeDeclarations.qll | 2 +- .../codingstandards/cpp/types/Compatible.qll | 421 ++++++++++++++++++ .../src/codingstandards/cpp/types/Graph.qll | 15 + .../cpp/types/LvalueConversion.qll | 38 ++ .../cpp/{ => types}/Pointers.qll | 0 .../cpp/types/SimpleAssignment.qll | 45 ++ .../cpp/{ => types}/TrivialType.qll | 0 .../src/codingstandards/cpp/types/Type.qll | 96 ++++ .../cpp/{TypeUses.qll => types/Uses.qll} | 0 .../cpp/{ => types}/VariablyModifiedTypes.qll | 0 .../DisappliedQuery.ql | 2 +- .../cpp/trivialtypes/LiteralType.ql | 2 +- .../cpp/trivialtypes/TrivialType.ql | 2 +- .../cpp/trivialtypes/TriviallyCopyableType.ql | 2 +- rule_packages/c/Generics.json | 194 ++++++++ 101 files changed, 2846 insertions(+), 263 deletions(-) create mode 100644 c/common/src/codingstandards/c/Generic.qll create mode 100644 c/misra/src/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.ql create mode 100644 c/misra/src/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.ql create mode 100644 c/misra/src/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.ql create mode 100644 c/misra/src/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.ql create mode 100644 c/misra/src/rules/RULE-23-4/GenericAssociationWithUnselectableType.ql create mode 100644 c/misra/src/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.ql create mode 100644 c/misra/src/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.ql create mode 100644 c/misra/src/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.ql create mode 100644 c/misra/src/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.ql create mode 100644 c/misra/test/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.expected create mode 100644 c/misra/test/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.qlref create mode 100644 c/misra/test/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.expected create mode 100644 c/misra/test/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.qlref create mode 100644 c/misra/test/rules/RULE-23-1/test.c create mode 100644 c/misra/test/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.expected create mode 100644 c/misra/test/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.qlref create mode 100644 c/misra/test/rules/RULE-23-2/test.c create mode 100644 c/misra/test/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.expected create mode 100644 c/misra/test/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.qlref create mode 100644 c/misra/test/rules/RULE-23-3/test.c create mode 100644 c/misra/test/rules/RULE-23-4/GenericAssociationWithUnselectableType.expected create mode 100644 c/misra/test/rules/RULE-23-4/GenericAssociationWithUnselectableType.qlref create mode 100644 c/misra/test/rules/RULE-23-4/test.c create mode 100644 c/misra/test/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.expected create mode 100644 c/misra/test/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.qlref create mode 100644 c/misra/test/rules/RULE-23-5/test.c create mode 100644 c/misra/test/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.expected create mode 100644 c/misra/test/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.qlref create mode 100644 c/misra/test/rules/RULE-23-6/test.c create mode 100644 c/misra/test/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.expected create mode 100644 c/misra/test/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.qlref create mode 100644 c/misra/test/rules/RULE-23-7/test.c create mode 100644 c/misra/test/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.expected create mode 100644 c/misra/test/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.qlref create mode 100644 c/misra/test/rules/RULE-23-8/test.c create mode 100644 change_notes/2025-02-25-move-type-related-libraries.md create mode 100644 change_notes/2025-02-25-update-macro-deduplication-library.md create mode 100644 change_notes/2025-03-04-essential-types-with-explicit-conversions.md create mode 100644 change_notes/2025-03-04-more-accurate-type-comparisons.md delete mode 100644 cpp/common/src/codingstandards/cpp/Compatible.qll create mode 100644 cpp/common/src/codingstandards/cpp/MatchingParenthesis.qll create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/c/Generics.qll create mode 100644 cpp/common/src/codingstandards/cpp/types/Compatible.qll create mode 100644 cpp/common/src/codingstandards/cpp/types/Graph.qll create mode 100644 cpp/common/src/codingstandards/cpp/types/LvalueConversion.qll rename cpp/common/src/codingstandards/cpp/{ => types}/Pointers.qll (100%) create mode 100644 cpp/common/src/codingstandards/cpp/types/SimpleAssignment.qll rename cpp/common/src/codingstandards/cpp/{ => types}/TrivialType.qll (100%) create mode 100644 cpp/common/src/codingstandards/cpp/types/Type.qll rename cpp/common/src/codingstandards/cpp/{TypeUses.qll => types/Uses.qll} (100%) rename cpp/common/src/codingstandards/cpp/{ => types}/VariablyModifiedTypes.qll (100%) create mode 100644 rule_packages/c/Generics.json diff --git a/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql b/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql index fd57bd6f75..61dd77f6f4 100644 --- a/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql +++ b/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.Pointers +import codingstandards.cpp.types.Pointers import semmle.code.cpp.dataflow.TaintTracking import ScaledIntegerPointerArithmeticFlow::PathGraph diff --git a/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql b/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql index 20b6e5e59e..95ef0fd682 100644 --- a/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql +++ b/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.Compatible +import codingstandards.cpp.types.Compatible import ExternalIdentifiers from ExternalIdentifiers d, FunctionDeclarationEntry f1, FunctionDeclarationEntry f2 @@ -29,12 +29,10 @@ where f1.getName() = f2.getName() and ( //return type check - not typesCompatible(f1.getType(), f2.getType()) + not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, f2) or //parameter type check - parameterTypesIncompatible(f1, f2) - or - not f1.getNumberOfParameters() = f2.getNumberOfParameters() + not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, f2) ) and // Apply ordering on start line, trying to avoid the optimiser applying this join too early // in the pipeline diff --git a/c/common/src/codingstandards/c/Generic.qll b/c/common/src/codingstandards/c/Generic.qll new file mode 100644 index 0000000000..1bf4282017 --- /dev/null +++ b/c/common/src/codingstandards/c/Generic.qll @@ -0,0 +1,155 @@ +import cpp +import codingstandards.cpp.Macro +import codingstandards.cpp.MatchingParenthesis + +string genericRegexp() { result = ".*_Generic\\s*\\(\\s*(.+),.*" } + +bindingset[input] +string deparenthesize(string input) { + input = "(" + result + ")" and + result = input.substring(1, input.length() - 1) +} + + +class GenericMacro extends Macro { + string ctrlExpr; + + GenericMacro() { ctrlExpr = getBody().regexpCapture(genericRegexp(), 1).trim() } + + string getAParameter() { result = this.(FunctionLikeMacro).getAParameter() } + + string getControllingExprString() { + if exists(string s | s = deparenthesize(ctrlExpr)) + then result = deparenthesize(ctrlExpr).trim() + else result = ctrlExpr + } + + /** + * Whether the controlling expression of the `_Generic` expr in this macro's controlling + * expression refers to one of this macro's parameters. + */ + predicate hasControllingExprFromMacroParameter() { + getControllingExprString().matches(getAParameter()) + } +} + +class GenericMacroString extends string { + GenericMacroString() { this = any(Macro m).getBody() and this.matches("%_Generic%") } +} + +import MatchingParenthesis + +class ParsedGenericMacro extends Macro { + ParsedRoot macroBody; + Parsed genericBody; + string beforeGenericBody; + string afterGenericBody; + + ParsedGenericMacro() { + macroBody.getInputString() = this.getBody() and + exists(ParsedText genericText | + genericText.getText().matches("%_Generic%") and + genericBody = genericText.getParent().getChild(genericText.getChildIdx() + 1) and + genericBody.getRoot() = macroBody + ) and + beforeGenericBody = + textFrom(macroBody.getStartToken(), genericBody.getStartToken().getPrevious()) and + ( + if exists(genericBody.getEndToken().getNext()) + then afterGenericBody = textFrom(genericBody.getEndToken().getNext(), macroBody.getEndToken()) + else afterGenericBody = "" + ) + } + + string getAParameter() { + result = this.(FunctionLikeMacro).getAParameter() + } + + int getAParsedGenericCommaSeparatorOffset() { + exists(ParsedText text | + text.getParent() = genericBody and + result = text.getStartToken().getStartPos() + text.getText().indexOf(",") + ) + } + + int getAParsedGenericColonSeparatorOffset() { + exists(ParsedText text | + text.getParent() = genericBody and + result = text.getStartToken().getStartPos() + text.getText().indexOf(":") + ) + } + + int getParsedGenericCommaSeparatorOffset(int i) { + result = rank[i](int index | index = getAParsedGenericCommaSeparatorOffset()) + } + + bindingset[start, end] + int getParsedGenericColon(int start, int end) { + result = + min(int offset | + offset = getAParsedGenericColonSeparatorOffset() and + offset >= start and + offset <= end + ) + } + + predicate hasParsedFullSelectionRange(int idx, int start, int end) { + idx = 1 and + start = genericBody.getStartToken().getEndPos() and + end = getParsedGenericCommaSeparatorOffset(idx) + or + not exists(getParsedGenericCommaSeparatorOffset(idx)) and + start = getParsedGenericCommaSeparatorOffset(idx - 1) and + end = genericBody.getEndToken().getStartPos() + or + start = getParsedGenericCommaSeparatorOffset(idx - 1) and + end = getParsedGenericCommaSeparatorOffset(idx) + } + + string getSelectionString(int idx) { + exists(int start, int rawStart, int end | + hasParsedFullSelectionRange(idx, rawStart, end) and + ( + if exists(getParsedGenericColon(rawStart, end)) + then start = getParsedGenericColon(rawStart, end) + else start = rawStart + ) and + result = genericBody.getInputString().substring(start, end) + ) + } + + string getControllingExprString() { + result = getSelectionString(1) + } + + bindingset[str, word] + private int countWordInString(string word, string str) { + result = + max(int occurrence | + exists(str.regexpFind("\\b" + word + "\\b", occurrence, _)) or occurrence = -1 + | + occurrence + 1 + ) + } + + int expansionsOutsideExpr(string parameter) { + parameter = getAParameter() and + result = + countWordInString(parameter, beforeGenericBody) + + countWordInString(parameter, afterGenericBody) + } + + int expansionsInsideSelection(string parameter, int idx) { + parameter = getAParameter() and + result = countWordInString(parameter, getSelectionString(idx)) + } + + int expansionsInsideControllingExpr(string parameter) { + result = expansionsInsideSelection(parameter, 1) + } + + int expansionsInsideAssociation(string parameter, int idx) { + not idx = 0 and + result = expansionsInsideSelection(parameter, idx + 1) + } +} \ No newline at end of file diff --git a/c/common/src/codingstandards/c/OutOfBounds.qll b/c/common/src/codingstandards/c/OutOfBounds.qll index 220cf5a0a0..bb7d1bd124 100644 --- a/c/common/src/codingstandards/c/OutOfBounds.qll +++ b/c/common/src/codingstandards/c/OutOfBounds.qll @@ -5,7 +5,7 @@ */ import cpp -import codingstandards.cpp.Pointers +import codingstandards.cpp.types.Pointers import codingstandards.c.Variable import codingstandards.cpp.Allocations import codingstandards.cpp.Overflow diff --git a/c/common/src/codingstandards/c/UndefinedBehavior.qll b/c/common/src/codingstandards/c/UndefinedBehavior.qll index 6a72cb6eb7..47461aa613 100644 --- a/c/common/src/codingstandards/c/UndefinedBehavior.qll +++ b/c/common/src/codingstandards/c/UndefinedBehavior.qll @@ -1,5 +1,5 @@ import cpp -import codingstandards.cpp.Pointers +import codingstandards.cpp.types.Pointers import codingstandards.cpp.UndefinedBehavior /** diff --git a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll index 02b8498ecb..afdbefdb7d 100644 --- a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll +++ b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll @@ -164,14 +164,14 @@ EssentialTypeCategory getEssentialTypeCategory(Type type) { */ pragma[nomagic] Type getEssentialType(Expr e) { - if e.hasExplicitConversion() - then - if e.getConversion() instanceof ParenthesisExpr - then - if e.getConversion().(ParenthesisExpr).hasExplicitConversion() - then result = e.getConversion().(ParenthesisExpr).getConversion().getType() - else result = e.getConversion().(ParenthesisExpr).getExpr().(EssentialExpr).getEssentialType() - else result = e.getConversion().getType() + if e.hasConversion() + then result = getEssentialTypeOfConversion(e.getFullyConverted()) + else result = e.(EssentialExpr).getEssentialType() +} + +Type getEssentialTypeOfConversion(Expr e) { + if e.(Conversion).isImplicit() or e instanceof ParenthesisExpr or e instanceof C11GenericExpr + then result = getEssentialTypeOfConversion(e.(Conversion).getExpr()) else result = e.(EssentialExpr).getEssentialType() } @@ -446,7 +446,7 @@ class EssentialLiteral extends EssentialExpr, Literal { if underlyingStandardType.(IntType).isSigned() then result = stlr(this) else result = utlr(this) - else result = underlyingStandardType + else result = getStandardType() ) ) } diff --git a/c/misra/src/rules/RULE-11-1/ConversionBetweenFunctionPointerAndOtherType.ql b/c/misra/src/rules/RULE-11-1/ConversionBetweenFunctionPointerAndOtherType.ql index 36157e130e..7678fc1d23 100644 --- a/c/misra/src/rules/RULE-11-1/ConversionBetweenFunctionPointerAndOtherType.ql +++ b/c/misra/src/rules/RULE-11-1/ConversionBetweenFunctionPointerAndOtherType.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Pointers +import codingstandards.cpp.types.Pointers from CStyleCast cast, Type type, Type newType where diff --git a/c/misra/src/rules/RULE-11-2/ConversionBetweenIncompleteTypePointerAndOtherType.ql b/c/misra/src/rules/RULE-11-2/ConversionBetweenIncompleteTypePointerAndOtherType.ql index 6c552b0f39..5c16dc1afb 100644 --- a/c/misra/src/rules/RULE-11-2/ConversionBetweenIncompleteTypePointerAndOtherType.ql +++ b/c/misra/src/rules/RULE-11-2/ConversionBetweenIncompleteTypePointerAndOtherType.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Pointers +import codingstandards.cpp.types.Pointers import codingstandards.cpp.Type from Cast cast, Type type, Type newType diff --git a/c/misra/src/rules/RULE-11-3/CastBetweenObjectPointerAndDifferentObjectType.ql b/c/misra/src/rules/RULE-11-3/CastBetweenObjectPointerAndDifferentObjectType.ql index 8292bd3b6f..3a6fb28c2a 100644 --- a/c/misra/src/rules/RULE-11-3/CastBetweenObjectPointerAndDifferentObjectType.ql +++ b/c/misra/src/rules/RULE-11-3/CastBetweenObjectPointerAndDifferentObjectType.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Pointers +import codingstandards.cpp.types.Pointers from CStyleCast cast, Type baseTypeFrom, Type baseTypeTo where diff --git a/c/misra/src/rules/RULE-11-4/ConversionBetweenPointerToObjectAndIntegerType.ql b/c/misra/src/rules/RULE-11-4/ConversionBetweenPointerToObjectAndIntegerType.ql index 8877d04323..336f5d4643 100644 --- a/c/misra/src/rules/RULE-11-4/ConversionBetweenPointerToObjectAndIntegerType.ql +++ b/c/misra/src/rules/RULE-11-4/ConversionBetweenPointerToObjectAndIntegerType.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.Macro -import codingstandards.cpp.Pointers +import codingstandards.cpp.types.Pointers MacroInvocation getAMacroInvocation(CStyleCast cast) { result.getAnExpandedElement() = cast } diff --git a/c/misra/src/rules/RULE-11-5/ConversionFromPointerToVoidIntoPointerToObject.ql b/c/misra/src/rules/RULE-11-5/ConversionFromPointerToVoidIntoPointerToObject.ql index 0363c28c19..b316b39a56 100644 --- a/c/misra/src/rules/RULE-11-5/ConversionFromPointerToVoidIntoPointerToObject.ql +++ b/c/misra/src/rules/RULE-11-5/ConversionFromPointerToVoidIntoPointerToObject.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Pointers +import codingstandards.cpp.types.Pointers from Cast cast, VoidPointerType type, PointerToObjectType newType where diff --git a/c/misra/src/rules/RULE-11-6/CastBetweenPointerToVoidAndArithmeticType.ql b/c/misra/src/rules/RULE-11-6/CastBetweenPointerToVoidAndArithmeticType.ql index cc0adf0517..2293ede61e 100644 --- a/c/misra/src/rules/RULE-11-6/CastBetweenPointerToVoidAndArithmeticType.ql +++ b/c/misra/src/rules/RULE-11-6/CastBetweenPointerToVoidAndArithmeticType.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Pointers +import codingstandards.cpp.types.Pointers from CStyleCast cast, Type typeFrom, Type typeTo where diff --git a/c/misra/src/rules/RULE-11-7/CastBetweenPointerToObjectAndNonIntArithmeticType.ql b/c/misra/src/rules/RULE-11-7/CastBetweenPointerToObjectAndNonIntArithmeticType.ql index e499ea6485..82ac620aa7 100644 --- a/c/misra/src/rules/RULE-11-7/CastBetweenPointerToObjectAndNonIntArithmeticType.ql +++ b/c/misra/src/rules/RULE-11-7/CastBetweenPointerToObjectAndNonIntArithmeticType.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Pointers +import codingstandards.cpp.types.Pointers class MisraNonIntegerArithmeticType extends Type { MisraNonIntegerArithmeticType() { diff --git a/c/misra/src/rules/RULE-11-9/MacroNullNotUsedAsIntegerNullPointerConstant.ql b/c/misra/src/rules/RULE-11-9/MacroNullNotUsedAsIntegerNullPointerConstant.ql index cb18ed0d1d..28b256e85c 100644 --- a/c/misra/src/rules/RULE-11-9/MacroNullNotUsedAsIntegerNullPointerConstant.ql +++ b/c/misra/src/rules/RULE-11-9/MacroNullNotUsedAsIntegerNullPointerConstant.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Pointers +import codingstandards.cpp.types.Pointers import codingstandards.cpp.Type from Zero zero, Expr e, string type diff --git a/c/misra/src/rules/RULE-18-10/PointersToVariablyModifiedArrayTypesUsed.ql b/c/misra/src/rules/RULE-18-10/PointersToVariablyModifiedArrayTypesUsed.ql index 3a99ebd842..dc1433d5e4 100644 --- a/c/misra/src/rules/RULE-18-10/PointersToVariablyModifiedArrayTypesUsed.ql +++ b/c/misra/src/rules/RULE-18-10/PointersToVariablyModifiedArrayTypesUsed.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.VariablyModifiedTypes +import codingstandards.cpp.types.VariablyModifiedTypes from VmtDeclarationEntry v, string declstr, string adjuststr, string relationstr where diff --git a/c/misra/src/rules/RULE-2-4/UnusedTagDeclaration.ql b/c/misra/src/rules/RULE-2-4/UnusedTagDeclaration.ql index 08fe2568e9..88b0a5b05a 100644 --- a/c/misra/src/rules/RULE-2-4/UnusedTagDeclaration.ql +++ b/c/misra/src/rules/RULE-2-4/UnusedTagDeclaration.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.TypeUses +import codingstandards.cpp.types.Uses from UserType s where diff --git a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinition.ql b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinition.ql index 2230a74592..13355b7f74 100644 --- a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinition.ql +++ b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinition.ql @@ -20,5 +20,5 @@ from ReportDeadObject report where not isExcluded(report.getPrimaryElement(), DeadCode2Package::unusedObjectDefinitionQuery()) and not report.hasAttrUnused() -select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocation(), +select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocatable(), report.getOptionalPlaceholderMessage() diff --git a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionStrict.ql b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionStrict.ql index cc117763ee..4eb1ad9773 100644 --- a/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionStrict.ql +++ b/c/misra/src/rules/RULE-2-8/UnusedObjectDefinitionStrict.ql @@ -22,5 +22,5 @@ from ReportDeadObject report where not isExcluded(report.getPrimaryElement(), DeadCode2Package::unusedObjectDefinitionStrictQuery()) and report.hasAttrUnused() -select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocation(), +select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocatable(), report.getOptionalPlaceholderMessage() diff --git a/c/misra/src/rules/RULE-21-15/MemcpyMemmoveMemcmpArgNotPointersToCompatibleTypes.ql b/c/misra/src/rules/RULE-21-15/MemcpyMemmoveMemcmpArgNotPointersToCompatibleTypes.ql index f5d8057b3a..28dce7b638 100644 --- a/c/misra/src/rules/RULE-21-15/MemcpyMemmoveMemcmpArgNotPointersToCompatibleTypes.ql +++ b/c/misra/src/rules/RULE-21-15/MemcpyMemmoveMemcmpArgNotPointersToCompatibleTypes.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Pointers +import codingstandards.cpp.types.Pointers class MemCmpMoveCpy extends Function { // Couldn't extend BuiltInFunction because it misses `memcmp` diff --git a/c/misra/src/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.ql b/c/misra/src/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.ql new file mode 100644 index 0000000000..0dc0e5273a --- /dev/null +++ b/c/misra/src/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.ql @@ -0,0 +1,26 @@ +/** + * @id c/misra/generic-selection-doesnt-depend-on-macro-argument + * @name RULE-23-1: A generic selection should depend on the type of a macro argument + * @description A generic selection should depend on the type of a macro argument. + * @kind problem + * @precision high + * @problem.severity warning + * @tags external/misra/id/rule-23-1 + * correctness + * maintainability + * external/misra/c/2012/amendment3 + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.Generic + +from ParsedGenericMacro macro, string ctrlExpr +where + not isExcluded(macro, GenericsPackage::genericSelectionDoesntDependOnMacroArgumentQuery()) and + ctrlExpr = macro.getControllingExprString().trim() and + not macro.expansionsInsideControllingExpr(_) > 0 +select macro, + "Generic macro " + macro.getName() + " uses controlling expr " + ctrlExpr + + ", which doesn't match any macro parameter." diff --git a/c/misra/src/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.ql b/c/misra/src/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.ql new file mode 100644 index 0000000000..ef2a2e75c5 --- /dev/null +++ b/c/misra/src/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.ql @@ -0,0 +1,25 @@ +/** + * @id c/misra/generic-selection-not-expanded-from-a-macro + * @name RULE-23-1: A generic selection should only be expanded from a macro + * @description A generic selection should only be expanded from a macro. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-23-1 + * maintainability + * external/misra/c/2012/amendment3 + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.c.misra + +from C11GenericExpr generic, Expr ctrlExpr +where + not isExcluded(generic, GenericsPackage::genericSelectionNotExpandedFromAMacroQuery()) and + ctrlExpr = generic.getControllingExpr() and + not exists(MacroInvocation mi | + mi.getAGeneratedElement() = generic.getExpr() + ) +select generic, "Generic expression with controlling expression $@ is not expanded froma macro", +ctrlExpr, ctrlExpr.toString() diff --git a/c/misra/src/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.ql b/c/misra/src/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.ql new file mode 100644 index 0000000000..3ec53a08bf --- /dev/null +++ b/c/misra/src/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.ql @@ -0,0 +1,87 @@ +/** + * @id c/misra/generic-selection-not-from-macro-with-side-effects + * @name RULE-23-2: A generic selection shall not contain side-effects if it is not expanded from a macro + * @description A generic selection that is not expanded from a macro shall not contain potential + * side effects in the controlling expression. + * @kind problem + * @precision high + * @problem.severity warning + * @tags external/misra/id/rule-23-2 + * maintainability + * external/misra/c/2012/amendment3 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.Generic +import codingstandards.cpp.SideEffect +import codingstandards.cpp.sideeffect.DefaultEffects +import codingstandards.cpp.alertreporting.DeduplicateMacroResults + +class GenericWithNonMacroSideEffect extends C11GenericExpr { + SideEffect sideEffect; + + GenericWithNonMacroSideEffect() { + not exists(MacroInvocation mi | + mi.getAGeneratedElement() = getExpr() and + mi.getMacro().(GenericMacro).hasControllingExprFromMacroParameter() + ) and + sideEffect = getASideEffect(getControllingExpr()) + } + + SideEffect getASideEffect() { result = sideEffect } +} + +module GenericSideEffectConfig implements DeduplicateMacroConfigSig { + string describe(GenericWithNonMacroSideEffect e) { + result = "side effect '" + e.getASideEffect() + "'" + } +} + +module GenericSideEffectReportConfig implements MacroReportConfigSig { + /* Create a message to describe this macro, with a string describing its `ResultElement`. */ + bindingset[description] + string getMessageSameResultInAllExpansions(Macro m, string description) { + result = + "Generic selection macro " + m.getName() + " contains a " + description + + ", which is not from macro invocation arguments." + } + + /* Create a message to describe this macro, using '$@' to describe an example `ResultElement`. */ + string getMessageVariedResultInAllExpansions(Macro m) { + result = + "Generic selection in macro " + m.getName() + + " contains an invocation-dependent side effect which is not from macro invocation arguments, for example $@." + } + + /** + * Create a message to describe this macro expansion which produces a `ResultElement`, using '$@' + * to describe the relevant macro. + */ + string getMessageResultInIsolatedExpansion(GenericWithNonMacroSideEffect element) { + // A result in an isolated expansion indicates that the side effect is not always present when + // macro is expanded, and therefore the side-effect is not in the macro definition but rather + // originates in one of the macro arguments. + none() + } + + /** + * Create a message to describe a `ResultElement` which is not generated by a macro expansion. + */ + string getMessageNotInMacro( + GenericWithNonMacroSideEffect element, Locatable optLoc1, string optStr1 + ) { + none() + } +} + +import DeduplicateMacroResults as Deduplicate +import Deduplicate::Report as Report + +from Report::ReportResult res +where + not isExcluded(res.getPrimaryElement(), + GenericsPackage::genericSelectionNotFromMacroWithSideEffectsQuery()) +select res.getPrimaryElement(), res.getMessage(), res.getOptionalPlaceholderLocatable(), + res.getOptionalPlaceholderMessage() \ No newline at end of file diff --git a/c/misra/src/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.ql b/c/misra/src/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.ql new file mode 100644 index 0000000000..f3a0227022 --- /dev/null +++ b/c/misra/src/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.ql @@ -0,0 +1,35 @@ +/** + * @id c/misra/generic-without-non-default-association + * @name RULE-23-3: A generic selection should contain at least one non-default association + * @description A generic selection should contain at least one non-default association. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-23-3 + * correctness + * maintainability + * external/misra/c/2012/amendment3 + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.AlertReporting + +class InvalidGeneric extends C11GenericExpr { + InvalidGeneric() { + not exists(Type t | + t = getAnAssociationType() and + not t instanceof VoidType + ) + } +} + +from C11GenericExpr generic, Element primaryElement +where + not isExcluded(primaryElement, GenericsPackage::genericWithoutNonDefaultAssociationQuery()) and + not exists(Type t | + t = generic.getAnAssociationType() and + not t instanceof VoidType + ) and primaryElement = MacroUnwrapper::unwrapElement(generic) +select primaryElement, "Generic selection contains no non-default association." diff --git a/c/misra/src/rules/RULE-23-4/GenericAssociationWithUnselectableType.ql b/c/misra/src/rules/RULE-23-4/GenericAssociationWithUnselectableType.ql new file mode 100644 index 0000000000..e8ed88f757 --- /dev/null +++ b/c/misra/src/rules/RULE-23-4/GenericAssociationWithUnselectableType.ql @@ -0,0 +1,111 @@ +/** + * @id c/misra/generic-association-with-unselectable-type + * @name RULE-23-4: A generic association shall list an appropriate type + * @description Generic selections undergo lvalue conversion before type comparison, leading to + * certain types being impossible to select. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-23-4 + * correctness + * external/misra/c/2012/amendment3 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.types.LvalueConversion +import codingstandards.cpp.types.Graph +import codingstandards.cpp.alertreporting.DeduplicateMacroResults + +/** + * Check if a type contains an unmatchable anonymous struct or union. + * + * Anonymous structs and unions are only equal to themselves. So any anonymous struct, or compound + * type containing an anonymous struct, is unmatchable. + * + * However, there is an exception if the anonymous struct is behind a typedef. All uses of that + * typedef will resolve to the same anonymous struct, and so the typedef is matchable. + */ +predicate containsAnonymousType(Type t) { + t.(Struct).isAnonymous() + or + not t instanceof TypedefType and + exists(Type next | typeGraph(t, next) | containsAnonymousType(next)) +} + +predicate invalidType(Type t, string reason) { + containsAnonymousType(t) and + reason = "containing an anonymous struct or union type" + or + exists(performLvalueConversion(t, reason)) +} + +class InvalidSelection extends Expr { + Type selectionType; + int idx; + C11GenericExpr generic; + string reason; + + InvalidSelection() { + this = generic.getAssociationExpr(idx) and + selectionType = generic.getAssociationType(idx) and + invalidType(selectionType, reason) + } + + Type getSelectionType() { result = selectionType } + + string getReason() { result = reason } +} + +module InvalidSelectionConfig implements DeduplicateMacroConfigSig { + string describe(InvalidSelection e) { + result = "'" + e.getSelectionType().toString() + "', due to " + e.getReason() + } +} + +import InvalidSelectionConfig + +module InvalidSelectionReportConfig implements MacroReportConfigSig { + /* Create a message to describe this macro, with a string describing its `ResultElement`. */ + bindingset[description] + string getMessageSameResultInAllExpansions(Macro m, string description) { + result = "Generic in macro " + m.getName() + " has unselectable type " + description + "." + } + + /* Create a message to describe this macro, using '$@' to describe an example `ResultElement`. */ + string getMessageVariedResultInAllExpansions(Macro m) { + result = + "Generic in macro " + m.getName() + + " has an invocation-dependent unselectable type, for example $@." + } + + /** + * Create a message to describe this macro expansion which produces a `ResultElement`, using '$@' + * to describe the relevant macro. + */ + string getMessageResultInIsolatedExpansion(InvalidSelection element) { + result = + "Generic resulting from invocation of macro $@ contains an unselectable type " + + describe(element) + "." + } + + /** + * Create a message to describe a `ResultElement` which is not generated by a macro expansion. + */ + string getMessageNotInMacro(InvalidSelection element, Locatable optLoc1, string optStr1) { + result = "Generic selection uses unselectable type " + describe(element) + "'." and + optLoc1 = element and + optStr1 = "side effect" + } +} + +import DeduplicateMacroResults as Deduplicate +import Deduplicate::Report as Report + +from Report::ReportResult res +where + not isExcluded(res.getPrimaryElement(), + GenericsPackage::genericSelectionNotFromMacroWithSideEffectsQuery()) +select res.getPrimaryElement(), res.getMessage(), res.getOptionalPlaceholderLocatable(), + res.getOptionalPlaceholderMessage() diff --git a/c/misra/src/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.ql b/c/misra/src/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.ql new file mode 100644 index 0000000000..a009ba1b2a --- /dev/null +++ b/c/misra/src/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.ql @@ -0,0 +1,78 @@ +/** + * @id c/misra/dangerous-default-selection-for-pointer-in-generic + * @name RULE-23-5: A generic selection should not depend on implicit pointer type conversion + * @description Pointer types in a generic selection do not undergo pointer conversions and should + * not counterintuitively fall through to the default association. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-23-5 + * correctness + * external/misra/c/2012/amendment3 + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.AlertReporting +import codingstandards.cpp.types.Compatible +import codingstandards.cpp.types.LvalueConversion +import codingstandards.cpp.types.SimpleAssignment + +predicate typesCompatible(Type t1, Type t2) { + TypeEquivalence::equalTypes(t1, t2) +} + +class TypeFromGeneric extends Type { + TypeFromGeneric() { + exists(C11GenericExpr g | + ( + this = g.getAssociationType(_) or + this = g.getControllingExpr().getFullyConverted().getType() + ) + ) + } +} + +predicate missesOnPointerConversion(Type provided, Type expected) { + // The provided type is not compatible with the expected type: + not typesCompatible(provided, expected) and + // But 6.5.16.1 simple assignment constraints would have been satisfied: + ( + // Check as if the controlling expr is assigned to the expected type: + SimpleAssignment::satisfiesSimplePointerAssignment(expected, provided) + or + // Since developers typically rely on the compiler to catch const/non-const assignment + // errors, don't assume a const-to-non-const generic selection miss was intentional. + SimpleAssignment::satisfiesSimplePointerAssignment(provided, expected) + ) +} + +from + C11GenericExpr generic, Expr controllingExpr, Type providedType, Type missedType, + Type lvalueConverted, Element extraElement, string extraString, string extraElementName +where + not isExcluded(generic, GenericsPackage::dangerousDefaultSelectionForPointerInGenericQuery()) and + controllingExpr = generic.getControllingExpr() and + providedType = generic.getControllingExpr().getFullyConverted().getType() and + // The controlling expression undergoes lvalue conversion: + lvalueConverted = getLvalueConverted(providedType) and + // There is no perfect match + not typesCompatible(lvalueConverted, generic.getAnAssociationType()) and + // There is a default selector. + exists(VoidType default | default = generic.getAnAssociationType()) and + missedType = generic.getAnAssociationType() and + missesOnPointerConversion(lvalueConverted, missedType) and + extraElement = MacroUnwrapper::unwrapElement(generic) and + ( + if extraElement instanceof Macro + then ( + extraString = " in generic macro $@" and extraElementName = extraElement.(Macro).getName() + ) else ( + extraString = "" and extraElementName = "" + ) + ) +select generic, + "Generic matched default selection, as controlling argument type " + lvalueConverted.toString() + + " does not undergo pointer conversion to " + missedType.toString() + extraString + ".", + extraElement, extraElementName diff --git a/c/misra/src/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.ql b/c/misra/src/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.ql new file mode 100644 index 0000000000..c27ce3dc55 --- /dev/null +++ b/c/misra/src/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.ql @@ -0,0 +1,62 @@ +/** + * @id c/misra/generic-expression-with-incorrect-essential-type + * @name RULE-23-6: The controlling expression of a generic selection shall have an essential type that matches its standard type + * @description The controlling expression of a generic selection shall have an essential type that + * matches its standard type. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-23-6 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.misra.EssentialTypes +import codingstandards.cpp.Cpp14Literal +import codingstandards.cpp.AlertReporting + +predicate allowedByException(Expr expr, Type essentialType) { + // Constant expressions + exists(expr.getValue()) and + ( + // with essentially signed or unsigned type + getEssentialTypeCategory(essentialType) = EssentiallySignedType() + or + getEssentialTypeCategory(essentialType) = EssentiallyUnsignedType() + ) and + // with lower rank than `int` + essentialType.getSize() < any(IntType t).getSize() and + // and not a character constant + not expr instanceof Cpp14Literal::CharLiteral +} + +from + C11GenericExpr generic, Expr ctrlExpr, Type ctrlType, Type ctrlEssentialType, + Element extraElement, string extraString, string extraMessage +where + not isExcluded(ctrlExpr, GenericsPackage::genericExpressionWithIncorrectEssentialTypeQuery()) and + ctrlExpr = generic.getControllingExpr() and + ctrlType = ctrlExpr.getFullyConverted().getType() and + ctrlEssentialType = getEssentialType(ctrlExpr) and + // Exclude lvalue conversion on const structs + exists(getEssentialTypeCategory(ctrlEssentialType)) and + ( + not ctrlEssentialType = ctrlType + or + getEssentialTypeCategory(ctrlEssentialType) = EssentiallyEnumType() + ) and + not allowedByException(ctrlExpr, ctrlEssentialType) and + extraElement = MacroUnwrapper::unwrapElement(generic) and + ( + if extraElement instanceof Macro + then ( + extraMessage = "macro $@ " and extraString = extraElement.(Macro).getName() + ) else ( + extraMessage = "" and extraString = "" + ) + ) +select generic, + "Controlling expression in generic " + extraMessage + + "has standard type " + ctrlType.toString() + ", which doesn't match its essential type " + + ctrlEssentialType.toString() + ".", extraElement, extraString \ No newline at end of file diff --git a/c/misra/src/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.ql b/c/misra/src/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.ql new file mode 100644 index 0000000000..04952ae960 --- /dev/null +++ b/c/misra/src/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.ql @@ -0,0 +1,60 @@ +/** + * @id c/misra/invalid-generic-macro-argument-evaluation + * @name RULE-23-7: A generic selection that is expanded from a macro should evaluate its argument only once + * @description A generic selection that is expanded from a macro should evaluate its argument only + * once. + * @kind problem + * @precision medium + * @problem.severity warning + * @tags external/misra/id/rule-23-7 + * correctness + * maintainability + * external/misra/c/2012/amendment3 + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.Generic + +predicate allowedByException(string parameter, ParsedGenericMacro genericMacro) { + genericMacro.expansionsOutsideExpr(parameter) = 0 and + not genericMacro.expansionsInsideAssociation(parameter, _) > 0 and + forall(MacroInvocation mi, C11GenericExpr expr | + mi.getMacro() = genericMacro and + mi.getAGeneratedElement() = expr + | + forall(Expr assoc | assoc = expr.getAnAssociationExpr() | exists(assoc.getValue())) + ) +} + +from ParsedGenericMacro genericMacro, string parameter, string reason +where + not isExcluded(genericMacro, GenericsPackage::invalidGenericMacroArgumentEvaluationQuery()) and + parameter = genericMacro.getAParameter() and + genericMacro.expansionsInsideControllingExpr(parameter) > 0 and + ( + genericMacro.expansionsOutsideExpr(parameter) > 1 and + reason = "expanded multiple times outside the generic selection" + or + genericMacro.expansionsOutsideExpr(parameter) = 1 and + genericMacro.expansionsInsideAssociation(parameter, _) > 0 and + reason = "expanded outside the generic selection and inside the generic selection" + or + genericMacro.expansionsOutsideExpr(parameter) = 0 and + exists(int i | + genericMacro.expansionsInsideAssociation(parameter, i) > 1 and + reason = "expanded in generic selection " + i.toString() + " more than once" + ) + or + genericMacro.expansionsOutsideExpr(parameter) = 0 and + exists(int i | + genericMacro.expansionsInsideAssociation(parameter, i) = 0 and + reason = "not expanded in generic selection " + i.toString() + ) and + not allowedByException(parameter, genericMacro) + ) and + not genericMacro.getBody().matches(["%sizeof%", "%__alignof%", "%typeof%", "%offsetof%"]) +select genericMacro, + "Generic macro " + genericMacro.getName() + " may have unexpected behavior from side effects " + + "in parameter " + parameter + ", as it is " + reason + "." diff --git a/c/misra/src/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.ql b/c/misra/src/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.ql new file mode 100644 index 0000000000..04b12ac436 --- /dev/null +++ b/c/misra/src/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.ql @@ -0,0 +1,93 @@ +/** + * @id c/misra/default-generic-selection-not-first-or-last + * @name RULE-23-8: A default association shall appear as either the first or the last association of a generic + * @description A default association shall appear as either the first or the last association of a + * generic selection + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-23-8 + * maintainability + * external/misra/c/2012/amendment3 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.alertreporting.DeduplicateMacroResults + +class GenericWithMisplacedDefault extends C11GenericExpr { + int defaultIdx; + + GenericWithMisplacedDefault() { + getAssociationType(defaultIdx) instanceof VoidType and + not defaultIdx = 0 and + not defaultIdx = max(int i | exists(getAssociationType(i))) + } + + int getDefaultIdx() { result = defaultIdx } +} + +module GenericWithMisplacedDefaultConfig implements + DeduplicateMacroConfigSig +{ + string describe(GenericWithMisplacedDefault e) { + exists(int i | i = e.getDefaultIdx() + 1 | + i = 1 and result = "1st" + or + i = 2 and result = "2nd" + or + i = 3 and result = "3rd" + or + i > 3 and result = i.toString() + "th" + ) + } +} + +import GenericWithMisplacedDefaultConfig + +module GenericMisplacedDefaultReportConfig implements + MacroReportConfigSig +{ + /* Create a message to describe this macro, with a string describing its `ResultElement`. */ + bindingset[description] + string getMessageSameResultInAllExpansions(Macro m, string description) { + result = + "Generic macro " + m.getName() + " has default as " + description + " association, which is not first or last." + } + + /* Create a message to describe this macro, using '$@' to describe an example `ResultElement`. */ + string getMessageVariedResultInAllExpansions(Macro m) { + result = + "Generic macro " + m.getName() + " has a default association which is not first or last, for example $@." + } + + /** + * Create a message to describe this macro expansion which produces a `ResultElement`, using '$@' + * to describe the relevant macro. + */ + string getMessageResultInIsolatedExpansion(GenericWithMisplacedDefault element) { + result = + "Generic macro $@, in this expansion, has default as " + describe(element) + " association, which is not first or last." + } + + /** + * Create a message to describe a `ResultElement` which is not generated by a macro expansion. + */ + string getMessageNotInMacro(GenericWithMisplacedDefault element, Locatable optLoc1, string optStr1) { + result = + "Generic has default as " + describe(element) + " association, which is not first or last." and + optLoc1 = element and + optStr1 = "" + } +} + +import DeduplicateMacroResults as Deduplicate +import Deduplicate::Report as Report + +from Report::ReportResult res +where + not isExcluded(res.getPrimaryElement(), + GenericsPackage::defaultGenericSelectionNotFirstOrLastQuery()) +select res.getPrimaryElement(), res.getMessage(), res.getOptionalPlaceholderLocatable(), + res.getOptionalPlaceholderMessage() diff --git a/c/misra/src/rules/RULE-8-13/PointerShouldPointToConstTypeWhenPossible.ql b/c/misra/src/rules/RULE-8-13/PointerShouldPointToConstTypeWhenPossible.ql index ddb8cbcdcc..6a2c123907 100644 --- a/c/misra/src/rules/RULE-8-13/PointerShouldPointToConstTypeWhenPossible.ql +++ b/c/misra/src/rules/RULE-8-13/PointerShouldPointToConstTypeWhenPossible.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Pointers +import codingstandards.cpp.types.Pointers import codingstandards.cpp.SideEffect import codingstandards.cpp.alertreporting.HoldsForAllCopies diff --git a/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql index 8c80c64a40..a0d7c0c9ab 100644 --- a/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql +++ b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql @@ -14,9 +14,9 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Compatible +import codingstandards.cpp.types.Compatible -from FunctionDeclarationEntry f1, FunctionDeclarationEntry f2, string case +from FunctionDeclarationEntry f1, FunctionDeclarationEntry f2, string case, string pluralDo where not isExcluded(f1, Declarations4Package::declarationsOfAFunctionSameNameAndTypeQuery()) and not isExcluded(f2, Declarations4Package::declarationsOfAFunctionSameNameAndTypeQuery()) and @@ -24,16 +24,16 @@ where f1.getDeclaration() = f2.getDeclaration() and //return type check ( - not typesCompatible(f1.getType(), f2.getType()) and - case = "return type" + not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, f2) and + case = "return type" and pluralDo = "does" or //parameter type check - parameterTypesIncompatible(f1, f2) and - case = "parameter types" + not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, f2) and + case = "parameter types" and pluralDo = "do" or //parameter name check - parameterNamesIncompatible(f1, f2) and - case = "parameter names" + parameterNamesUnmatched(f1, f2) and + case = "parameter names" and pluralDo = "do" ) -select f1, "The " + case + " of re-declaration of $@ is not compatible with declaration $@", f1, +select f1, "The " + case + " of re-declaration of $@ " + pluralDo + " not use the same type names as declaration $@", f1, f1.getName(), f2, f2.getName() diff --git a/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql b/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql index 421998c582..83c67e2efa 100644 --- a/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql +++ b/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql @@ -14,12 +14,18 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Compatible +import codingstandards.cpp.types.Compatible -from VariableDeclarationEntry decl1, VariableDeclarationEntry decl2 -where - not isExcluded(decl1, Declarations4Package::declarationsOfAnObjectSameNameAndTypeQuery()) and - not isExcluded(decl2, Declarations4Package::declarationsOfAnObjectSameNameAndTypeQuery()) and +class RelevantType extends Type { + RelevantType() { + exists(VariableDeclarationEntry decl | + (relevantPair(decl, _) or relevantPair(_, decl)) and + decl.getType() = this + ) + } +} + +predicate relevantPair(VariableDeclarationEntry decl1, VariableDeclarationEntry decl2) { not decl1 = decl2 and not decl1.getVariable().getDeclaringType().isAnonymous() and // Declarations are for the same qualified name @@ -34,9 +40,17 @@ where or decl1.getVariable().(Field).getDeclaringType().(Class).getALinkTarget() = decl2.getVariable().(Field).getDeclaringType().(Class).getALinkTarget() - ) and - not typesCompatible(decl1.getType(), decl2.getType()) + ) +} + +from VariableDeclarationEntry decl1, VariableDeclarationEntry decl2 +where + not isExcluded(decl1, Declarations4Package::declarationsOfAnObjectSameNameAndTypeQuery()) and + not isExcluded(decl2, Declarations4Package::declarationsOfAnObjectSameNameAndTypeQuery()) and + relevantPair(decl1, decl2) and + not TypeEquivalence::equalTypes(decl1.getType(), + decl2.getType()) select decl1, "The object $@ of type " + decl1.getType().toString() + - " is not compatible with re-declaration $@ of type " + decl2.getType().toString(), decl1, + " does not use the same type names as re-declaration $@ of type " + decl2.getType().toString(), decl1, decl1.getName(), decl2, decl2.getName() diff --git a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql index 63f70d3541..98876ad1bd 100644 --- a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql +++ b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql @@ -17,7 +17,7 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.Identifiers -import codingstandards.cpp.Compatible +import codingstandards.cpp.types.Compatible from FunctionDeclarationEntry f1 where @@ -36,15 +36,15 @@ where f1.getName() = f2.getName() and not f2.isDefinition() and f2.getDeclaration() = f1.getDeclaration() and - //return types differ ( - not typesCompatible(f1.getType(), f2.getType()) + //return types differ + not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, f2) or //parameter types differ - parameterTypesIncompatible(f1, f2) + not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, f2) or //parameter names differ - parameterNamesIncompatible(f1, f2) + parameterNamesUnmatched(f1, f2) ) ) ) diff --git a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationObjectDefined.ql b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationObjectDefined.ql index 7e5baacd9a..613ce56806 100644 --- a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationObjectDefined.ql +++ b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationObjectDefined.ql @@ -17,7 +17,16 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.Identifiers -import codingstandards.cpp.Compatible +import codingstandards.cpp.types.Compatible + +class RelevantType extends Type { + RelevantType() { + exists(VariableDeclarationEntry decl | + count(VariableDeclarationEntry others | others.getDeclaration() = decl.getDeclaration()) > 1 and + decl.getType() = this + ) + } +} from VariableDeclarationEntry decl1 where @@ -28,6 +37,7 @@ where not exists(VariableDeclarationEntry decl2 | not decl2.isDefinition() and decl1.getDeclaration() = decl2.getDeclaration() and - typesCompatible(decl1.getType(), decl2.getType()) + TypeEquivalence::equalTypes(decl1.getType(), + decl2.getType()) ) select decl1, "No separate compatible declaration found for this definition." diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected index 731aebb1be..9a373a644c 100644 --- a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected +++ b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinition.expected @@ -1,12 +1,12 @@ -| test.c:6:5:6:6 | definition of g2 | Unused object 'g2'. | test.c:6:5:6:6 | test.c:6:5:6:6 | (ignored) | -| test.c:9:5:9:6 | definition of g3 | Unused object 'g3'. | test.c:9:5:9:6 | test.c:9:5:9:6 | (ignored) | -| test.c:20:7:20:8 | definition of l2 | Unused object 'l2'. | test.c:20:7:20:8 | test.c:20:7:20:8 | (ignored) | -| test.c:27:7:27:8 | definition of l5 | Unused object 'l5'. | test.c:27:7:27:8 | test.c:27:7:27:8 | (ignored) | -| test.c:37:10:37:11 | definition of g5 | Unused object 'g5'. | test.c:37:10:37:11 | test.c:37:10:37:11 | (ignored) | -| test.c:45:9:45:10 | definition of g6 | Unused object 'g6'. | test.c:45:9:45:10 | test.c:45:9:45:10 | (ignored) | -| test.c:51:5:51:6 | definition of g7 | Unused object 'g7'. | test.c:51:5:51:6 | test.c:51:5:51:6 | (ignored) | -| test.c:64:3:64:18 | ONLY_DEF_VAR(x) | Invocation of macro '$@' defines unused object 'l2'. | test.c:60:1:60:34 | test.c:60:1:60:34 | ONLY_DEF_VAR | -| test.c:68:1:71:5 | #define ALSO_DEF_VAR(x) int x = 0; while (1) ; | Macro 'ALSO_DEF_VAR' defines unused object with an invocation-dependent name, for example, '$@'. | test.c:73:16:73:17 | test.c:73:16:73:17 | l1 | -| test.c:77:1:82:3 | #define DEF_UNUSED_INNER_VAR() { int _v = 0; while (1) ; } | Macro 'DEF_UNUSED_INNER_VAR' defines unused object '_v'. | test.c:77:1:82:3 | test.c:77:1:82:3 | (ignored) | -| test.c:119:11:119:13 | definition of g10 | Unused object 'g10'. | test.c:119:11:119:13 | test.c:119:11:119:13 | (ignored) | -| test.c:124:13:124:14 | definition of l2 | Unused object 'l2'. | test.c:124:13:124:14 | test.c:124:13:124:14 | (ignored) | +| test.c:6:5:6:6 | definition of g2 | Unused object 'g2'. | test.c:6:5:6:6 | definition of g2 | (ignored) | +| test.c:9:5:9:6 | definition of g3 | Unused object 'g3'. | test.c:9:5:9:6 | definition of g3 | (ignored) | +| test.c:20:7:20:8 | definition of l2 | Unused object 'l2'. | test.c:20:7:20:8 | definition of l2 | (ignored) | +| test.c:27:7:27:8 | definition of l5 | Unused object 'l5'. | test.c:27:7:27:8 | definition of l5 | (ignored) | +| test.c:37:10:37:11 | definition of g5 | Unused object 'g5'. | test.c:37:10:37:11 | definition of g5 | (ignored) | +| test.c:45:9:45:10 | definition of g6 | Unused object 'g6'. | test.c:45:9:45:10 | definition of g6 | (ignored) | +| test.c:51:5:51:6 | definition of g7 | Unused object 'g7'. | test.c:51:5:51:6 | definition of g7 | (ignored) | +| test.c:64:3:64:18 | ONLY_DEF_VAR(x) | Invocation of macro '$@' defines unused object 'l2'. | test.c:60:1:60:34 | #define ONLY_DEF_VAR(x) int x = 0; | ONLY_DEF_VAR | +| test.c:68:1:71:5 | #define ALSO_DEF_VAR(x) int x = 0; while (1) ; | Macro 'ALSO_DEF_VAR' defines unused object with an invocation-dependent name, for example, '$@'. | test.c:73:16:73:17 | definition of l1 | l1 | +| test.c:77:1:82:3 | #define DEF_UNUSED_INNER_VAR() { int _v = 0; while (1) ; } | Macro 'DEF_UNUSED_INNER_VAR' defines unused object '_v'. | test.c:77:1:82:3 | #define DEF_UNUSED_INNER_VAR() { int _v = 0; while (1) ; } | (ignored) | +| test.c:119:11:119:13 | definition of g10 | Unused object 'g10'. | test.c:119:11:119:13 | definition of g10 | (ignored) | +| test.c:124:13:124:14 | definition of l2 | Unused object 'l2'. | test.c:124:13:124:14 | definition of l2 | (ignored) | diff --git a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.expected b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.expected index cf3c0b64e1..fa191e5d68 100644 --- a/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.expected +++ b/c/misra/test/rules/RULE-2-8/UnusedObjectDefinitionStrict.expected @@ -1,4 +1,4 @@ -| test.c:87:29:87:30 | definition of g8 | Unused object 'g8'. | test.c:87:29:87:30 | test.c:87:29:87:30 | (ignored) | -| test.c:92:3:92:30 | ONLY_DEF_ATTR_UNUSED_VAR(x) | Invocation of macro '$@' defines unused object 'l2'. | test.c:88:1:88:70 | test.c:88:1:88:70 | ONLY_DEF_ATTR_UNUSED_VAR | -| test.c:96:1:99:5 | #define ALSO_DEF_ATTR_UNUSED_VAR(x) __attribute__((unused)) int x = 0; while (1) ; | Macro 'ALSO_DEF_ATTR_UNUSED_VAR' defines unused object with an invocation-dependent name, for example, '$@'. | test.c:101:28:101:29 | test.c:101:28:101:29 | l1 | -| test.c:106:1:111:3 | #define DEF_ATTR_UNUSED_INNER_VAR() { __attribute__((unused)) int _v = 0; while (1) ; } | Macro 'DEF_ATTR_UNUSED_INNER_VAR' defines unused object '_v'. | test.c:106:1:111:3 | test.c:106:1:111:3 | (ignored) | +| test.c:87:29:87:30 | definition of g8 | Unused object 'g8'. | test.c:87:29:87:30 | definition of g8 | (ignored) | +| test.c:92:3:92:30 | ONLY_DEF_ATTR_UNUSED_VAR(x) | Invocation of macro '$@' defines unused object 'l2'. | test.c:88:1:88:70 | #define ONLY_DEF_ATTR_UNUSED_VAR(x) __attribute__((unused)) int x = 0; | ONLY_DEF_ATTR_UNUSED_VAR | +| test.c:96:1:99:5 | #define ALSO_DEF_ATTR_UNUSED_VAR(x) __attribute__((unused)) int x = 0; while (1) ; | Macro 'ALSO_DEF_ATTR_UNUSED_VAR' defines unused object with an invocation-dependent name, for example, '$@'. | test.c:101:28:101:29 | definition of l1 | l1 | +| test.c:106:1:111:3 | #define DEF_ATTR_UNUSED_INNER_VAR() { __attribute__((unused)) int _v = 0; while (1) ; } | Macro 'DEF_ATTR_UNUSED_INNER_VAR' defines unused object '_v'. | test.c:106:1:111:3 | #define DEF_ATTR_UNUSED_INNER_VAR() { __attribute__((unused)) int _v = 0; while (1) ; } | (ignored) | diff --git a/c/misra/test/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.expected b/c/misra/test/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.expected new file mode 100644 index 0000000000..2534e47012 --- /dev/null +++ b/c/misra/test/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.expected @@ -0,0 +1,3 @@ +| test.c:2:1:2:30 | #define M1 _Generic(1, int: 1) | Generic macro M1 uses controlling expr 1, which doesn't match any macro parameter. | +| test.c:4:1:4:33 | #define M2(X) _Generic(1, int: X) | Generic macro M2 uses controlling expr 1, which doesn't match any macro parameter. | +| test.c:18:1:18:38 | #define M9(X) g(_Generic((Y), int: 1)) | Generic macro M9 uses controlling expr (Y), which doesn't match any macro parameter. | diff --git a/c/misra/test/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.qlref b/c/misra/test/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.qlref new file mode 100644 index 0000000000..1ca5f792fa --- /dev/null +++ b/c/misra/test/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.qlref @@ -0,0 +1 @@ +rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.expected b/c/misra/test/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.expected new file mode 100644 index 0000000000..476a9320b8 --- /dev/null +++ b/c/misra/test/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.expected @@ -0,0 +1 @@ +| test.c:21:3:21:21 | _Generic | Generic expression with controlling expression $@ is not expanded froma macro | test.c:21:12:21:12 | 1 | 1 | diff --git a/c/misra/test/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.qlref b/c/misra/test/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.qlref new file mode 100644 index 0000000000..59fae02b7f --- /dev/null +++ b/c/misra/test/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.qlref @@ -0,0 +1 @@ +rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-1/test.c b/c/misra/test/rules/RULE-23-1/test.c new file mode 100644 index 0000000000..f27541dd38 --- /dev/null +++ b/c/misra/test/rules/RULE-23-1/test.c @@ -0,0 +1,25 @@ +// NON_COMPLIANT: +#define M1 _Generic(1, int: 1) +// NON_COMPLIANT: +#define M2(X) _Generic(1, int: X) +// COMPLIANT: +#define M3(X) _Generic((X), int: 1) +// COMPLIANT: +#define M4(X) _Generic((X), int: 1) +// COMPLIANT: +#define M5(X) _Generic((X + X), int: 1) +int f1(int a, int b); +// COMPLIANT: +#define M6(X) _Generic(f(1, (X)), int: 1) +#define M7(X) 1 + _Generic((X), int: 1) +// COMPLIANT: +#define M8(X) g(_Generic((X), int: 1)) +// NON_COMPLIANT: +#define M9(X) g(_Generic((Y), int: 1)) + +void f2() { + _Generic(1, int: 1); // NON_COMPLIANT + M1; // NON_COMPLIANT + M2(1); // NON_COMPLIANT + M3(1); // COMPLIANT +} diff --git a/c/misra/test/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.expected b/c/misra/test/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.expected new file mode 100644 index 0000000000..1abcb4f2bb --- /dev/null +++ b/c/misra/test/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.expected @@ -0,0 +1,3 @@ +| test.c:4:1:4:37 | #define M2(X) _Generic((X)++, int: 1) | Generic selection macro M2 contains a side effect '... ++', which is not from macro invocation arguments. | test.c:4:1:4:37 | #define M2(X) _Generic((X)++, int: 1) | (ignored) | +| test.c:7:1:7:38 | #define M3(X) _Generic(l1++, int: (X)) | Generic selection macro M3 contains a side effect '... ++', which is not from macro invocation arguments. | test.c:7:1:7:38 | #define M3(X) _Generic(l1++, int: (X)) | (ignored) | +| test.c:42:1:44:24 | #define M5(X) static volatile l ## X; _Generic(l ## X, int: 1) | Generic selection in macro M5 contains an invocation-dependent side effect which is not from macro invocation arguments, for example $@. | test.c:47:3:47:7 | _Generic | side effect 'la' | diff --git a/c/misra/test/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.qlref b/c/misra/test/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.qlref new file mode 100644 index 0000000000..bb3e39a58c --- /dev/null +++ b/c/misra/test/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.qlref @@ -0,0 +1 @@ +rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-2/test.c b/c/misra/test/rules/RULE-23-2/test.c new file mode 100644 index 0000000000..6a25e15189 --- /dev/null +++ b/c/misra/test/rules/RULE-23-2/test.c @@ -0,0 +1,49 @@ +#define M1(X) _Generic((X), int: 1) + +// NON_COMPLIANT: +#define M2(X) _Generic((X)++, int: 1) + +// NON_COMPLIANT: +#define M3(X) _Generic(l1++, int: (X)) + +// COMPLIANT: +#define M3_WRAPPER(X) M3(X) + +#define M4(X) _Generic((X)(), int: 1) + +void f1() { + int l1; + + _Generic(1, int: 1); // COMPLIANT + M1(1); // COMPLIANT + _Generic(l1, int: 1); // COMPLIANT + M1(l1); // COMPLIANT + + _Generic(l1++, + int: 1); // COMPLIANT: side effect is not from a macro argument. + M1(l1++); // COMPLIANT + M2(l1); // NON-COMPLIANT: at macro definition + M3(1); // NON-COMPLIANT: at macro definition + M3_WRAPPER(1); // NON-COMPLIANT: at definition of M3 +} + +int g1; +int pure() { return g1; } + +int impure() { return g1++; } + +void f2() { + M1(pure()); // COMPLIANT + M1(impure()); // COMPLIANT + M4(pure); // COMPLIANT + M4(impure); // NON_COMPLIANT[False negative] +} + +#define M5(X) \ + static volatile l##X; \ + _Generic(l##X, int: 1) + +void f3() { + M5(a); // NON-COMPLIANT + M5(b); // NON-COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.expected b/c/misra/test/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.expected new file mode 100644 index 0000000000..50d6277e84 --- /dev/null +++ b/c/misra/test/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.expected @@ -0,0 +1,2 @@ +| test.c:2:1:2:35 | #define M1 _Generic(1, default: 1); | Generic selection contains no non-default association. | +| test.c:14:3:14:25 | _Generic | Generic selection contains no non-default association. | diff --git a/c/misra/test/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.qlref b/c/misra/test/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.qlref new file mode 100644 index 0000000000..b44de9083e --- /dev/null +++ b/c/misra/test/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.qlref @@ -0,0 +1 @@ +rules/RULE-23-3/GenericWithoutNonDefaultAssociation.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-3/test.c b/c/misra/test/rules/RULE-23-3/test.c new file mode 100644 index 0000000000..d3f093f242 --- /dev/null +++ b/c/misra/test/rules/RULE-23-3/test.c @@ -0,0 +1,23 @@ +// NON-COMPLIANT +#define M1 _Generic(1, default: 1); +// COMPLIANT +#define M2 _Generic(1, int: 1); +// COMPLIANT +#define M3 _Generic(1, int: 1, default: 1); +// COMPLIANT +#define M4 _Generic(1, int: 1, long: 1); + +void f() { + // Invalid generics: + // _Generic(1); + // _Generic(1, void: 1); + _Generic(1, default: 1); // NON-COMPLIANT + _Generic(1, int: 1); // COMPLIANT + _Generic(1, int: 1, default: 1); // COMPLIANT + _Generic(1, int: 1, long: 1); // COMPLIANT + + M1; + M2; + M3; + M4; +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-4/GenericAssociationWithUnselectableType.expected b/c/misra/test/rules/RULE-23-4/GenericAssociationWithUnselectableType.expected new file mode 100644 index 0000000000..27030fc768 --- /dev/null +++ b/c/misra/test/rules/RULE-23-4/GenericAssociationWithUnselectableType.expected @@ -0,0 +1,13 @@ +| test.c:11:18:11:18 | 1 | Generic selection uses unselectable type 'const int', due to qualifiers removed'. | test.c:11:18:11:18 | 1 | side effect | +| test.c:12:21:12:21 | 1 | Generic selection uses unselectable type 'volatile int', due to qualifiers removed'. | test.c:12:21:12:21 | 1 | side effect | +| test.c:13:20:13:20 | 1 | Generic selection uses unselectable type '_Atomic(int)', due to qualifiers removed'. | test.c:13:20:13:20 | 1 | side effect | +| test.c:16:27:16:27 | 1 | Generic selection uses unselectable type 'const volatile int', due to qualifiers removed'. | test.c:16:27:16:27 | 1 | side effect | +| test.c:18:18:18:18 | 1 | Generic selection uses unselectable type '(unnamed class/struct/union)', due to containing an anonymous struct or union type'. | test.c:18:18:18:18 | 1 | side effect | +| test.c:19:20:19:20 | 1 | Generic selection uses unselectable type 'struct *', due to containing an anonymous struct or union type'. | test.c:19:20:19:20 | 1 | side effect | +| test.c:24:17:24:17 | 1 | Generic selection uses unselectable type '(unnamed class/struct/union)', due to containing an anonymous struct or union type'. | test.c:24:17:24:17 | 1 | side effect | +| test.c:25:19:25:19 | 1 | Generic selection uses unselectable type 'union *', due to containing an anonymous struct or union type'. | test.c:25:19:25:19 | 1 | side effect | +| test.c:31:15:31:15 | 1 | Generic selection uses unselectable type 'int[3]', due to array-to-pointer decay'. | test.c:31:15:31:15 | 1 | side effect | +| test.c:40:1:40:53 | #define M1(X) _Generic((X), const int: 1, default: 0) | Generic in macro M1 has unselectable type 'const int', due to qualifiers removed. | test.c:40:1:40:53 | #define M1(X) _Generic((X), const int: 1, default: 0) | (ignored) | +| test.c:42:1:42:46 | #define M2(X) _Generic(1, X[3]: 1, default: 0) | Generic in macro M2 has an invocation-dependent unselectable type, for example $@. | test.c:49:3:49:10 | 1 | 'char[3]', due to array-to-pointer decay | +| test.c:52:3:52:15 | M3(X) | Generic resulting from invocation of macro $@ contains an unselectable type 'const int', due to qualifiers removed. | test.c:44:1:44:43 | #define M3(X) _Generic(1, X: 1, default: 0) | M3 | +| test.c:64:18:64:18 | 1 | Generic selection uses unselectable type 'const_int', due to qualifiers removed'. | test.c:64:18:64:18 | 1 | side effect | diff --git a/c/misra/test/rules/RULE-23-4/GenericAssociationWithUnselectableType.qlref b/c/misra/test/rules/RULE-23-4/GenericAssociationWithUnselectableType.qlref new file mode 100644 index 0000000000..1214be7ce2 --- /dev/null +++ b/c/misra/test/rules/RULE-23-4/GenericAssociationWithUnselectableType.qlref @@ -0,0 +1 @@ +rules/RULE-23-4/GenericAssociationWithUnselectableType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-4/test.c b/c/misra/test/rules/RULE-23-4/test.c new file mode 100644 index 0000000000..135ab4d0f7 --- /dev/null +++ b/c/misra/test/rules/RULE-23-4/test.c @@ -0,0 +1,73 @@ +typedef struct { +} empty_struct_t; +struct empty_struct {}; +typedef union { +} empty_union_t; +union empty_union {}; + +void f() { + _Generic(1, + int: 1, // COMPLIANT + const int: 1, // NON-COMPLIANT + volatile int: 1, // NON-COMPLIANT + _Atomic int: 1, // NON-COMPLIANT + int *: 1, // COMPLIANT + int const *: 1, // COMPLIANT + const volatile int: 1, // NON-COMPLIANT + int volatile const *: 1, // COMPLIANT + struct {}: 1, // NON-COMPLIANT + struct {} *: 1, // NON-COMPLIANT + empty_struct_t: 1, // COMPLIANT + struct empty_struct: 1, // COMPLIANT + empty_struct_t *: 1, // COMPLIANT + struct empty_struct *: 1, // COMPLIANT + union {}: 1, // NON-COMPLIANT + union {} *: 1, // NON-COMPLIANT + empty_union_t: 1, // COMPLIANT + union empty_union: 1, // COMPLIANT + empty_union_t *: 1, // COMPLIANT + union empty_union *: 1, // COMPLIANT + // int[]: 1, // compile error + int[3]: 1, // NON-COMPLIANT + int(*)[3]: 1, // COMPLIANT: pointer to array OK + // int (int*): 1, // compile error + int (*)(int *): 1, // COMPLIANT: function pointers OK + default: 1 // COMPLIANT + ); +} + +// NON-COMPLIANT +#define M1(X) _Generic((X), const int: 1, default: 0) +// NON-COMPLIANT +#define M2(X) _Generic(1, X[3]: 1, default: 0) +// COMPLIANT +#define M3(X) _Generic(1, X: 1, default: 0) + +void f2() { + M1(1); + M2(int); + M2(char); + + M3(int); // COMPLIANT + M3(const int); // NON-COMPLIANT +} + +typedef int int_t; +typedef int *int_ptr; +const typedef int const_int; +const typedef int *const_int_ptr; +typedef long const *long_const_ptr; + +void f3() { + _Generic(1, + int_t: 1, // COMPLIANT + const_int: 1, // NON-COMPLIANT + const_int_ptr: 1, // COMPLIANT + long_const_ptr: 1, // COMPLIANT + const int_ptr: 1, // COMPLIANT + default: 1 // COMPLIANT + ); +} + +// Type written here so it gets added to the database, see LvalueConversion.qll. +char *g; \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.expected b/c/misra/test/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.expected new file mode 100644 index 0000000000..994d55968c --- /dev/null +++ b/c/misra/test/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.expected @@ -0,0 +1,84 @@ +| test.c:41:3:41:44 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const int *. | test.c:41:3:41:44 | _Generic | | +| test.c:42:3:42:47 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to volatile int *. | test.c:42:3:42:47 | _Generic | | +| test.c:43:3:43:53 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile int *. | test.c:43:3:43:53 | _Generic | | +| test.c:44:3:44:39 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to void *. | test.c:44:3:44:39 | _Generic | | +| test.c:45:3:45:45 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const void *. | test.c:45:3:45:45 | _Generic | | +| test.c:46:3:46:54 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile void *. | test.c:46:3:46:54 | _Generic | | +| test.c:48:3:48:38 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to int *. | test.c:48:3:48:38 | _Generic | | +| test.c:50:3:50:39 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to void *. | test.c:50:3:50:39 | _Generic | | +| test.c:51:3:51:45 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const void *. | test.c:51:3:51:45 | _Generic | | +| test.c:52:3:52:54 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile void *. | test.c:52:3:52:54 | _Generic | | +| test.c:57:3:57:53 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile int *. | test.c:57:3:57:53 | _Generic | | +| test.c:59:3:59:38 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to int *. | test.c:59:3:59:38 | _Generic | | +| test.c:61:3:61:53 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to const volatile int *. | test.c:61:3:61:53 | _Generic | | +| test.c:62:3:62:39 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to void *. | test.c:62:3:62:39 | _Generic | | +| test.c:63:3:63:54 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to const volatile void *. | test.c:63:3:63:54 | _Generic | | +| test.c:69:3:69:38 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to int *. | test.c:69:3:69:38 | _Generic | | +| test.c:70:3:70:44 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const int *. | test.c:70:3:70:44 | _Generic | | +| test.c:71:3:71:47 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to volatile int *. | test.c:71:3:71:47 | _Generic | | +| test.c:73:3:73:39 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to void *. | test.c:73:3:73:39 | _Generic | | +| test.c:74:3:74:45 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const void *. | test.c:74:3:74:45 | _Generic | | +| test.c:75:3:75:54 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const volatile void *. | test.c:75:3:75:54 | _Generic | | +| test.c:77:3:77:38 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to int *. | test.c:77:3:77:38 | _Generic | | +| test.c:78:3:78:44 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to const int *. | test.c:78:3:78:44 | _Generic | | +| test.c:79:3:79:47 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to volatile int *. | test.c:79:3:79:47 | _Generic | | +| test.c:80:3:80:53 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to const volatile int *. | test.c:80:3:80:53 | _Generic | | +| test.c:82:3:82:45 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to const void *. | test.c:82:3:82:45 | _Generic | | +| test.c:83:3:83:54 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to const volatile void *. | test.c:83:3:83:54 | _Generic | | +| test.c:85:3:85:38 | _Generic | Generic matched default selection, as controlling argument type const void * does not undergo pointer conversion to int *. | test.c:85:3:85:38 | _Generic | | +| test.c:86:3:86:44 | _Generic | Generic matched default selection, as controlling argument type const void * does not undergo pointer conversion to const int *. | test.c:86:3:86:44 | _Generic | | +| test.c:87:3:87:53 | _Generic | Generic matched default selection, as controlling argument type const void * does not undergo pointer conversion to const volatile int *. | test.c:87:3:87:53 | _Generic | | +| test.c:88:3:88:39 | _Generic | Generic matched default selection, as controlling argument type const void * does not undergo pointer conversion to void *. | test.c:88:3:88:39 | _Generic | | +| test.c:90:3:90:54 | _Generic | Generic matched default selection, as controlling argument type const void * does not undergo pointer conversion to const volatile void *. | test.c:90:3:90:54 | _Generic | | +| test.c:94:3:94:38 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to int *. | test.c:94:3:94:38 | _Generic | | +| test.c:95:3:95:44 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to const int *. | test.c:95:3:95:44 | _Generic | | +| test.c:96:3:96:47 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to volatile int *. | test.c:96:3:96:47 | _Generic | | +| test.c:97:3:97:53 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to const volatile int *. | test.c:97:3:97:53 | _Generic | | +| test.c:98:3:98:39 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to void *. | test.c:98:3:98:39 | _Generic | | +| test.c:99:3:99:45 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to const void *. | test.c:99:3:99:45 | _Generic | | +| test.c:119:3:119:45 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const int *. | test.c:119:3:119:45 | _Generic | | +| test.c:120:3:120:48 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to volatile int *. | test.c:120:3:120:48 | _Generic | | +| test.c:121:3:121:54 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile int *. | test.c:121:3:121:54 | _Generic | | +| test.c:122:3:122:40 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to void *. | test.c:122:3:122:40 | _Generic | | +| test.c:123:3:123:46 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const void *. | test.c:123:3:123:46 | _Generic | | +| test.c:124:3:124:55 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile void *. | test.c:124:3:124:55 | _Generic | | +| test.c:126:3:126:39 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to int *. | test.c:126:3:126:39 | _Generic | | +| test.c:128:3:128:40 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to void *. | test.c:128:3:128:40 | _Generic | | +| test.c:129:3:129:46 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const void *. | test.c:129:3:129:46 | _Generic | | +| test.c:130:3:130:55 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile void *. | test.c:130:3:130:55 | _Generic | | +| test.c:135:3:135:54 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile int *. | test.c:135:3:135:54 | _Generic | | +| test.c:137:3:137:39 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to int *. | test.c:137:3:137:39 | _Generic | | +| test.c:139:3:139:54 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to const volatile int *. | test.c:139:3:139:54 | _Generic | | +| test.c:140:3:140:40 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to void *. | test.c:140:3:140:40 | _Generic | | +| test.c:141:3:141:55 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to const volatile void *. | test.c:141:3:141:55 | _Generic | | +| test.c:147:3:147:39 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to int *. | test.c:147:3:147:39 | _Generic | | +| test.c:148:3:148:45 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const int *. | test.c:148:3:148:45 | _Generic | | +| test.c:149:3:149:48 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to volatile int *. | test.c:149:3:149:48 | _Generic | | +| test.c:151:3:151:40 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to void *. | test.c:151:3:151:40 | _Generic | | +| test.c:152:3:152:46 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const void *. | test.c:152:3:152:46 | _Generic | | +| test.c:153:3:153:55 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const volatile void *. | test.c:153:3:153:55 | _Generic | | +| test.c:156:3:156:45 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const int *. | test.c:156:3:156:45 | _Generic | | +| test.c:157:3:157:48 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to volatile int *. | test.c:157:3:157:48 | _Generic | | +| test.c:158:3:158:54 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile int *. | test.c:158:3:158:54 | _Generic | | +| test.c:159:3:159:40 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to void *. | test.c:159:3:159:40 | _Generic | | +| test.c:160:3:160:46 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const void *. | test.c:160:3:160:46 | _Generic | | +| test.c:161:3:161:55 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile void *. | test.c:161:3:161:55 | _Generic | | +| test.c:163:3:163:39 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to int *. | test.c:163:3:163:39 | _Generic | | +| test.c:165:3:165:40 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to void *. | test.c:165:3:165:40 | _Generic | | +| test.c:166:3:166:46 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const void *. | test.c:166:3:166:46 | _Generic | | +| test.c:167:3:167:55 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile void *. | test.c:167:3:167:55 | _Generic | | +| test.c:172:3:172:54 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile int *. | test.c:172:3:172:54 | _Generic | | +| test.c:180:3:180:48 | _Generic | Generic matched default selection, as controlling argument type int(*)[3] does not undergo pointer conversion to int(*const)[3]. | test.c:180:3:180:48 | _Generic | | +| test.c:188:3:191:18 | _Generic | Generic matched default selection, as controlling argument type int(*)[3] does not undergo pointer conversion to int(*const)[3]. | test.c:188:3:191:18 | _Generic | | +| test.c:200:3:200:47 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to int *. | test.c:200:3:200:47 | _Generic | | +| test.c:201:3:201:47 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to void *. | test.c:201:3:201:47 | _Generic | | +| test.c:215:3:215:44 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const int *. | test.c:215:3:215:44 | _Generic | | +| test.c:216:3:216:46 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const int_t *. | test.c:216:3:216:46 | _Generic | | +| test.c:217:3:217:42 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to c_int_t *. | test.c:217:3:217:42 | _Generic | | +| test.c:221:3:221:45 | _Generic | Generic matched default selection, as controlling argument type int_t * does not undergo pointer conversion to const int *. | test.c:221:3:221:45 | _Generic | | +| test.c:222:3:222:47 | _Generic | Generic matched default selection, as controlling argument type int_t * does not undergo pointer conversion to const int_t *. | test.c:222:3:222:47 | _Generic | | +| test.c:223:3:223:43 | _Generic | Generic matched default selection, as controlling argument type int_t * does not undergo pointer conversion to c_int_t *. | test.c:223:3:223:43 | _Generic | | +| test.c:225:3:225:38 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to int *. | test.c:225:3:225:38 | _Generic | | +| test.c:226:3:226:40 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to int_t *. | test.c:226:3:226:40 | _Generic | | +| test.c:231:3:231:39 | _Generic | Generic matched default selection, as controlling argument type c_int_t * does not undergo pointer conversion to int *. | test.c:231:3:231:39 | _Generic | | +| test.c:232:3:232:41 | _Generic | Generic matched default selection, as controlling argument type c_int_t * does not undergo pointer conversion to int_t *. | test.c:232:3:232:41 | _Generic | | diff --git a/c/misra/test/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.qlref b/c/misra/test/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.qlref new file mode 100644 index 0000000000..c6b02b6273 --- /dev/null +++ b/c/misra/test/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.qlref @@ -0,0 +1 @@ +rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-5/test.c b/c/misra/test/rules/RULE-23-5/test.c new file mode 100644 index 0000000000..d9e140f0af --- /dev/null +++ b/c/misra/test/rules/RULE-23-5/test.c @@ -0,0 +1,236 @@ +void f1(); + +void f2() { + int l1; + int *l2; + const int *l3; + volatile int *l4; + volatile const int *l5; + void *l6; + const void *l7; + volatile void *l8; + const volatile void *l9; + + // No violation for missing pointer/integral conversions: + _Generic(l1, // COMPLIANT + int *: f1, + const int *: f1, + volatile int *: f1, + void *: f1, + const void *: f1, + default: f1); // COMPLIANT + _Generic(l2, int: f1, default: f1); // COMPLIANT + _Generic(l3, int: f1, default: f1); // COMPLIANT + _Generic(l4, int: f1, default: f1); // COMPLIANT + _Generic(l5, int: f1, default: f1); // COMPLIANT + + // Compliant, default case is not matched + _Generic(l1, int: f1); // COMPLIANT + _Generic(l2, int *: f1); // COMPLIANT + _Generic(l3, const int *: f1); // COMPLIANT + _Generic(l4, volatile int *: f1); // COMPLIANT + _Generic(l5, volatile const int *: f1); // COMPLIANT + _Generic(l6, void *: f1); // COMPLIANT + _Generic(l7, const void *: f1); // COMPLIANT + _Generic(l8, volatile void *: f1); // COMPLIANT + _Generic(l9, const volatile void *: f1); // COMPLIANT + + // Violation, match default case due to lack of pointer to pointer + // conversions: + _Generic(l2, int *: f1, default: f1); // COMPLIANT + _Generic(l2, const int *: f1, default: f1); // NON-COMPLIANT + _Generic(l2, volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l2, const volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l2, void *: f1, default: f1); // NON-COMPLIANT + _Generic(l2, const void *: f1, default: f1); // NON-COMPLIANT + _Generic(l2, const volatile void *: f1, default: f1); // NON-COMPLIANT + + _Generic(l3, int *: f1, default: f1); // NON-COMPLIANT + _Generic(l3, const int *: f1, default: f1); // COMPLIANT + _Generic(l3, void *: f1, default: f1); // NON-COMPLIANT + _Generic(l3, const void *: f1, default: f1); // NON-COMPLIANT + _Generic(l3, const volatile void *: f1, default: f1); // NON-COMPLIANT + // Obviously not volatile: + _Generic(l3, volatile int *: f1, default: f1); // COMPLIANT + // Debatable, but volatile const int* is assignable to const int* so its + // considered risky + _Generic(l3, const volatile int *: f1, default: f1); // NON-COMPLIANT + + _Generic(l4, int *: f1, default: f1); // NON-COMPLIANT + _Generic(l4, volatile int *: f1, default: f1); // COMPLIANT + _Generic(l4, const volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l4, void *: f1, default: f1); // NON-COMPLIANT + _Generic(l4, const volatile void *: f1, default: f1); // NON-COMPLIANT + // Debatable, but volatile int* isn't assignable to const int* or vice versa. + _Generic(l4, const int *: f1, default: f1); // COMPLIANT + // Debatable, but volatile int* isn't assignable to const void* or vice versa. + _Generic(l4, const void *: f1, default: f1); // COMPLIANT + + _Generic(l5, int *: f1, default: f1); // NON-COMPLIANT + _Generic(l5, const int *: f1, default: f1); // NON-COMPLIANT + _Generic(l5, volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l5, const volatile int *: f1, default: f1); // COMPLIANT + _Generic(l5, void *: f1, default: f1); // NON-COMPLIANT + _Generic(l5, const void *: f1, default: f1); // NON-COMPLIANT + _Generic(l5, const volatile void *: f1, default: f1); // NON-COMPLIANT + + _Generic(l6, int *: f1, default: f1); // NON-COMPLIANT + _Generic(l6, const int *: f1, default: f1); // NON-COMPLIANT + _Generic(l6, volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l6, const volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l6, void *: f1, default: f1); // COMPLIANT + _Generic(l6, const void *: f1, default: f1); // NON-COMPLIANT + _Generic(l6, const volatile void *: f1, default: f1); // NON-COMPLIANT + + _Generic(l7, int *: f1, default: f1); // NON-COMPLIANT + _Generic(l7, const int *: f1, default: f1); // NON-COMPLIANT + _Generic(l7, const volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l7, void *: f1, default: f1); // NON-COMPLIANT + _Generic(l7, const void *: f1, default: f1); // COMPLIANT + _Generic(l7, const volatile void *: f1, default: f1); // NON-COMPLIANT + // Debatable, but const void* isn't assignable to volatile int* or vice versa. + _Generic(l7, volatile int *: f1, default: f1); // COMPLIANT + + _Generic(l9, int *: f1, default: f1); // NON-COMPLIANT + _Generic(l9, const int *: f1, default: f1); // NON-COMPLIANT + _Generic(l9, volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l9, const volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l9, void *: f1, default: f1); // NON-COMPLIANT + _Generic(l9, const void *: f1, default: f1); // NON-COMPLIANT + _Generic(l9, const volatile void *: f1, default: f1); // COMPLIANT + + /** + * Edge case 1: The controlling expression undergoes lvalue conversion, so + * arrays become pointers and qualifiers on pointers are stripped. + */ + int l10[3]; + const int l11[3]; + volatile int l12[3]; + const volatile int l13[3]; + int *const l14; + const int *const l15; + + _Generic(l10, int *: f1, default: f1); // COMPLIANT + _Generic(l11, const int *: f1, default: f1); // COMPLIANT + _Generic(l12, volatile int *: f1, default: f1); // COMPLIANT + _Generic(l13, const volatile int *: f1, default: f1); // COMPLIANT + + _Generic(l10, int *: f1, default: f1); // COMPLIANT + _Generic(l10, const int *: f1, default: f1); // NON-COMPLIANT + _Generic(l10, volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l10, const volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l10, void *: f1, default: f1); // NON-COMPLIANT + _Generic(l10, const void *: f1, default: f1); // NON-COMPLIANT + _Generic(l10, const volatile void *: f1, default: f1); // NON-COMPLIANT + + _Generic(l11, int *: f1, default: f1); // NON-COMPLIANT + _Generic(l11, const int *: f1, default: f1); // COMPLIANT + _Generic(l11, void *: f1, default: f1); // NON-COMPLIANT + _Generic(l11, const void *: f1, default: f1); // NON-COMPLIANT + _Generic(l11, const volatile void *: f1, default: f1); // NON-COMPLIANT + // Obviously not volatile: + _Generic(l11, volatile int *: f1, default: f1); // COMPLIANT + // Debatable, but volatile const int* is assignable to const int* so its + // considered risky + _Generic(l11, const volatile int *: f1, default: f1); // NON-COMPLIANT + + _Generic(l12, int *: f1, default: f1); // NON-COMPLIANT + _Generic(l12, volatile int *: f1, default: f1); // COMPLIANT + _Generic(l12, const volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l12, void *: f1, default: f1); // NON-COMPLIANT + _Generic(l12, const volatile void *: f1, default: f1); // NON-COMPLIANT + // Debatab12e, but volatile int* isn't assignable to const int* or vice versa. + _Generic(l12, const int *: f1, default: f1); // COMPLIANT + // Debatable, but volatile int* isn't assignable to const void* or vice versa. + _Generic(l12, const void *: f1, default: f1); // COMPLIANT + + _Generic(l13, int *: f1, default: f1); // NON-COMPLIANT + _Generic(l13, const int *: f1, default: f1); // NON-COMPLIANT + _Generic(l13, volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l13, const volatile int *: f1, default: f1); // COMPLIANT + _Generic(l13, void *: f1, default: f1); // NON-COMPLIANT + _Generic(l13, const void *: f1, default: f1); // NON-COMPLIANT + _Generic(l13, const volatile void *: f1, default: f1); // NON-COMPLIANT + + _Generic(l14, int *: f1, default: f1); // COMPLIANT + _Generic(l14, const int *: f1, default: f1); // NON-COMPLIANT + _Generic(l14, volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l14, const volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l14, void *: f1, default: f1); // NON-COMPLIANT + _Generic(l14, const void *: f1, default: f1); // NON-COMPLIANT + _Generic(l14, const volatile void *: f1, default: f1); // NON-COMPLIANT + + _Generic(l15, int *: f1, default: f1); // NON-COMPLIANT + _Generic(l15, const int *: f1, default: f1); // COMPLIANT + _Generic(l15, void *: f1, default: f1); // NON-COMPLIANT + _Generic(l15, const void *: f1, default: f1); // NON-COMPLIANT + _Generic(l15, const volatile void *: f1, default: f1); // NON-COMPLIANT + // Obviously not volatile: + _Generic(l15, volatile int *: f1, default: f1); // COMPLIANT + // Debatable, but volatile const int* is assignable to const int* so its + // considered risky + _Generic(l15, const volatile int *: f1, default: f1); // NON-COMPLIANT + + /** + * Edge case 2: Types don't have to be identical to be compatible. + */ + int(*l16)[3]; + + // This is a risky conversion that should be reported: + _Generic(l16, int(*const)[3]: f1, default: f1); // NON-COMPLIANT + // However, in this one, there is a match on the second selector, because it + // it is an array type with a compatible element type, and sizes only have to + // match if both arrays have a constant size. Therefore, the default selector + // is not chosen and this is not a violation. + _Generic(l16, int(*const)[3]: f1, int(*)[]: f1, default: f1); // COMPLIANT + // In this case, the second selector is not a compatible type because the + // array has a constant size that doesn't match, and this should be reported. + _Generic(l16, + int(*const)[3]: f1, + int(*)[4]: f1, + default: f1); // NON-COMPLIANT + + /** + * Edge case 3: Conversion on _Generic, make sure we use the fully converted + * type when considering compliance. + */ + int *l17; + void *l18; + _Generic((void *)l17, void *: f1, default: f1); // COMPLIANT + _Generic((void *)l17, int *: f1, default: f1); // NON-COMPLIANT + _Generic((int *)l18, void *: f1, default: f1); // NON-COMPLIANT + _Generic((int *)l18, int *: f1, default: f1); // COMPLIANT + + /** + * Edge case 4: Typedefs must be resolved properly. + */ + typedef int int_t; + const typedef int c_int_t; + int_t *l19; + c_int_t *l20; + volatile c_int_t *l21; + + _Generic(l2, int *: f1, default: f1); // COMPLIANT + _Generic(l2, int_t *: f1, default: f1); // COMPLIANT + _Generic(l2, const int *: f1, default: f1); // NON-COMPLIANT + _Generic(l2, const int_t *: f1, default: f1); // NON-COMPLIANT + _Generic(l2, c_int_t *: f1, default: f1); // NON-COMPLIANT + + _Generic(l19, int *: f1, default: f1); // COMPLIANT + _Generic(l19, int_t *: f1, default: f1); // COMPLIANT + _Generic(l19, const int *: f1, default: f1); // NON-COMPLIANT + _Generic(l19, const int_t *: f1, default: f1); // NON-COMPLIANT + _Generic(l19, c_int_t *: f1, default: f1); // NON-COMPLIANT + + _Generic(l3, int *: f1, default: f1); // NON-COMPLIANT + _Generic(l3, int_t *: f1, default: f1); // NON-COMPLIANT + _Generic(l3, const int *: f1, default: f1); // COMPLIANT + _Generic(l3, const int_t *: f1, default: f1); // COMPLIANT + _Generic(l3, c_int_t *: f1, default: f1); // COMPLIANT + + _Generic(l20, int *: f1, default: f1); // NON-COMPLIANT + _Generic(l20, int_t *: f1, default: f1); // NON-COMPLIANT + _Generic(l20, const int *: f1, default: f1); // COMPLIANT + _Generic(l20, const int_t *: f1, default: f1); // COMPLIANT + _Generic(l20, c_int_t *: f1, default: f1); // COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.expected b/c/misra/test/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.expected new file mode 100644 index 0000000000..1cdcc82698 --- /dev/null +++ b/c/misra/test/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.expected @@ -0,0 +1,4 @@ +| test.c:11:3:11:8 | _Generic | Controlling expression in generic macro $@ has standard type (unnamed enum), which doesn't match its essential type (unnamed enum). | test.c:6:1:6:71 | #define M1(X) _Generic((X), int: 1, unsigned int: 1, short: 2, long: 3) | M1 | +| test.c:15:3:15:13 | _Generic | Controlling expression in generic macro $@ has standard type int, which doesn't match its essential type short. | test.c:6:1:6:71 | #define M1(X) _Generic((X), int: 1, unsigned int: 1, short: 2, long: 3) | M1 | +| test.c:18:3:18:23 | _Generic | Controlling expression in generic has standard type int, which doesn't match its essential type char. | test.c:18:3:18:23 | _Generic | | +| test.c:19:3:19:53 | _Generic | Controlling expression in generic has standard type int, which doesn't match its essential type short. | test.c:19:3:19:53 | _Generic | | diff --git a/c/misra/test/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.qlref b/c/misra/test/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.qlref new file mode 100644 index 0000000000..b91bbefec6 --- /dev/null +++ b/c/misra/test/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.qlref @@ -0,0 +1 @@ +rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-6/test.c b/c/misra/test/rules/RULE-23-6/test.c new file mode 100644 index 0000000000..7d59c1e199 --- /dev/null +++ b/c/misra/test/rules/RULE-23-6/test.c @@ -0,0 +1,33 @@ +short l1; +int l2; +long l3; +enum { E1 } l4; + +#define M1(X) _Generic((X), int: 1, unsigned int: 1, short: 2, long: 3) +void f1() { + M1(l1); // COMPLIANT + M1(l2); // COMPLIANT + M1(l3); // COMPLIANT + M1(l4); // NON-COMPLIANT + + M1(1); // COMPLIANT + M1(1u); // COMPLIANT + M1(l1 + l1); // NON-COMPLIANT + M1((int)(l1 + l1)); // COMPLIANT + M1('c'); // NON-COMPLIANT[false negative] + _Generic('c', int: 1); // NON-COMPLIANT + _Generic(_Generic(0, default: l1 + l1), default: 1); // NON-COMPLIANT + _Generic(((short)_Generic(0, default: (l1 + l1))), default: 1); // COMPLIANT +} + +void f2() { + // Edge case: lvalue conversion of a const struct yields an implicit + // conversion to a non-const struct which is ignored by EssentialTypes.qll, + // meaning the essential type does not match the static type. However, we + // shouldn't report an issue here as the static/essential types are not one + // of the essential type categories. + struct S1 { + int m1; + }; + _Generic((const struct S1){.m1 = 0}, default: 1); +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.expected b/c/misra/test/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.expected new file mode 100644 index 0000000000..57eecd6be8 --- /dev/null +++ b/c/misra/test/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.expected @@ -0,0 +1,12 @@ +| test.c:9:1:9:51 | #define M3(X) _Generic((X), int: f1(X), default: 0) | Generic macro M3 may have unexpected behavior from side effects in parameter X, as it is not expanded in generic selection 2. | +| test.c:10:1:10:61 | #define M4(X) (X) + _Generic((X), int: f1(X), default: f1(X)) | Generic macro M4 may have unexpected behavior from side effects in parameter X, as it is expanded outside the generic selection and inside the generic selection. | +| test.c:11:1:11:61 | #define M5(X) _Generic((X), int: f1(X), default: f1(X)) + (X) | Generic macro M5 may have unexpected behavior from side effects in parameter X, as it is expanded outside the generic selection and inside the generic selection. | +| test.c:12:1:12:63 | #define M6(X) _Generic((X), int: f1((X) + (X)), default: f1(X)) | Generic macro M6 may have unexpected behavior from side effects in parameter X, as it is expanded in generic selection 1 more than once. | +| test.c:21:1:21:36 | #define M9(X) _Generic((X), int: f1) | Generic macro M9 may have unexpected behavior from side effects in parameter X, as it is not expanded in generic selection 1. | +| test.c:23:1:23:40 | #define M10(X) _Generic((X), int: f1(1)) | Generic macro M10 may have unexpected behavior from side effects in parameter X, as it is not expanded in generic selection 1. | +| test.c:32:1:32:58 | #define M12(X) _Generic((X) + (X), int: f1(X), default: 1) | Generic macro M12 may have unexpected behavior from side effects in parameter X, as it is not expanded in generic selection 2. | +| test.c:33:1:33:68 | #define M13(X) _Generic((X) + (X), int: f1(X), default: f1(X)) + (X) | Generic macro M13 may have unexpected behavior from side effects in parameter X, as it is expanded outside the generic selection and inside the generic selection. | +| test.c:43:1:43:77 | #define M17(X,Y) _Generic((X) + (Y), int: f2((X), (Y)), default: f2((X), 1)) | Generic macro M17 may have unexpected behavior from side effects in parameter Y, as it is not expanded in generic selection 2. | +| test.c:67:1:67:78 | #define M26(X) _Generic((X), int: IGNORE_2ND(X, X), default: IGNORE_2ND(X, X)) | Generic macro M26 may have unexpected behavior from side effects in parameter X, as it is expanded in generic selection 1 more than once. | +| test.c:67:1:67:78 | #define M26(X) _Generic((X), int: IGNORE_2ND(X, X), default: IGNORE_2ND(X, X)) | Generic macro M26 may have unexpected behavior from side effects in parameter X, as it is expanded in generic selection 2 more than once. | +| test.c:68:1:68:75 | #define M27(X) _Generic((X), int: f1(IGNORE(X)), default: f1(IGNORE(X)))(X) | Generic macro M27 may have unexpected behavior from side effects in parameter X, as it is expanded outside the generic selection and inside the generic selection. | diff --git a/c/misra/test/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.qlref b/c/misra/test/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.qlref new file mode 100644 index 0000000000..3156bdce91 --- /dev/null +++ b/c/misra/test/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.qlref @@ -0,0 +1 @@ +rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-7/test.c b/c/misra/test/rules/RULE-23-7/test.c new file mode 100644 index 0000000000..41a5d6ab6c --- /dev/null +++ b/c/misra/test/rules/RULE-23-7/test.c @@ -0,0 +1,71 @@ +int f1(int p1); +int f2(int p1, int p2); + +// COMPLIANT -- standard correct cases: +#define M1(X) _Generic((X), int: f1, default: f1)(X) +#define M2(X) _Generic((X), int: f1(X), default: f1(X)) + +// NON-COMPLIANT -- standard incorrect cases: +#define M3(X) _Generic((X), int: f1(X), default: 0) +#define M4(X) (X) + _Generic((X), int: f1(X), default: f1(X)) +#define M5(X) _Generic((X), int: f1(X), default: f1(X)) + (X) +#define M6(X) _Generic((X), int: f1((X) + (X)), default: f1(X)) + +// Compliant by exception +// COMPLIANT +#define M7(X) _Generic((X), int: 1, default: 0) +// NON-COMPLIANT[FALSE NEGATIVE] -- Without an expansion, we can't tell if this +// macro has only constant expressions or not. +#define M8(X) _Generic((X), int: f1(1)) +// NON-COMPLIANT -- If the macro is expanded we can detect constant expressions +#define M9(X) _Generic((X), int: f1) +// NON-COMPLIANT -- If the macro is expanded we can detect constant expressions +#define M10(X) _Generic((X), int: f1(1)) +void f3() { + M9(1); + M10(1); +} + +// COMPLIANT -- multiple uses in the controlling expression is OK: +#define M11(X) _Generic((X) + (X), int: f1(X), default: f1(X)) +// NON-COMPLIANT -- the rule should still be enforced otherwise: +#define M12(X) _Generic((X) + (X), int: f1(X), default: 1) +#define M13(X) _Generic((X) + (X), int: f1(X), default: f1(X)) + (X) + +// COMPLIANT -- the argument is not used in the controlling expression: +#define M14(X) _Generic(1, int: f1((X) + (X)), default: f1(X)) +#define M15(X) _Generic(1, int: f1(X), default: f1(X)) + (X) + +// Test cases with more than one argument: +// COMPLIANT -- Y is not used in the controlling expression: +#define M16(X, Y) _Generic((X), int: f2((X), (Y)), default: f2((X), 1)) +// NON-COMPLIANT -- Y is used in the controlling expression +#define M17(X, Y) _Generic((X) + (Y), int: f2((X), (Y)), default: f2((X), 1)) +// COMPLIANT -- Y is used in the controlling expression correctly +#define M18(X, Y) _Generic((X) + (Y), int: f2((X), (Y)), default: f2((X), (Y))) + +// Test unevaluated contexts: +// COMPLIANT -- sizeof is not evaluated: +#define M19(X) _Generic((X), int[sizeof(X)]: f1, default: f1)(X) +#define M20(X) _Generic((X), int: f1(sizeof(X)), default: f1)(X) +#define M21(X) _Generic((X), int: f1(X), default: f1(X)) + sizeof(X) +// NON-COMPLIANT[FALSE NEGATIVE] -- sizeof plus evaluated context +#define M22(X) _Generic((X), int: f1(sizeof(X) + X), default: f1(X))(X) +// NON-COMPLIANT[FALSE NEGATIVE] -- array type sizes may be evaluated +#define M23(X) _Generic((X), int[X]: f1, default: f1)(X) +// COMPLIANT -- alignof, typeof are not evaluated: +#define M24(X) _Generic((X), int[X]: f1, default: f1)(X) + +// Nested macros: +#define ONCE(X) (X) +#define TWICE(X) (X) + (X) +#define IGNORE(X) (1) +#define IGNORE_2ND(X, Y) (X) +// COMPLIANT +#define M25(X) _Generic((X), int: ONCE(f1(X)), default: ONCE(f1(X)) +// COMPLIANT[FALSE POSITIVE] +#define M26(X) _Generic((X), int: IGNORE_2ND(X, X), default: IGNORE_2ND(X, X)) +#define M27(X) _Generic((X), int: f1(IGNORE(X)), default: f1(IGNORE(X)))(X) +// NON-COMPLIANT[FASE NEGATIVE] +#define M28(X) _Generic((X), int: f1(IGNORE(X)), default: f1(IGNORE(X))) +#define M29(X) _Generic((X), int: TWICE(f1(X)), default: TWICE(f1(X))) \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.expected b/c/misra/test/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.expected new file mode 100644 index 0000000000..5951834d00 --- /dev/null +++ b/c/misra/test/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.expected @@ -0,0 +1,4 @@ +| test.c:11:1:11:64 | #define M4(X) _Generic((X), int: 1, default: 0, unsigned int: 2) | Generic macro M4 has default as 2nd association, which is not first or last. | test.c:11:1:11:64 | #define M4(X) _Generic((X), int: 1, default: 0, unsigned int: 2) | (ignored) | +| test.c:17:1:17:60 | #define M5(__VA_ARGS__...) _Generic(0, __VA_ARGS__, default: 0, int: 1) | Generic macro M5 has a default association which is not first or last, for example $@. | test.c:28:5:28:23 | _Generic | 2nd | +| test.c:34:5:34:27 | M6(__VA_ARGS__...) | Generic macro $@, in this expansion, has default as 2nd association, which is not first or last. | test.c:19:1:19:48 | #define M6(__VA_ARGS__...) _Generic(0, __VA_ARGS__, int: 1) | M6 | +| test.c:44:5:44:52 | _Generic | Generic has default as 2nd association, which is not first or last. | test.c:44:5:44:52 | _Generic | | diff --git a/c/misra/test/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.qlref b/c/misra/test/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.qlref new file mode 100644 index 0000000000..06fe786e7d --- /dev/null +++ b/c/misra/test/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.qlref @@ -0,0 +1 @@ +rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-8/test.c b/c/misra/test/rules/RULE-23-8/test.c new file mode 100644 index 0000000000..fdd6e66044 --- /dev/null +++ b/c/misra/test/rules/RULE-23-8/test.c @@ -0,0 +1,49 @@ +/** + * Cases where the macro itself is always compliant or non compliant: + */ +// COMPLIANT +#define M1(X) _Generic((X), int: 1, unsigned int: 2) +// COMPLIANT +#define M2(X) _Generic((X), int: 1, unsigned int: 2, default: 0) +// COMPLIANT +#define M3(X) _Generic((X), default: 0, int: 1, unsigned int: 2) +// NON-COMPLIANT +#define M4(X) _Generic((X), int: 1, default: 0, unsigned int: 2) + +/** + * Macros that are compliant or not based on use: + */ +// NON-COMPLIANT: because every use is non compliant +#define M5(...) _Generic(0, __VA_ARGS__, default: 0, int: 1) +// COMPLIANT: because some uses are compliant +#define M6(...) _Generic(0, __VA_ARGS__, int: 1) + +void f1() { + M1(0); // COMPLIANT + M2(0); // COMPLIANT + M3(0); // COMPLIANT + M4(0); // COMPLIANT: the macro invocation is compliant, the macro definition + // is not. + + // COMPLIANT: all invocations of M5 are non compliant so the macro is reported + // instead. + M5(unsigned int : 1); + M5(unsigned int : 1, long : 2); + + // Some invocations of M6() will be compliant, so we'll report the issue at + // each invocation. + M6(default : 0); // COMPLIANT + M6(default : 0, long : 1); // COMPLIANT + M6(long : 1, default : 0); // NON-COMPLIANT +} + +/** + * For completeness, non macro cases, though these are not likely and violate + * RULE-23-1. + */ +void f2() { + _Generic(0, int: 1, unsigned int: 2); // COMPLIANT + _Generic(0, int: 1, unsigned int: 2, default: 0); // COMPLIANT + _Generic(0, default: 0, int: 1, unsigned int: 2); // COMPLIANT + _Generic(0, int: 1, default: 0, unsigned int: 2); // NON-COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.expected b/c/misra/test/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.expected index 08e419ef4f..f2b438aaf1 100644 --- a/c/misra/test/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.expected +++ b/c/misra/test/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.expected @@ -1,12 +1,14 @@ -| function1.c:6:6:6:7 | declaration of f3 | The return type of re-declaration of $@ is not compatible with declaration $@ | function1.c:6:6:6:7 | declaration of f3 | f3 | function1.c:8:4:8:5 | declaration of f3 | f3 | -| function1.c:8:4:8:5 | declaration of f3 | The return type of re-declaration of $@ is not compatible with declaration $@ | function1.c:8:4:8:5 | declaration of f3 | f3 | function1.c:6:6:6:7 | declaration of f3 | f3 | -| function1.c:8:4:8:5 | declaration of f3 | The return type of re-declaration of $@ is not compatible with declaration $@ | function1.c:8:4:8:5 | declaration of f3 | f3 | function2.c:4:6:4:7 | declaration of f3 | f3 | -| function1.c:9:6:9:7 | declaration of f4 | The return type of re-declaration of $@ is not compatible with declaration $@ | function1.c:9:6:9:7 | declaration of f4 | f4 | function2.c:5:5:5:6 | declaration of f4 | f4 | -| function1.c:13:5:13:6 | definition of f6 | The return type of re-declaration of $@ is not compatible with declaration $@ | function1.c:13:5:13:6 | definition of f6 | f6 | function2.c:9:6:9:7 | definition of f6 | f6 | -| function1.c:21:3:21:5 | definition of f21 | The parameter types of re-declaration of $@ is not compatible with declaration $@ | function1.c:21:3:21:5 | definition of f21 | f21 | function2.c:17:10:17:12 | declaration of f21 | f21 | -| function1.c:25:6:25:8 | definition of f22 | The parameter names of re-declaration of $@ is not compatible with declaration $@ | function1.c:25:6:25:8 | definition of f22 | f22 | function2.c:19:13:19:15 | declaration of f22 | f22 | -| function2.c:4:6:4:7 | declaration of f3 | The return type of re-declaration of $@ is not compatible with declaration $@ | function2.c:4:6:4:7 | declaration of f3 | f3 | function1.c:8:4:8:5 | declaration of f3 | f3 | -| function2.c:5:5:5:6 | declaration of f4 | The return type of re-declaration of $@ is not compatible with declaration $@ | function2.c:5:5:5:6 | declaration of f4 | f4 | function1.c:9:6:9:7 | declaration of f4 | f4 | -| function2.c:9:6:9:7 | definition of f6 | The return type of re-declaration of $@ is not compatible with declaration $@ | function2.c:9:6:9:7 | definition of f6 | f6 | function1.c:13:5:13:6 | definition of f6 | f6 | -| function2.c:17:10:17:12 | declaration of f21 | The parameter types of re-declaration of $@ is not compatible with declaration $@ | function2.c:17:10:17:12 | declaration of f21 | f21 | function1.c:21:3:21:5 | definition of f21 | f21 | -| function2.c:19:13:19:15 | declaration of f22 | The parameter names of re-declaration of $@ is not compatible with declaration $@ | function2.c:19:13:19:15 | declaration of f22 | f22 | function1.c:25:6:25:8 | definition of f22 | f22 | +| function1.c:6:6:6:7 | declaration of f3 | The return type of re-declaration of $@ does not use the same type names as declaration $@ | function1.c:6:6:6:7 | declaration of f3 | f3 | function1.c:8:4:8:5 | declaration of f3 | f3 | +| function1.c:8:4:8:5 | declaration of f3 | The return type of re-declaration of $@ does not use the same type names as declaration $@ | function1.c:8:4:8:5 | declaration of f3 | f3 | function1.c:6:6:6:7 | declaration of f3 | f3 | +| function1.c:8:4:8:5 | declaration of f3 | The return type of re-declaration of $@ does not use the same type names as declaration $@ | function1.c:8:4:8:5 | declaration of f3 | f3 | function2.c:4:6:4:7 | declaration of f3 | f3 | +| function1.c:9:6:9:7 | declaration of f4 | The return type of re-declaration of $@ does not use the same type names as declaration $@ | function1.c:9:6:9:7 | declaration of f4 | f4 | function2.c:5:5:5:6 | declaration of f4 | f4 | +| function1.c:13:5:13:6 | definition of f6 | The return type of re-declaration of $@ does not use the same type names as declaration $@ | function1.c:13:5:13:6 | definition of f6 | f6 | function2.c:9:6:9:7 | definition of f6 | f6 | +| function1.c:15:5:15:7 | declaration of f20 | The parameter types of re-declaration of $@ do not use the same type names as declaration $@ | function1.c:15:5:15:7 | declaration of f20 | f20 | function2.c:11:5:11:7 | declaration of f20 | f20 | +| function1.c:21:3:21:5 | definition of f21 | The parameter types of re-declaration of $@ do not use the same type names as declaration $@ | function1.c:21:3:21:5 | definition of f21 | f21 | function2.c:17:10:17:12 | declaration of f21 | f21 | +| function1.c:25:6:25:8 | definition of f22 | The parameter names of re-declaration of $@ do not use the same type names as declaration $@ | function1.c:25:6:25:8 | definition of f22 | f22 | function2.c:19:13:19:15 | declaration of f22 | f22 | +| function2.c:4:6:4:7 | declaration of f3 | The return type of re-declaration of $@ does not use the same type names as declaration $@ | function2.c:4:6:4:7 | declaration of f3 | f3 | function1.c:8:4:8:5 | declaration of f3 | f3 | +| function2.c:5:5:5:6 | declaration of f4 | The return type of re-declaration of $@ does not use the same type names as declaration $@ | function2.c:5:5:5:6 | declaration of f4 | f4 | function1.c:9:6:9:7 | declaration of f4 | f4 | +| function2.c:9:6:9:7 | definition of f6 | The return type of re-declaration of $@ does not use the same type names as declaration $@ | function2.c:9:6:9:7 | definition of f6 | f6 | function1.c:13:5:13:6 | definition of f6 | f6 | +| function2.c:11:5:11:7 | declaration of f20 | The parameter types of re-declaration of $@ do not use the same type names as declaration $@ | function2.c:11:5:11:7 | declaration of f20 | f20 | function1.c:15:5:15:7 | declaration of f20 | f20 | +| function2.c:17:10:17:12 | declaration of f21 | The parameter types of re-declaration of $@ do not use the same type names as declaration $@ | function2.c:17:10:17:12 | declaration of f21 | f21 | function1.c:21:3:21:5 | definition of f21 | f21 | +| function2.c:19:13:19:15 | declaration of f22 | The parameter names of re-declaration of $@ do not use the same type names as declaration $@ | function2.c:19:13:19:15 | declaration of f22 | f22 | function1.c:25:6:25:8 | definition of f22 | f22 | diff --git a/c/misra/test/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.expected b/c/misra/test/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.expected index c63681c7be..8b8e7f8a48 100644 --- a/c/misra/test/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.expected +++ b/c/misra/test/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.expected @@ -1,22 +1,22 @@ -| object1.c:5:6:5:7 | definition of a3 | The object $@ of type long is not compatible with re-declaration $@ of type LL | object1.c:5:6:5:7 | definition of a3 | a3 | object2.c:11:11:11:12 | declaration of a3 | a3 | -| object1.c:6:6:6:7 | definition of a4 | The object $@ of type long is not compatible with re-declaration $@ of type int | object1.c:6:6:6:7 | definition of a4 | a4 | object2.c:13:12:13:13 | declaration of a4 | a4 | -| object1.c:7:5:7:6 | definition of a5 | The object $@ of type int is not compatible with re-declaration $@ of type long | object1.c:7:5:7:6 | definition of a5 | a5 | object2.c:15:13:15:14 | declaration of a5 | a5 | -| object1.c:8:6:8:7 | definition of a6 | The object $@ of type long is not compatible with re-declaration $@ of type int | object1.c:8:6:8:7 | definition of a6 | a6 | object2.c:19:1:19:3 | declaration of a6 | a6 | -| object1.c:9:5:9:6 | definition of a7 | The object $@ of type int is not compatible with re-declaration $@ of type LL | object1.c:9:5:9:6 | definition of a7 | a7 | object2.c:21:11:21:12 | declaration of a7 | a7 | -| object1.c:15:5:15:7 | definition of a10 | The object $@ of type int[100] is not compatible with re-declaration $@ of type LI[100] | object1.c:15:5:15:7 | definition of a10 | a10 | object2.c:24:4:24:6 | definition of a10 | a10 | -| object1.c:16:5:16:7 | definition of a11 | The object $@ of type int[100] is not compatible with re-declaration $@ of type int[101] | object1.c:16:5:16:7 | definition of a11 | a11 | object2.c:25:12:25:14 | declaration of a11 | a11 | -| object1.c:19:12:19:14 | definition of a13 | The object $@ of type int *const is not compatible with re-declaration $@ of type int * | object1.c:19:12:19:14 | definition of a13 | a13 | object2.c:28:13:28:15 | declaration of a13 | a13 | -| object1.c:23:10:23:13 | definition of size | The object $@ of type size_t is not compatible with re-declaration $@ of type unsigned char | object1.c:23:10:23:13 | definition of size | size | object2.c:32:17:32:20 | definition of size | size | -| object1.c:24:3:24:4 | definition of s0 | The object $@ of type NamedStruct0 is not compatible with re-declaration $@ of type NamedStruct0 | object1.c:24:3:24:4 | definition of s0 | s0 | object2.c:33:3:33:4 | definition of s0 | s0 | -| object1.c:29:3:29:4 | definition of s1 | The object $@ of type NamedStruct1 is not compatible with re-declaration $@ of type NamedStruct1 | object1.c:29:3:29:4 | definition of s1 | s1 | object2.c:38:3:38:4 | definition of s1 | s1 | -| object2.c:11:11:11:12 | declaration of a3 | The object $@ of type LL is not compatible with re-declaration $@ of type long | object2.c:11:11:11:12 | declaration of a3 | a3 | object1.c:5:6:5:7 | definition of a3 | a3 | -| object2.c:13:12:13:13 | declaration of a4 | The object $@ of type int is not compatible with re-declaration $@ of type long | object2.c:13:12:13:13 | declaration of a4 | a4 | object1.c:6:6:6:7 | definition of a4 | a4 | -| object2.c:15:13:15:14 | declaration of a5 | The object $@ of type long is not compatible with re-declaration $@ of type int | object2.c:15:13:15:14 | declaration of a5 | a5 | object1.c:7:5:7:6 | definition of a5 | a5 | -| object2.c:19:1:19:3 | declaration of a6 | The object $@ of type int is not compatible with re-declaration $@ of type long | object2.c:19:1:19:3 | declaration of a6 | a6 | object1.c:8:6:8:7 | definition of a6 | a6 | -| object2.c:21:11:21:12 | declaration of a7 | The object $@ of type LL is not compatible with re-declaration $@ of type int | object2.c:21:11:21:12 | declaration of a7 | a7 | object1.c:9:5:9:6 | definition of a7 | a7 | -| object2.c:24:4:24:6 | definition of a10 | The object $@ of type LI[100] is not compatible with re-declaration $@ of type int[100] | object2.c:24:4:24:6 | definition of a10 | a10 | object1.c:15:5:15:7 | definition of a10 | a10 | -| object2.c:25:12:25:14 | declaration of a11 | The object $@ of type int[101] is not compatible with re-declaration $@ of type int[100] | object2.c:25:12:25:14 | declaration of a11 | a11 | object1.c:16:5:16:7 | definition of a11 | a11 | -| object2.c:28:13:28:15 | declaration of a13 | The object $@ of type int * is not compatible with re-declaration $@ of type int *const | object2.c:28:13:28:15 | declaration of a13 | a13 | object1.c:19:12:19:14 | definition of a13 | a13 | -| object2.c:32:17:32:20 | definition of size | The object $@ of type unsigned char is not compatible with re-declaration $@ of type size_t | object2.c:32:17:32:20 | definition of size | size | object1.c:23:10:23:13 | definition of size | size | -| object2.c:33:3:33:4 | definition of s0 | The object $@ of type NamedStruct0 is not compatible with re-declaration $@ of type NamedStruct0 | object2.c:33:3:33:4 | definition of s0 | s0 | object1.c:24:3:24:4 | definition of s0 | s0 | -| object2.c:38:3:38:4 | definition of s1 | The object $@ of type NamedStruct1 is not compatible with re-declaration $@ of type NamedStruct1 | object2.c:38:3:38:4 | definition of s1 | s1 | object1.c:29:3:29:4 | definition of s1 | s1 | +| object1.c:5:6:5:7 | definition of a3 | The object $@ of type long does not use the same type names as re-declaration $@ of type LL | object1.c:5:6:5:7 | definition of a3 | a3 | object2.c:11:11:11:12 | declaration of a3 | a3 | +| object1.c:6:6:6:7 | definition of a4 | The object $@ of type long does not use the same type names as re-declaration $@ of type int | object1.c:6:6:6:7 | definition of a4 | a4 | object2.c:13:12:13:13 | declaration of a4 | a4 | +| object1.c:7:5:7:6 | definition of a5 | The object $@ of type int does not use the same type names as re-declaration $@ of type long | object1.c:7:5:7:6 | definition of a5 | a5 | object2.c:15:13:15:14 | declaration of a5 | a5 | +| object1.c:8:6:8:7 | definition of a6 | The object $@ of type long does not use the same type names as re-declaration $@ of type int | object1.c:8:6:8:7 | definition of a6 | a6 | object2.c:19:1:19:3 | declaration of a6 | a6 | +| object1.c:9:5:9:6 | definition of a7 | The object $@ of type int does not use the same type names as re-declaration $@ of type LL | object1.c:9:5:9:6 | definition of a7 | a7 | object2.c:21:11:21:12 | declaration of a7 | a7 | +| object1.c:15:5:15:7 | definition of a10 | The object $@ of type int[100] does not use the same type names as re-declaration $@ of type LI[100] | object1.c:15:5:15:7 | definition of a10 | a10 | object2.c:24:4:24:6 | definition of a10 | a10 | +| object1.c:16:5:16:7 | definition of a11 | The object $@ of type int[100] does not use the same type names as re-declaration $@ of type int[101] | object1.c:16:5:16:7 | definition of a11 | a11 | object2.c:25:12:25:14 | declaration of a11 | a11 | +| object1.c:19:12:19:14 | definition of a13 | The object $@ of type int *const does not use the same type names as re-declaration $@ of type int * | object1.c:19:12:19:14 | definition of a13 | a13 | object2.c:28:13:28:15 | declaration of a13 | a13 | +| object1.c:23:10:23:13 | definition of size | The object $@ of type size_t does not use the same type names as re-declaration $@ of type unsigned char | object1.c:23:10:23:13 | definition of size | size | object2.c:32:17:32:20 | definition of size | size | +| object1.c:24:3:24:4 | definition of s0 | The object $@ of type NamedStruct0 does not use the same type names as re-declaration $@ of type NamedStruct0 | object1.c:24:3:24:4 | definition of s0 | s0 | object2.c:33:3:33:4 | definition of s0 | s0 | +| object1.c:29:3:29:4 | definition of s1 | The object $@ of type NamedStruct1 does not use the same type names as re-declaration $@ of type NamedStruct1 | object1.c:29:3:29:4 | definition of s1 | s1 | object2.c:38:3:38:4 | definition of s1 | s1 | +| object2.c:11:11:11:12 | declaration of a3 | The object $@ of type LL does not use the same type names as re-declaration $@ of type long | object2.c:11:11:11:12 | declaration of a3 | a3 | object1.c:5:6:5:7 | definition of a3 | a3 | +| object2.c:13:12:13:13 | declaration of a4 | The object $@ of type int does not use the same type names as re-declaration $@ of type long | object2.c:13:12:13:13 | declaration of a4 | a4 | object1.c:6:6:6:7 | definition of a4 | a4 | +| object2.c:15:13:15:14 | declaration of a5 | The object $@ of type long does not use the same type names as re-declaration $@ of type int | object2.c:15:13:15:14 | declaration of a5 | a5 | object1.c:7:5:7:6 | definition of a5 | a5 | +| object2.c:19:1:19:3 | declaration of a6 | The object $@ of type int does not use the same type names as re-declaration $@ of type long | object2.c:19:1:19:3 | declaration of a6 | a6 | object1.c:8:6:8:7 | definition of a6 | a6 | +| object2.c:21:11:21:12 | declaration of a7 | The object $@ of type LL does not use the same type names as re-declaration $@ of type int | object2.c:21:11:21:12 | declaration of a7 | a7 | object1.c:9:5:9:6 | definition of a7 | a7 | +| object2.c:24:4:24:6 | definition of a10 | The object $@ of type LI[100] does not use the same type names as re-declaration $@ of type int[100] | object2.c:24:4:24:6 | definition of a10 | a10 | object1.c:15:5:15:7 | definition of a10 | a10 | +| object2.c:25:12:25:14 | declaration of a11 | The object $@ of type int[101] does not use the same type names as re-declaration $@ of type int[100] | object2.c:25:12:25:14 | declaration of a11 | a11 | object1.c:16:5:16:7 | definition of a11 | a11 | +| object2.c:28:13:28:15 | declaration of a13 | The object $@ of type int * does not use the same type names as re-declaration $@ of type int *const | object2.c:28:13:28:15 | declaration of a13 | a13 | object1.c:19:12:19:14 | definition of a13 | a13 | +| object2.c:32:17:32:20 | definition of size | The object $@ of type unsigned char does not use the same type names as re-declaration $@ of type size_t | object2.c:32:17:32:20 | definition of size | size | object1.c:23:10:23:13 | definition of size | size | +| object2.c:33:3:33:4 | definition of s0 | The object $@ of type NamedStruct0 does not use the same type names as re-declaration $@ of type NamedStruct0 | object2.c:33:3:33:4 | definition of s0 | s0 | object1.c:24:3:24:4 | definition of s0 | s0 | +| object2.c:38:3:38:4 | definition of s1 | The object $@ of type NamedStruct1 does not use the same type names as re-declaration $@ of type NamedStruct1 | object2.c:38:3:38:4 | definition of s1 | s1 | object1.c:29:3:29:4 | definition of s1 | s1 | diff --git a/c/misra/test/rules/RULE-8-3/function1.c b/c/misra/test/rules/RULE-8-3/function1.c index 2072748047..7fcf775167 100644 --- a/c/misra/test/rules/RULE-8-3/function1.c +++ b/c/misra/test/rules/RULE-8-3/function1.c @@ -12,7 +12,7 @@ long f5(int f5a) { return 0; } // COMPLIANT int f6(int f6a) { return 0; } // NON_COMPLIANT -int f20(int f20a); // COMPLIANT - overloaded function +int f20(int f20a); // NON_COMPLIANT typedef int wi; typedef int hi; diff --git a/c/misra/test/rules/RULE-8-3/function2.c b/c/misra/test/rules/RULE-8-3/function2.c index 979e002466..b33dc73c1c 100644 --- a/c/misra/test/rules/RULE-8-3/function2.c +++ b/c/misra/test/rules/RULE-8-3/function2.c @@ -8,7 +8,7 @@ long f5(int f5a) { return 0; } // COMPLIANT long f6(int f6a) { return 0; } // NON_COMPLIANT -int f20(int f20a, int f20b); // COMPLIANT -- overloaded function +int f20(int f20a, int f20b); // NON_COMPLIANT typedef int wi; typedef int hi; diff --git a/change_notes/2025-02-25-move-type-related-libraries.md b/change_notes/2025-02-25-move-type-related-libraries.md new file mode 100644 index 0000000000..9f4fbd0bf2 --- /dev/null +++ b/change_notes/2025-02-25-move-type-related-libraries.md @@ -0,0 +1,2 @@ + - All rules using `Type.qll`, `TypeUses.qll`, `Pointers.qll`, `TrivialType.qll`, `VariablyModifiedTypes.qll`: + - Files moved into `cpp/common/types` directory. No external changes in behavior expected. \ No newline at end of file diff --git a/change_notes/2025-02-25-update-macro-deduplication-library.md b/change_notes/2025-02-25-update-macro-deduplication-library.md new file mode 100644 index 0000000000..90b3ef51af --- /dev/null +++ b/change_notes/2025-02-25-update-macro-deduplication-library.md @@ -0,0 +1,4 @@ +- `RULE-2-8` - `UnusedObjectDefinition.ql`, `UnusedObjectDefinitionStrict.ql`: + - Refactor to allow additional parameters in non-macro results for library `DeduplicateMacroResults.qll`. + - Refactor to replace `Location` with `Locatable` in API of library `DeduplicationMacroResults.qll`. + - No observable difference in behavior expected. diff --git a/change_notes/2025-03-04-essential-types-with-explicit-conversions.md b/change_notes/2025-03-04-essential-types-with-explicit-conversions.md new file mode 100644 index 0000000000..aa32044087 --- /dev/null +++ b/change_notes/2025-03-04-essential-types-with-explicit-conversions.md @@ -0,0 +1,2 @@ + - `EssentialType` - for all queries related to essential types: + - Updated the way essential types of expressions with "conversions" (including explicit casts, parenthesis, and implicit conversions such as array-to-pointer conversions) are handled, to get proper essential types when parenthesis, casts, and generics interact. \ No newline at end of file diff --git a/change_notes/2025-03-04-more-accurate-type-comparisons.md b/change_notes/2025-03-04-more-accurate-type-comparisons.md new file mode 100644 index 0000000000..942d76f7af --- /dev/null +++ b/change_notes/2025-03-04-more-accurate-type-comparisons.md @@ -0,0 +1,6 @@ + - `RULE-8-3` - `DeclarationsOfAFunctionSameNameAndType.ql`, `DeclarationsOfAnObjectSameNameAndType.ql`: + - New shared module used to fix false positives for compound types referring to the same basic integer types under a different name, e.g., query will not report for `signed[4]` used in place of `int[4]` as per MISRA spec. + - Now query will report incompatibilities for two functions of the same name with a different number of parameters. + - Query result string updated to not use the word "Compatible," which is confusing, as it may falsely appear that the query is testing for compatibility as defined by C17. + - `RULE-8-4`, `DCL-40C` - `CompatibleDeclarationFunctionDefined.ql`, `CompatibleDeclarationObjectDefined.ql`, `IncomptatibleFunctionDeclarations.ql`: + - New shared module used to fix false positives by updating "compatible" type checks to more closely match the C17 standard. For instance, `int[3]` and `int[]` are compatible declarations (while `int[3]` and `int[4]` are not), and typedefs are now resolved as well. Some false positives may still occur regarding structs from different compilation units. \ No newline at end of file diff --git a/cpp/autosar/src/rules/A0-4-1/FloatingPointImplementationShallComplyWithIeeeStandard.ql b/cpp/autosar/src/rules/A0-4-1/FloatingPointImplementationShallComplyWithIeeeStandard.ql index 9123e7de2f..0a59b423d0 100644 --- a/cpp/autosar/src/rules/A0-4-1/FloatingPointImplementationShallComplyWithIeeeStandard.ql +++ b/cpp/autosar/src/rules/A0-4-1/FloatingPointImplementationShallComplyWithIeeeStandard.ql @@ -18,7 +18,7 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.TypeUses +import codingstandards.cpp.types.Uses class NumericLimits extends Class { NumericLimits() { this.hasQualifiedName("std", ["numeric_limits", "__libcpp_numeric_limits"]) } diff --git a/cpp/autosar/src/rules/A12-8-4/MoveConstructorUsesCopySemantics.ql b/cpp/autosar/src/rules/A12-8-4/MoveConstructorUsesCopySemantics.ql index 4996afd34e..a71d49d844 100644 --- a/cpp/autosar/src/rules/A12-8-4/MoveConstructorUsesCopySemantics.ql +++ b/cpp/autosar/src/rules/A12-8-4/MoveConstructorUsesCopySemantics.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.TrivialType +import codingstandards.cpp.types.TrivialType /** * A literal with no values. diff --git a/cpp/autosar/src/rules/A14-5-2/NonTemplateMemberDefinedInTemplate.ql b/cpp/autosar/src/rules/A14-5-2/NonTemplateMemberDefinedInTemplate.ql index 7f9ced9909..61b00ba852 100644 --- a/cpp/autosar/src/rules/A14-5-2/NonTemplateMemberDefinedInTemplate.ql +++ b/cpp/autosar/src/rules/A14-5-2/NonTemplateMemberDefinedInTemplate.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.TypeUses +import codingstandards.cpp.types.Uses import codingstandards.cpp.Operator predicate templateDefinitionMentionsTypeParameter(Declaration d, TemplateParameter tp) { diff --git a/cpp/autosar/src/rules/A7-1-2/VariableMissingConstexpr.ql b/cpp/autosar/src/rules/A7-1-2/VariableMissingConstexpr.ql index a07dbd43f7..af3a00fadb 100644 --- a/cpp/autosar/src/rules/A7-1-2/VariableMissingConstexpr.ql +++ b/cpp/autosar/src/rules/A7-1-2/VariableMissingConstexpr.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.TrivialType +import codingstandards.cpp.types.TrivialType import codingstandards.cpp.SideEffect import semmle.code.cpp.controlflow.SSA import codingstandards.cpp.Expr diff --git a/cpp/autosar/src/rules/A8-4-7/TriviallyCopyableSmallType.qll b/cpp/autosar/src/rules/A8-4-7/TriviallyCopyableSmallType.qll index be7cd76bd2..09c6cdae69 100644 --- a/cpp/autosar/src/rules/A8-4-7/TriviallyCopyableSmallType.qll +++ b/cpp/autosar/src/rules/A8-4-7/TriviallyCopyableSmallType.qll @@ -1,6 +1,6 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.TrivialType +import codingstandards.cpp.types.TrivialType /** * Get the largest word size, in bytes. Some projects may have multiple different diff --git a/cpp/autosar/src/rules/M0-1-4/SingleUsePODVariable.qll b/cpp/autosar/src/rules/M0-1-4/SingleUsePODVariable.qll index c0a32baba9..8985f7254e 100644 --- a/cpp/autosar/src/rules/M0-1-4/SingleUsePODVariable.qll +++ b/cpp/autosar/src/rules/M0-1-4/SingleUsePODVariable.qll @@ -1,7 +1,7 @@ /** A module providing predicates that support identifying single use non volatile POD variables. */ import cpp -import codingstandards.cpp.TrivialType +import codingstandards.cpp.types.TrivialType import codingstandards.cpp.deadcode.UnusedVariables /** diff --git a/cpp/cert/src/rules/MEM53-CPP/ManuallyManagedLifetime.qll b/cpp/cert/src/rules/MEM53-CPP/ManuallyManagedLifetime.qll index 4392b598f7..0eaf9f8dfa 100644 --- a/cpp/cert/src/rules/MEM53-CPP/ManuallyManagedLifetime.qll +++ b/cpp/cert/src/rules/MEM53-CPP/ManuallyManagedLifetime.qll @@ -1,6 +1,6 @@ import codingstandards.cpp.cert import codingstandards.cpp.Conversion -import codingstandards.cpp.TrivialType +import codingstandards.cpp.types.TrivialType import ManuallyManagedLifetime import semmle.code.cpp.controlflow.Dominance import semmle.code.cpp.dataflow.TaintTracking diff --git a/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject.ql b/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject.ql index 6e3121e46d..5398aa04e1 100644 --- a/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject.ql +++ b/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject.ql @@ -12,7 +12,7 @@ import cpp import codingstandards.cpp.cert -import codingstandards.cpp.TrivialType +import codingstandards.cpp.types.TrivialType import ManuallyManagedLifetime import semmle.code.cpp.dataflow.TaintTracking import AllocToStaticCastFlow::PathGraph diff --git a/cpp/common/src/codingstandards/cpp/Compatible.qll b/cpp/common/src/codingstandards/cpp/Compatible.qll deleted file mode 100644 index 0f6e2108ff..0000000000 --- a/cpp/common/src/codingstandards/cpp/Compatible.qll +++ /dev/null @@ -1,30 +0,0 @@ -import cpp - -pragma[noinline] -pragma[nomagic] -predicate typesCompatible(Type t1, Type t2) { - t1 = t2 - or - //signed int is same as int ect - t1.(IntegralType).getCanonicalArithmeticType() = t2.(IntegralType).getCanonicalArithmeticType() -} - -predicate parameterTypesIncompatible(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { - f1.getDeclaration() = f2.getDeclaration() and - exists(ParameterDeclarationEntry p1, ParameterDeclarationEntry p2, int i | - p1 = f1.getParameterDeclarationEntry(i) and - p2 = f2.getParameterDeclarationEntry(i) - | - not typesCompatible(p1.getType(), p2.getType()) - ) -} - -predicate parameterNamesIncompatible(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { - f1.getDeclaration() = f2.getDeclaration() and - exists(ParameterDeclarationEntry p1, ParameterDeclarationEntry p2, int i | - p1 = f1.getParameterDeclarationEntry(i) and - p2 = f2.getParameterDeclarationEntry(i) - | - not p1.getName() = p2.getName() - ) -} diff --git a/cpp/common/src/codingstandards/cpp/MatchingParenthesis.qll b/cpp/common/src/codingstandards/cpp/MatchingParenthesis.qll new file mode 100644 index 0000000000..8a28bd0517 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/MatchingParenthesis.qll @@ -0,0 +1,264 @@ +/** + * A library for parsing a string of parentheses and non-parentheses characters. + * + * Simply implement the signature class `InputString` for the set of strings that you wish to parse, + * and then use the `MatchingParenthesis` module which exposes the following classes/predicates: + * - `ParsedRoot`: The root of the parse tree. + * - `ParsedGroup`: Parenthesis groups. The root is also a group, even if not parenthesized. + * - `ParsedText`: All text that is not '(' or ')'. + * - `Tokenized`: A linked list of the tokens in the input string. + * - `textFrom(start, end)`: A function to get the text between two tokens. + * + * The parenthesis AST has functions `getChild(int i)` and `getParent()` to navigate the tree, as + * well as `getRoot()` and `getText()` for `ParsedText` nodes. They also have methods + * `getStartToken()`, `getEndToken()` which are especially useful with the method `textFrom(...)`. + * + * This module can allow for slightly more intelligent interpretation of macro strings, but it has + * limitations. + * - It _only_ handles the parenthesis. + * - It assumes parentheses are matched. + * - It does not handle the case where a parenthesis is inside a string literal. + * - It does not handle the case where a parenthesis is inside a comment. + * + * This module has been moderately optimized, but still it is best to be selective with the set of + * strings you attempt to parse with it. + */ + +import codeql.util.Option + +signature class InputString extends string; + +module MatchingParenthesis { + newtype TTokenType = + TOpenParen() or + TCloseParen() or + TNotParen() + + bindingset[char] + private TTokenType tokenTypeOfChar(string char) { + result = TOpenParen() and char = "(" + or + result = TCloseParen() and char = ")" + } + + private int inputId(Input i) { rank[result](Input inp) = i } + + private newtype TTokenized = + TTokenizerStart(int iid) { iid = inputId(_) } or + TToken(int iid, TTokenized prev, TTokenType token, int occurrence, int endPos) { + exists(string inputStr, int prevEndPos, int prevOccurrence, string char | + iid = inputId(inputStr) and + ( + prev = TTokenizerStart(iid) and prevOccurrence = -1 and prevEndPos = 0 + or + prev = TToken(iid, _, _, prevOccurrence, prevEndPos) + ) and + inputStr.charAt(prevEndPos) = char and + if char = ["(", ")"] + then ( + endPos = prevEndPos + 1 and + token = tokenTypeOfChar(char) and + occurrence = prevOccurrence + 1 + ) else ( + token = TNotParen() and + exists(inputStr.regexpFind("\\(|\\)", prevOccurrence + 1, endPos)) and + occurrence = prevOccurrence + ) + ) + } + + class Tokenized extends TTokenized { + string toString() { + getTokenType() = TOpenParen() and result = "(" + or + getTokenType() = TCloseParen() and result = ")" + or + getTokenType() = TNotParen() and result = "non-parenthesis" + } + + int getInputId() { this = TToken(result, _, _, _, _) } + + TTokenType getTokenType() { this = TToken(_, _, result, _, _) } + + Tokenized getPrevious() { this = TToken(_, result, _, _, _) } + + string getInputString() { + this = TToken(inputId(result), _, _, _, _) or this = TTokenizerStart(inputId(result)) + } + + int getStartPos() { + if exists(getPrevious()) then result = getPrevious().getEndPos() else result = 0 + } + + int getEndPos() { + this = TToken(_, _, _, _, result) + or + this = TTokenizerStart(_) and result = 0 + } + + string getText() { result = textFrom(this, this) } + + Tokenized getNext() { result.getPrevious() = this } + + Tokenized getLast() { + if exists(getNext()) then result = getNext().getLast() else result = this + } + } + + /** + * The root of the parse tree. + */ + class ParsedRoot extends ParsedGroup { + ParsedRoot() { not exists(getParent()) } + + override ParsedRoot getRoot() { result = this } + + override string getDebugText() { result = this.(Tokenized).getInputString() } + } + + /** + * A group of tokens that may be parenthesized. + * + * The `ParseRoot` is the only group that isn't parenthesized. + */ + class ParsedGroup extends Parsed { + ParsedGroup() { isGroup() } + + Parsed getChild(int i) { + result.getParent() = this and + result.getChildIdx() = i + } + } + + /** + * Get the text from the `start` token to the `end` token (inclusive on both ends). + */ + pragma[inline] + string textFrom(Tokenized start, Tokenized end) { + result = start.getInputString().substring(start.getStartPos(), end.getEndPos()) + } + + /** + * All text that is not '(' or ')'. + */ + class ParsedText extends Parsed { + ParsedText() { not isGroup() } + + string getText() { result = textFrom(getStartToken(), getEndToken()) } + } + + /** + * The AST for the input string parsed with matching parenthesis. + */ + class Parsed extends TTokenized { + Option::Option parent; + int childIdx; + boolean isGroup; + + Parsed() { + this.(Tokenized).getTokenType() = TNotParen() and + parseStepAppend(this, parent.asSome(), childIdx) and + isGroup = false + or + this.(Tokenized).getTokenType() = TOpenParen() and + parseStepOpen(this, parent.asSome(), childIdx) and + isGroup = true + or + this = TTokenizerStart(_) and + parent.isNone() and + childIdx = 0 and + isGroup = true + } + + ParsedRoot getRoot() { result = getParent().getRoot() } + + string getInputString() { result = this.(Tokenized).getInputString() } + + /** + * The token that starts this group. + * + * For `ParsedText`, this is the same as the end token. + */ + Tokenized getStartToken() { result = this } + + /** + * The token that endns this group. + * + * For `ParsedText`, this is the same as the start token. If parentheses are not matched, this + * may not have a result. + */ + Tokenized getEndToken() { + this.(Tokenized).getTokenType() = TNotParen() and + result = this + or + this.(Tokenized).getTokenType() = TOpenParen() and + parseStepClose(result, this) + or + this = TTokenizerStart(_) and + result = getStartToken().(Tokenized).getLast() + } + + /** + * The index of this child in the parent group. + */ + int getChildIdx() { result = childIdx } + + ParsedGroup getParent() { result = parent.asSome() } + + predicate isGroup() { isGroup = true } + + string getDebugText() { result = textFrom(getStartToken(), getEndToken()) } + + string toString() { result = this.(Tokenized).toString() } + } + + /** + * Parse open parenthesis and add it to the open group or parse root. Parsing algorithm may not + * behave reliably for mismatched parenthesis. + */ + private predicate parseStepOpen(Tokenized consumeToken, ParsedGroup parent, int childIdx) { + consumeToken.getTokenType() = TOpenParen() and + ( + consumeToken.getPrevious() = parent.getStartToken() and + childIdx = 0 + or + exists(Parsed prevSibling | + prevSibling.getEndToken() = consumeToken.getPrevious() and + childIdx = prevSibling.getChildIdx() + 1 and + parent = prevSibling.getParent() + ) + ) + } + + /** + * Parse raw text that isn't '(' or ')' and add it to the open group or parse root. + */ + private predicate parseStepAppend(Tokenized consumeToken, ParsedGroup parent, int childIdx) { + consumeToken.getTokenType() = TNotParen() and + ( + consumeToken.getPrevious() = parent.getStartToken() and childIdx = 0 + or + exists(Parsed prevSibling | + prevSibling.getEndToken() = consumeToken.getPrevious() and + childIdx = prevSibling.getChildIdx() + 1 and + parent = prevSibling.getParent() + ) + ) + } + + /** + * Parse a close parenthesis to close the currently open group. Parsing algorithm may not behave + * properly for mismatched parenthesis. + */ + private predicate parseStepClose(Tokenized consumeToken, ParsedGroup closed) { + consumeToken.getTokenType() = TCloseParen() and + ( + closed.getStartToken() = consumeToken.getPrevious() + or + exists(Parsed finalChild | + consumeToken.getPrevious() = finalChild.getEndToken() and + finalChild.getParent() = closed + ) + ) + } +} diff --git a/cpp/common/src/codingstandards/cpp/Type.qll b/cpp/common/src/codingstandards/cpp/Type.qll index 42d77b8055..32c139fd89 100644 --- a/cpp/common/src/codingstandards/cpp/Type.qll +++ b/cpp/common/src/codingstandards/cpp/Type.qll @@ -1,96 +1,2 @@ -/** - * A module for representing different `Type`s. - */ - -import cpp - -/** - * A fundamental type, as defined by `[basic.fundamental]`. - */ -class FundamentalType extends BuiltInType { - FundamentalType() { - // A fundamental type is any `BuiltInType` except types indicating errors during extraction, or - // "unknown" types inserted into uninstantiated templates - not this instanceof ErroneousType and - not this instanceof UnknownType - } -} - -/** - * A type that is incomplete. - */ -class IncompleteType extends Class { - IncompleteType() { not hasDefinition() } -} - -/** - * A type that implements the BitmaskType trait. - * https://en.cppreference.com/w/cpp/named_req/BitmaskType - */ -abstract class BitmaskType extends Type { } - -/** - * Holds if `enum` implements required overload `overload` to implement - * the BitmaskType trait. - */ -private predicate isRequiredEnumOverload(Enum enum, Function overload) { - overload.getName().regexpMatch("operator([&|^~]|&=|\\|=)") and - forex(Parameter p | p = overload.getAParameter() | - ( - p.getType() = enum - or - p.getType().(ReferenceType).getBaseType() = enum - ) - ) -} - -private class EnumBitmaskType extends BitmaskType, Enum { - EnumBitmaskType() { - // Implements all the required overload - count(Function overload | isRequiredEnumOverload(this, overload)) = 6 - } -} - -/** - * A type without `const` and `volatile` specifiers. - */ -Type stripSpecifiers(Type type) { - if type instanceof SpecifiedType - then result = stripSpecifiers(type.(SpecifiedType).getBaseType()) - else result = type -} - -signature class PossiblySpecifiedBaseType extends Type; - -/** - * This module defines a class `Type` which holds for types `T` and `const/volatile T` etc. - * - * Similar to `getUnspecifiedType()`, but does not resolve typedefs. Useful for matching - * potentially qualified versions of standard typedef types, such as `const mtx_t`. - * - * Example usage: `someType.(PossiblySpecified::Type).strip()` - */ -module PossiblySpecified { - import cpp as cpp - - final class CppType = cpp::Type; - - class Type extends CppType { - BaseType baseType; - - Type() { baseType = stripSpecifiers(this) } - - BaseType strip() { result = baseType } - } -} - -/** - * Get the precision of an integral type, where precision is defined as the number of bits - * that can be used to represent the numeric value. - * https://wiki.sei.cmu.edu/confluence/display/c/INT35-C.+Use+correct+integer+precisions - */ -int getPrecision(IntegralType type) { - type.isExplicitlyUnsigned() and result = type.getSize() * 8 - or - type.isExplicitlySigned() and result = type.getSize() * 8 - 1 -} +import codingstandards.cpp.types.Type +import codingstandards.cpp.types.Uses \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll b/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll index b3c3d44ff4..b41de3ef9a 100644 --- a/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll +++ b/cpp/common/src/codingstandards/cpp/alertreporting/DeduplicateMacroResults.qll @@ -38,7 +38,7 @@ signature module MacroReportConfigSig { /** * Create a message to describe a `ResultElement` which is not generated by a macro expansion. */ - string getMessageNotInMacro(ResultElement element); + string getMessageNotInMacro(ResultElement element, Locatable optExtraLoc1, string optExtraStr1); } /** @@ -120,7 +120,7 @@ signature module MacroReportConfigSig { * * from Report::ReportResult report * where not excluded(report.getPrimaryElement(), ...) - * select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocation(), + * select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocatable(), * report.getOptionalPlaceholderMessage() * ``` * @@ -295,7 +295,7 @@ module DeduplicateMacroResults< * To show a report, use the following methods: * - `report.getPrimaryElement()` * - `report.getMessage()` - * - `report.getOptionalPlaceholderLocation()` + * - `report.getOptionalPlaceholderLocatable()` * - `report.getOptionalPlaceholderMessage()` * * The values returned by these methods are configured by the `MacroReportConfigSig` @@ -337,7 +337,7 @@ module DeduplicateMacroResults< or exists(ResultElement def | this = TReportNotInMacro(def) and - result = ReportConfig::getMessageNotInMacro(def) + result = ReportConfig::getMessageNotInMacro(def, _, _) ) } @@ -351,25 +351,25 @@ module DeduplicateMacroResults< this = TReportNotInMacro(result) } - Location getOptionalPlaceholderLocation() { + Locatable getOptionalPlaceholderLocatable() { exists(PrimaryMacroDifferentResultElementInAllInvocations def | this = TReportMacroResultWithVariedName(def) and - result = def.getExampleResultElement().getLocation() + result = def.getExampleResultElement() ) or exists(PrimaryMacroSameResultElementInAllInvocations def | this = TReportMacroResultWithSameName(def) and - result = def.getLocation() + result = def ) or exists(IsolatedMacroExpansionWithResultElement def | this = TReportIsolatedMacroResult(def) and - result = def.getMacro().getLocation() + result = def.getMacro() ) or exists(ResultElement def | this = TReportNotInMacro(def) and - result = def.getLocation() + exists(ReportConfig::getMessageNotInMacro(def, result, _)) ) } @@ -379,14 +379,16 @@ module DeduplicateMacroResults< result = Config::describe(def.getExampleResultElement()) ) or - ( - this = TReportMacroResultWithSameName(_) or - this = TReportNotInMacro(_) - ) and + this = TReportMacroResultWithSameName(_) and result = "(ignored)" or this = TReportIsolatedMacroResult(_) and result = getMacro().getName() + or + exists(ResultElement def | + this = TReportNotInMacro(def) and + exists(ReportConfig::getMessageNotInMacro(def, _, result)) + ) } Macro getMacro() { diff --git a/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll b/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll index 60e732873a..94ae16ec4f 100644 --- a/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll +++ b/cpp/common/src/codingstandards/cpp/deadcode/UnusedObjects.qll @@ -57,8 +57,10 @@ module ReportDeadObjectConfig implements MacroReportConfigSig; + +/** + * Signature module for handling various kinds of potentially recursive type equivalence using the + * module `TypeEquivalence`. + * + * The various kinds of types to be compared all have an overridable predicate with default + * behavior here, and a boolean flag that indicates whether the base types are equal. This pattern + * is used because we can't make a default implementation of a predicate such as + * `equalPointerTypes` that recurses into the `TypeEquivalence` module. Instead, the + * `TypeEquivalence` module drives all of the recursion, and these predicates take the result of + * that recursion and use it to determine whether the types are equivalent. + */ +signature module TypeEquivalenceSig { + /** + * Whether two leaf types are equivalent, such as `int`s and structs. By default, we assume only + * that types are equal to themselves and that equivalent arithmetic types are equal. + */ + bindingset[t1, t2] + default predicate equalLeafTypes(Type t1, Type t2) { + t1 = t2 + or + t1.(IntegralType).getCanonicalArithmeticType() = t2.(IntegralType).getCanonicalArithmeticType() + } + + /** + * A predicate to arbitrarily override the default behavior of the `TypeEquivalence` module, + * including preventing recursion. If this predicate holds for a pair of types, then + * `TypeEquivalence::equalTypes()` holds only if `areEqual` is true. + */ + bindingset[t1, t2] + default predicate overrideTypeComparison(Type t1, Type t2, Boolean areEqual) { none() } + + /** + * Whether two specified types are equivalent. By default, we assume that the specifier sets are + * exactly the same, and the inner types also match. + */ + bindingset[t1, t2] + default predicate equalSpecifiedTypes( + SpecifiedType t1, SpecifiedType t2, Boolean unspecifiedTypesEqual + ) { + specifiersMatchExactly(t1, t2) and + unspecifiedTypesEqual = true + } + + /** + * Whether two specified types are equivalent. By default, we only require that the base (pointed + * to) types match. + */ + bindingset[t1, t2] + default predicate equalPointerTypes(PointerType t1, PointerType t2, Boolean baseTypesEqual) { + baseTypesEqual = true + } + + /** + * Whether two array types are equivalent. By default, we only require that the element types and + * array sizes match. + */ + bindingset[t1, t2] + default predicate equalArrayTypes(ArrayType t1, ArrayType t2, Boolean baseTypesEqual) { + t1.getSize() = t2.getSize() and + baseTypesEqual = true + } + + /** + * Whether two reference types are equivalent. By default, we only require that the base types match. + */ + bindingset[t1, t2] + default predicate equalReferenceTypes(ReferenceType t1, ReferenceType t2, Boolean baseTypesEqual) { + baseTypesEqual = true + } + + /** + * Whether typedefs should be resolved before comparison. By default, we assume `TypeEquivalence` + * should resolve typedefs before comparison. + */ + default predicate resolveTypedefs() { any() } + + /** + * Whether two typedef types are equivalent. + * + * This predicate is only used if `resolveTypedefs()` is false. If so, then we assume two + * typedefs are the same if they have the same name and their base types are equal. + */ + bindingset[t1, t2] + default predicate equalTypedefTypes(TypedefType t1, TypedefType t2, Boolean baseTypesEqual) { + t1.getName() = t2.getName() and + baseTypesEqual = true + } + + /** + * Whether two routine types are equivalent. By default, we only require that the return types and + * parameter types match. + */ + bindingset[t1, t2] + default predicate equalRoutineTypes( + RoutineType t1, RoutineType t2, Boolean returnTypeEqual, Boolean parameterTypesEqual + ) { + returnTypeEqual = true and parameterTypesEqual = true + } + + /** + * Whether two function pointer/reference types are equivalent. By default, we only require that + * the return types and parameter types match. + */ + bindingset[t1, t2] + default predicate equalFunctionPointerIshTypes( + FunctionPointerIshType t1, FunctionPointerIshType t2, Boolean returnTypeEqual, + Boolean parameterTypesEqual + ) { + returnTypeEqual = true and parameterTypesEqual = true + } +} + +/** + * The default equivalence behavior for the `TypeEquivalence` module. + */ +module DefaultEquivalence implements TypeEquivalenceSig { } + +/** + * A signature class used to restrict the set of types considered by `TypeEquivalence`, for + * performance reasons. + */ +signature class TypeSubset extends Type; + +/** + * A module to check the equivalence of two types, as defined by the provided `TypeEquivalenceSig`. + * + * For performance reasons, this module is designed to be used with a `TypeSubset` that restricts + * the set of considered types. All types reachable (in the type graph) from a type in the subset + * will be considered. (See `RelevantType`.) + * + * To use this module, define a `TypeEquivalenceSig` module and implement a subset of `Type` that + * selects the relevant root types to be considered. Then use the predicate `equalTypes(a, b)`. + */ +module TypeEquivalence { + /** + * Check whether two types are equivalent, as defined by the `TypeEquivalenceSig` module. + */ + predicate equalTypes(RelevantType t1, RelevantType t2) { + if Config::overrideTypeComparison(t1, t2, _) + then Config::overrideTypeComparison(t1, t2, true) + else + if t1 instanceof TypedefType and Config::resolveTypedefs() + then equalTypes(t1.(TypedefType).getBaseType(), t2) + else + if t2 instanceof TypedefType and Config::resolveTypedefs() + then equalTypes(t1, t2.(TypedefType).getBaseType()) + else ( + not t1 instanceof DerivedType and + not t2 instanceof DerivedType and + not t1 instanceof TypedefType and + not t2 instanceof TypedefType and + LeafEquiv::getEquivalenceClass(t1) = LeafEquiv::getEquivalenceClass(t2) + or + equalDerivedTypes(t1, t2) + or + equalTypedefTypes(t1, t2) + or + equalFunctionTypes(t1, t2) + ) + } + + /** + * A type that is either part of the type subset, or that is reachable from a type in the subset. + */ + private class RelevantType instanceof Type { + RelevantType() { exists(T t | typeGraph*(t, this)) } + + string toString() { result = this.(Type).toString() } + } + + private class RelevantDerivedType extends RelevantType instanceof DerivedType { + RelevantType getBaseType() { result = this.(DerivedType).getBaseType() } + } + + private class RelevantFunctionType extends RelevantType instanceof FunctionType { + RelevantType getReturnType() { result = this.(FunctionType).getReturnType() } + + RelevantType getParameterType(int i) { result = this.(FunctionType).getParameterType(i) } + } + + private class RelevantTypedefType extends RelevantType instanceof TypedefType { + RelevantType getBaseType() { result = this.(TypedefType).getBaseType() } + } + + private module LeafEquiv = QlBuiltins::EquivalenceRelation; + + private predicate equalLeafRelation(RelevantType t1, RelevantType t2) { + Config::equalLeafTypes(t1, t2) + } + + private RelevantType unspecify(SpecifiedType t) { + // This subtly and importantly handles the complicated cases of typedefs. Under most scenarios, + // if we see a typedef in `equalTypes()` we can simply get the base type and continue. However, + // there is an exception if we have a specified type that points to a typedef that points to + // another specified type. In this case, `SpecifiedType::getASpecifier()` will return all of + // specifiers, not just those above the TypedefType, and `stripTopLevelSpecifiers` will return + // the innermost type that is not a TypedefType or a SpecifiedType, which is what we want, as + // all specifiers have already been accounted for when we visit the outermost `SpecifiedType`. + if Config::resolveTypedefs() + then result = t.(SpecifiedType).stripTopLevelSpecifiers() + else result = t.(SpecifiedType).getBaseType() + } + + bindingset[t1, t2] + private predicate equalDerivedTypes(RelevantDerivedType t1, RelevantDerivedType t2) { + exists(Boolean baseTypesEqual | + (baseTypesEqual = true implies equalTypes(t1.getBaseType(), t2.getBaseType())) and + ( + Config::equalPointerTypes(t1, t2, baseTypesEqual) + or + Config::equalArrayTypes(t1, t2, baseTypesEqual) + or + Config::equalReferenceTypes(t1, t2, baseTypesEqual) + ) + ) + or + exists(Boolean unspecifiedTypesEqual | + // Note that this case is different from the above, in that we don't merely get the base + // type (as that could be a TypedefType that points to another SpecifiedType). We need to + // unspecify the type to see if the base types are equal. + (unspecifiedTypesEqual = true implies equalTypes(unspecify(t1), unspecify(t2))) and + Config::equalSpecifiedTypes(t1, t2, unspecifiedTypesEqual) + ) + } + + bindingset[t1, t2] + private predicate equalFunctionTypes(RelevantFunctionType t1, RelevantFunctionType t2) { + exists(Boolean returnTypeEqual, Boolean parameterTypesEqual | + (returnTypeEqual = true implies equalTypes(t1.getReturnType(), t2.getReturnType())) and + ( + parameterTypesEqual = true + implies + forall(int i | exists([t1, t2].getParameterType(i)) | + equalTypes(t1.getParameterType(i), t2.getParameterType(i)) + ) + ) and + ( + Config::equalRoutineTypes(t1, t2, returnTypeEqual, parameterTypesEqual) + or + Config::equalFunctionPointerIshTypes(t1, t2, returnTypeEqual, parameterTypesEqual) + ) + ) + } + + bindingset[t1, t2] + private predicate equalTypedefTypes(RelevantTypedefType t1, RelevantTypedefType t2) { + exists(Boolean baseTypesEqual | + (baseTypesEqual = true implies equalTypes(t1.getBaseType(), t2.getBaseType())) and + Config::equalTypedefTypes(t1, t2, baseTypesEqual) + ) + } +} + +module FunctionDeclarationTypeEquivalence { + predicate equalReturnTypes(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { + TypeEquivalence::equalTypes(f1.getType(), f2.getType()) + } + + predicate equalParameterTypes(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { + f1.getDeclaration() = f2.getDeclaration() and + forall(int i | exists([f1, f2].getParameterDeclarationEntry(i)) | + TypeEquivalence::equalTypes(f1.getParameterDeclarationEntry(i) + .getType(), f2.getParameterDeclarationEntry(i).getType()) + ) + } +} + +/** + * Convenience class to reduce the awkwardness of how `RoutineType` and `FunctionPointerIshType` + * don't have a common ancestor. + */ +private class FunctionType extends Type { + FunctionType() { this instanceof RoutineType or this instanceof FunctionPointerIshType } + + Type getReturnType() { + result = this.(RoutineType).getReturnType() or + result = this.(FunctionPointerIshType).getReturnType() + } + + Type getParameterType(int i) { + result = this.(RoutineType).getParameterType(i) or + result = this.(FunctionPointerIshType).getParameterType(i) + } +} +/* + * predicate typesCompatibleImpl(Type t1, Type t2) { + * // A type is compatible with itself + * t1 = t2 + * or + * // All specifiers must match, but the order does not matter: + * ( + * t1 instanceof SpecifiedType and + * t2 instanceof SpecifiedType + * ) and + * specifiersMatchExactly(t1, t2) and + * typesCompatibleImpl(t1.stripTopLevelSpecifiers(), t2.stripTopLevelSpecifiers()) + * or + * // Identically qualified pointers are compatible if they point to compatible types. + * typesCompatibleImpl(t1.(PointerType).getBaseType(), t2.(PointerType).getBaseType()) + * or + * // Array objects are compatible if they have a compatible element type. If both have a constant + * // size then that size must match. + * typesCompatibleImpl(t1.(ArrayType).getBaseType(), t2.(ArrayType).getBaseType()) and + * count(int i | i = [t1, t2].(ArrayType).getSize()) < 2 + * or + * // Enum types are compatible with one of char, int, or signed int, but the implementation + * // decides. + * [t1, t2] instanceof Enum and + * ([t1, t2] instanceof CharType or [t1, t2] instanceof IntType) + * or + * // `int` is the same as `signed`, `signed int`, while `unsigned` is the same as `unsigned int`. + * t1.(IntegralType).getCanonicalArithmeticType() = t2.(IntegralType).getCanonicalArithmeticType() + * or + * // Function types are compatible if they have the same return type and compatible parameters. + * // Technically, variadic functions are have special behavior not covered here. + * exists(RoutineType f1, RoutineType f2 | f1 = t1 and f2 = t2 | + * typesCompatibleImpl(f1.getReturnType(), f2.getReturnType()) and + * forall(int i | exists([f1, f2].getParameterType(i)) | + * typesCompatibleImpl(f1.getParameterType(i), f2.getParameterType(i)) + * ) + * ) + * or + * // Function pointer types should be covered by `PointerType` and `RoutineType` above, but that is + * // not how they are implemented in CodeQL. + * exists(FunctionPointerIshType f1, FunctionPointerIshType f2 | f1 = t1 and f2 = t2 | + * typesCompatibleImpl(f1.getReturnType(), f2.getReturnType()) and + * forall(int i | exists([f1, f2].getParameterType(i)) | + * typesCompatibleImpl(f1.getParameterType(i), f2.getParameterType(i)) + * ) + * ) + * } + */ + diff --git a/cpp/common/src/codingstandards/cpp/types/Graph.qll b/cpp/common/src/codingstandards/cpp/types/Graph.qll new file mode 100644 index 0000000000..70c51a40ba --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/types/Graph.qll @@ -0,0 +1,15 @@ +import cpp + +predicate typeGraph(Type t, Type refersTo) { + refersTo = t.(DerivedType).getBaseType() + or + refersTo = t.(RoutineType).getReturnType() + or + refersTo = t.(RoutineType).getAParameterType() + or + refersTo = t.(FunctionPointerIshType).getReturnType() + or + refersTo = t.(FunctionPointerIshType).getAParameterType() + or + refersTo = t.(TypedefType).getBaseType() +} diff --git a/cpp/common/src/codingstandards/cpp/types/LvalueConversion.qll b/cpp/common/src/codingstandards/cpp/types/LvalueConversion.qll new file mode 100644 index 0000000000..252e783438 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/types/LvalueConversion.qll @@ -0,0 +1,38 @@ +import cpp + +/** + * Get the type of an lvalue after lvalue conversion. + * + * This will return the type itself if no conversion is performed. + */ +Type getLvalueConverted(Type t) { + if exists(performLvalueConversion(t, _)) + then result = performLvalueConversion(t, _) + else result = t +} + +/** + * Perform lvalue conversion on a type, allowing for a description of why the type was converted + * if it was. + * + * Does not return a value if no lvalue conversion was performed. + * + * Warning: This predicate may not return a result if the resulting type is not in the database. + * For convenience, this is accepted here, otherwise we would have to create a new type to return + * that wouldn't implement the type APIs and likely wouldn't be very useful. + */ +Type performLvalueConversion(Type t, string reason) { + result.(PointerType).getBaseType() = t.(ArrayType).getBaseType() and + reason = "array-to-pointer decay" + or + t instanceof RoutineType and + result.(PointerType).getBaseType() = t and + reason = "function-to-function-pointer decay" + or + isObjectType(t) and + exists(t.getASpecifier()) and + result = t.stripTopLevelSpecifiers() and + reason = "qualifiers removed" +} + +private predicate isObjectType(Type t) { not t.stripTopLevelSpecifiers() instanceof PointerType } diff --git a/cpp/common/src/codingstandards/cpp/Pointers.qll b/cpp/common/src/codingstandards/cpp/types/Pointers.qll similarity index 100% rename from cpp/common/src/codingstandards/cpp/Pointers.qll rename to cpp/common/src/codingstandards/cpp/types/Pointers.qll diff --git a/cpp/common/src/codingstandards/cpp/types/SimpleAssignment.qll b/cpp/common/src/codingstandards/cpp/types/SimpleAssignment.qll new file mode 100644 index 0000000000..e9804c29c4 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/types/SimpleAssignment.qll @@ -0,0 +1,45 @@ +import codingstandards.cpp.types.LvalueConversion +import codingstandards.cpp.types.Compatible + +module SimpleAssignment { + final private class FinalType = Type; + + private class RelevantType extends FinalType { + RelevantType() { exists(T t | typeGraph*(t, this) or typeGraph(getLvalueConverted(t), this)) } + + string toString() { result = "relevant type" } + } + + /** + * Whether a pair of qualified or unqualified pointer types satisfy the simple assignment + * constraints from 6.5.16.1. + * + * There are additional constraints not implemented here involving one or more arithmetic types. + */ + predicate satisfiesSimplePointerAssignment(RelevantType left, RelevantType right) { + simplePointerAssignmentImpl(getLvalueConverted(left), right) + } + + /** + * Implementation of 6.5.16.1 for a pair of pointer types, that assumes lvalue conversion has been + * performed on the left operand. + */ + private predicate simplePointerAssignmentImpl(RelevantType left, RelevantType right) { + exists(RelevantType leftBase, RelevantType rightBase | + // The left operand has atomic, qualified, or unqualified pointer type: + leftBase = left.stripTopLevelSpecifiers().(PointerType).getBaseType() and + rightBase = right.stripTopLevelSpecifiers().(PointerType).getBaseType() and + ( + // and both operands are pointers to qualified or unqualified versions of compatible types: + TypeEquivalence::equalTypes(leftBase + .stripTopLevelSpecifiers(), rightBase.stripTopLevelSpecifiers()) + or + // or one operand is a pointer to a qualified or unqualified version of void + [leftBase, rightBase].stripTopLevelSpecifiers() instanceof VoidType + ) and + // and the type pointed to by the left has all the qualifiers of the type pointed to by the + // right: + forall(Specifier s | s = rightBase.getASpecifier() | s = leftBase.getASpecifier()) + ) + } +} diff --git a/cpp/common/src/codingstandards/cpp/TrivialType.qll b/cpp/common/src/codingstandards/cpp/types/TrivialType.qll similarity index 100% rename from cpp/common/src/codingstandards/cpp/TrivialType.qll rename to cpp/common/src/codingstandards/cpp/types/TrivialType.qll diff --git a/cpp/common/src/codingstandards/cpp/types/Type.qll b/cpp/common/src/codingstandards/cpp/types/Type.qll new file mode 100644 index 0000000000..42d77b8055 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/types/Type.qll @@ -0,0 +1,96 @@ +/** + * A module for representing different `Type`s. + */ + +import cpp + +/** + * A fundamental type, as defined by `[basic.fundamental]`. + */ +class FundamentalType extends BuiltInType { + FundamentalType() { + // A fundamental type is any `BuiltInType` except types indicating errors during extraction, or + // "unknown" types inserted into uninstantiated templates + not this instanceof ErroneousType and + not this instanceof UnknownType + } +} + +/** + * A type that is incomplete. + */ +class IncompleteType extends Class { + IncompleteType() { not hasDefinition() } +} + +/** + * A type that implements the BitmaskType trait. + * https://en.cppreference.com/w/cpp/named_req/BitmaskType + */ +abstract class BitmaskType extends Type { } + +/** + * Holds if `enum` implements required overload `overload` to implement + * the BitmaskType trait. + */ +private predicate isRequiredEnumOverload(Enum enum, Function overload) { + overload.getName().regexpMatch("operator([&|^~]|&=|\\|=)") and + forex(Parameter p | p = overload.getAParameter() | + ( + p.getType() = enum + or + p.getType().(ReferenceType).getBaseType() = enum + ) + ) +} + +private class EnumBitmaskType extends BitmaskType, Enum { + EnumBitmaskType() { + // Implements all the required overload + count(Function overload | isRequiredEnumOverload(this, overload)) = 6 + } +} + +/** + * A type without `const` and `volatile` specifiers. + */ +Type stripSpecifiers(Type type) { + if type instanceof SpecifiedType + then result = stripSpecifiers(type.(SpecifiedType).getBaseType()) + else result = type +} + +signature class PossiblySpecifiedBaseType extends Type; + +/** + * This module defines a class `Type` which holds for types `T` and `const/volatile T` etc. + * + * Similar to `getUnspecifiedType()`, but does not resolve typedefs. Useful for matching + * potentially qualified versions of standard typedef types, such as `const mtx_t`. + * + * Example usage: `someType.(PossiblySpecified::Type).strip()` + */ +module PossiblySpecified { + import cpp as cpp + + final class CppType = cpp::Type; + + class Type extends CppType { + BaseType baseType; + + Type() { baseType = stripSpecifiers(this) } + + BaseType strip() { result = baseType } + } +} + +/** + * Get the precision of an integral type, where precision is defined as the number of bits + * that can be used to represent the numeric value. + * https://wiki.sei.cmu.edu/confluence/display/c/INT35-C.+Use+correct+integer+precisions + */ +int getPrecision(IntegralType type) { + type.isExplicitlyUnsigned() and result = type.getSize() * 8 + or + type.isExplicitlySigned() and result = type.getSize() * 8 - 1 +} diff --git a/cpp/common/src/codingstandards/cpp/TypeUses.qll b/cpp/common/src/codingstandards/cpp/types/Uses.qll similarity index 100% rename from cpp/common/src/codingstandards/cpp/TypeUses.qll rename to cpp/common/src/codingstandards/cpp/types/Uses.qll diff --git a/cpp/common/src/codingstandards/cpp/VariablyModifiedTypes.qll b/cpp/common/src/codingstandards/cpp/types/VariablyModifiedTypes.qll similarity index 100% rename from cpp/common/src/codingstandards/cpp/VariablyModifiedTypes.qll rename to cpp/common/src/codingstandards/cpp/types/VariablyModifiedTypes.qll diff --git a/cpp/common/test/guideline_recategorizations/DisappliedQuery.ql b/cpp/common/test/guideline_recategorizations/DisappliedQuery.ql index 0254eca9bd..58ba3239e0 100644 --- a/cpp/common/test/guideline_recategorizations/DisappliedQuery.ql +++ b/cpp/common/test/guideline_recategorizations/DisappliedQuery.ql @@ -10,7 +10,7 @@ import cpp import codingstandards.cpp.CodingStandards -import codingstandards.cpp.TypeUses +import codingstandards.cpp.types.Uses import codingstandards.cpp.exclusions.cpp.RuleMetadata from UserType ut, string reason diff --git a/cpp/common/test/library/codingstandards/cpp/trivialtypes/LiteralType.ql b/cpp/common/test/library/codingstandards/cpp/trivialtypes/LiteralType.ql index 4d0f8567d0..e7a1d5ebd3 100644 --- a/cpp/common/test/library/codingstandards/cpp/trivialtypes/LiteralType.ql +++ b/cpp/common/test/library/codingstandards/cpp/trivialtypes/LiteralType.ql @@ -1,5 +1,5 @@ import cpp -import codingstandards.cpp.TrivialType +import codingstandards.cpp.types.TrivialType from Type t where diff --git a/cpp/common/test/library/codingstandards/cpp/trivialtypes/TrivialType.ql b/cpp/common/test/library/codingstandards/cpp/trivialtypes/TrivialType.ql index a85fcf5676..edbfbe5303 100644 --- a/cpp/common/test/library/codingstandards/cpp/trivialtypes/TrivialType.ql +++ b/cpp/common/test/library/codingstandards/cpp/trivialtypes/TrivialType.ql @@ -1,5 +1,5 @@ import cpp -import codingstandards.cpp.TrivialType +import codingstandards.cpp.types.TrivialType from Type t where diff --git a/cpp/common/test/library/codingstandards/cpp/trivialtypes/TriviallyCopyableType.ql b/cpp/common/test/library/codingstandards/cpp/trivialtypes/TriviallyCopyableType.ql index 3b3f498796..1667372f4b 100644 --- a/cpp/common/test/library/codingstandards/cpp/trivialtypes/TriviallyCopyableType.ql +++ b/cpp/common/test/library/codingstandards/cpp/trivialtypes/TriviallyCopyableType.ql @@ -1,5 +1,5 @@ import cpp -import codingstandards.cpp.TrivialType +import codingstandards.cpp.types.TrivialType from TriviallyCopyableClass t select t diff --git a/rule_packages/c/Generics.json b/rule_packages/c/Generics.json new file mode 100644 index 0000000000..1183bdc709 --- /dev/null +++ b/rule_packages/c/Generics.json @@ -0,0 +1,194 @@ +{ + "MISRA-C-2012": { + "RULE-23-1": { + "properties": { + "obligation": "advisory" + }, + "queries": [ + { + "description": "A generic selection should only be expanded from a macro.", + "kind": "problem", + "name": "A generic selection should only be expanded from a macro", + "precision": "very-high", + "severity": "warning", + "short_name": "GenericSelectionNotExpandedFromAMacro", + "tags": [ + "maintainability", + "external/misra/c/2012/amendment3" + ] + }, + { + "description": "A generic selection should depend on the type of a macro argument.", + "kind": "problem", + "name": "A generic selection should depend on the type of a macro argument", + "precision": "high", + "severity": "warning", + "short_name": "GenericSelectionDoesntDependOnMacroArgument", + "tags": [ + "correctness", + "maintainability", + "external/misra/c/2012/amendment3" + ] + } + ], + "title": "A generic selection should only be expanded from a macro" + }, + "RULE-23-2": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "A generic selection that is not expanded from a macro shall not contain potential side effects in the controlling expression.", + "kind": "problem", + "name": "A generic selection shall not contain side-effects if it is not expanded from a macro", + "precision": "high", + "severity": "warning", + "short_name": "GenericSelectionNotFromMacroWithSideEffects", + "tags": [ + "maintainability", + "external/misra/c/2012/amendment3" + ] + } + ], + "implementation_scope": { + "items": [ + "Due to limited information in the CodeQL database for macro argument expansions, this implementation reports generics not of the form `_Generic((X)` where all invocations of that generic contain a side effect in the controlling expression." + ] + }, + "title": "A generic selection that is not expanded from a macro shall not contain potential side effects in the controlling expression" + }, + "RULE-23-3": { + "properties": { + "obligation": "advisory" + }, + "queries": [ + { + "description": "A generic selection should contain at least one non-default association.", + "kind": "problem", + "name": "A generic selection should contain at least one non-default association", + "precision": "very-high", + "severity": "warning", + "short_name": "GenericWithoutNonDefaultAssociation", + "tags": [ + "correctness", + "maintainability", + "external/misra/c/2012/amendment3" + ] + } + ], + "title": "A generic selection should contain at least one non-default association" + }, + "RULE-23-4": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Generic selections undergo lvalue conversion before type comparison, leading to certain types being impossible to select.", + "kind": "problem", + "name": "A generic association shall list an appropriate type", + "precision": "very-high", + "severity": "error", + "short_name": "GenericAssociationWithUnselectableType", + "tags": [ + "correctness", + "external/misra/c/2012/amendment3" + ] + } + ], + "title": "A generic association shall list an appropriate type" + }, + "RULE-23-5": { + "properties": { + "obligation": "advisory" + }, + "queries": [ + { + "description": "Pointer types in a generic selection do not undergo pointer conversions and should not counterintuitively fall through to the default association.", + "kind": "problem", + "name": "A generic selection should not depend on implicit pointer type conversion", + "precision": "very-high", + "severity": "warning", + "short_name": "DangerousDefaultSelectionForPointerInGeneric", + "tags": [ + "correctness", + "external/misra/c/2012/amendment3" + ] + } + ], + "title": "A generic selection should not depend on implicit pointer type conversion" + }, + "RULE-23-6": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "The controlling expression of a generic selection shall have an essential type that matches its standard type.", + "kind": "problem", + "name": "The controlling expression of a generic selection shall have an essential type that matches its standard type", + "precision": "high", + "severity": "error", + "short_name": "GenericExpressionWithIncorrectEssentialType", + "tags": [ + "correctness", + "external/misra/c/2012/amendment3" + ] + } + ], + "implementation_scope": { + "items": [ + "The CodeQL extractor will expand character literals passed into macros into integer literals, and therefore the essential type system for character literals will not necessarily be analyzed correctly." + ] + }, + "title": "The controlling expression of a generic selection shall have an essential type that matches its standard type" + }, + "RULE-23-7": { + "properties": { + "obligation": "advisory" + }, + "queries": [ + { + "description": "A generic selection that is expanded from a macro should evaluate its argument only once.", + "kind": "problem", + "name": "A generic selection that is expanded from a macro should evaluate its argument only once", + "precision": "medium", + "severity": "warning", + "short_name": "InvalidGenericMacroArgumentEvaluation", + "tags": [ + "correctness", + "maintainability", + "external/misra/c/2012/amendment3" + ] + } + ], + "implementation_scope": { + "items": [ + "Due to limited information in the CodeQL database for macro argument expansions, this implementation performs string matching on the macro parameters against the macro body to determine where parameters are expanded. If text indicating a nonevaluated context such as sizeof() or _Alignof() appear, there will be no positive result." + ] + }, + "title": "A generic selection that is expanded from a macro should evaluate its argument only once" + }, + "RULE-23-8": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "A default association shall appear as either the first or the last association of a generic selection", + "kind": "problem", + "name": "A default association shall appear as either the first or the last association of a generic", + "precision": "very-high", + "severity": "warning", + "short_name": "DefaultGenericSelectionNotFirstOrLast", + "tags": [ + "maintainability", + "external/misra/c/2012/amendment3" + ] + } + ], + "title": "A default association shall appear as either the first or the last association of a generic selection" + } + } +} \ No newline at end of file From cec1948777ab22388c622f460e1dfde9577f66d9 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 9 Mar 2025 23:05:52 -0700 Subject: [PATCH 237/370] Use clang-format v11, which is closer to v14 installed on ci/cd --- c/misra/test/rules/RULE-23-1/test.c | 26 +-- c/misra/test/rules/RULE-23-2/test.c | 28 +-- c/misra/test/rules/RULE-23-3/test.c | 16 +- c/misra/test/rules/RULE-23-4/test.c | 70 +++---- c/misra/test/rules/RULE-23-5/test.c | 301 ++++++++++++++-------------- c/misra/test/rules/RULE-23-6/test.c | 20 +- c/misra/test/rules/RULE-23-7/test.c | 57 +++--- c/misra/test/rules/RULE-23-8/test.c | 20 +- 8 files changed, 270 insertions(+), 268 deletions(-) diff --git a/c/misra/test/rules/RULE-23-1/test.c b/c/misra/test/rules/RULE-23-1/test.c index f27541dd38..c7d33b1a70 100644 --- a/c/misra/test/rules/RULE-23-1/test.c +++ b/c/misra/test/rules/RULE-23-1/test.c @@ -1,25 +1,25 @@ // NON_COMPLIANT: -#define M1 _Generic(1, int: 1) +#define M1 _Generic(1, int : 1) // NON_COMPLIANT: -#define M2(X) _Generic(1, int: X) +#define M2(X) _Generic(1, int : X) // COMPLIANT: -#define M3(X) _Generic((X), int: 1) +#define M3(X) _Generic((X), int : 1) // COMPLIANT: -#define M4(X) _Generic((X), int: 1) +#define M4(X) _Generic((X), int : 1) // COMPLIANT: -#define M5(X) _Generic((X + X), int: 1) +#define M5(X) _Generic((X + X), int : 1) int f1(int a, int b); // COMPLIANT: -#define M6(X) _Generic(f(1, (X)), int: 1) -#define M7(X) 1 + _Generic((X), int: 1) +#define M6(X) _Generic(f(1, (X)), int : 1) +#define M7(X) 1 + _Generic((X), int : 1) // COMPLIANT: -#define M8(X) g(_Generic((X), int: 1)) +#define M8(X) g(_Generic((X), int : 1)) // NON_COMPLIANT: -#define M9(X) g(_Generic((Y), int: 1)) +#define M9(X) g(_Generic((Y), int : 1)) void f2() { - _Generic(1, int: 1); // NON_COMPLIANT - M1; // NON_COMPLIANT - M2(1); // NON_COMPLIANT - M3(1); // COMPLIANT + _Generic(1, int : 1); // NON_COMPLIANT + M1; // NON_COMPLIANT + M2(1); // NON_COMPLIANT + M3(1); // COMPLIANT } diff --git a/c/misra/test/rules/RULE-23-2/test.c b/c/misra/test/rules/RULE-23-2/test.c index 6a25e15189..9e4c6ca6b2 100644 --- a/c/misra/test/rules/RULE-23-2/test.c +++ b/c/misra/test/rules/RULE-23-2/test.c @@ -1,30 +1,30 @@ -#define M1(X) _Generic((X), int: 1) +#define M1(X) _Generic((X), int : 1) // NON_COMPLIANT: -#define M2(X) _Generic((X)++, int: 1) +#define M2(X) _Generic((X)++, int : 1) // NON_COMPLIANT: -#define M3(X) _Generic(l1++, int: (X)) +#define M3(X) _Generic(l1++, int : (X)) // COMPLIANT: #define M3_WRAPPER(X) M3(X) -#define M4(X) _Generic((X)(), int: 1) +#define M4(X) _Generic((X)(), int : 1) void f1() { int l1; - _Generic(1, int: 1); // COMPLIANT - M1(1); // COMPLIANT - _Generic(l1, int: 1); // COMPLIANT - M1(l1); // COMPLIANT + _Generic(1, int : 1); // COMPLIANT + M1(1); // COMPLIANT + _Generic(l1, int : 1); // COMPLIANT + M1(l1); // COMPLIANT _Generic(l1++, - int: 1); // COMPLIANT: side effect is not from a macro argument. - M1(l1++); // COMPLIANT - M2(l1); // NON-COMPLIANT: at macro definition - M3(1); // NON-COMPLIANT: at macro definition - M3_WRAPPER(1); // NON-COMPLIANT: at definition of M3 + int : 1); // COMPLIANT: side effect is not from a macro argument. + M1(l1++); // COMPLIANT + M2(l1); // NON-COMPLIANT: at macro definition + M3(1); // NON-COMPLIANT: at macro definition + M3_WRAPPER(1); // NON-COMPLIANT: at definition of M3 } int g1; @@ -41,7 +41,7 @@ void f2() { #define M5(X) \ static volatile l##X; \ - _Generic(l##X, int: 1) + _Generic(l##X, int : 1) void f3() { M5(a); // NON-COMPLIANT diff --git a/c/misra/test/rules/RULE-23-3/test.c b/c/misra/test/rules/RULE-23-3/test.c index d3f093f242..616c14bc80 100644 --- a/c/misra/test/rules/RULE-23-3/test.c +++ b/c/misra/test/rules/RULE-23-3/test.c @@ -1,20 +1,20 @@ // NON-COMPLIANT -#define M1 _Generic(1, default: 1); +#define M1 _Generic(1, default : 1); // COMPLIANT -#define M2 _Generic(1, int: 1); +#define M2 _Generic(1, int : 1); // COMPLIANT -#define M3 _Generic(1, int: 1, default: 1); +#define M3 _Generic(1, int : 1, default : 1); // COMPLIANT -#define M4 _Generic(1, int: 1, long: 1); +#define M4 _Generic(1, int : 1, long : 1); void f() { // Invalid generics: // _Generic(1); // _Generic(1, void: 1); - _Generic(1, default: 1); // NON-COMPLIANT - _Generic(1, int: 1); // COMPLIANT - _Generic(1, int: 1, default: 1); // COMPLIANT - _Generic(1, int: 1, long: 1); // COMPLIANT + _Generic(1, default : 1); // NON-COMPLIANT + _Generic(1, int : 1); // COMPLIANT + _Generic(1, int : 1, default : 1); // COMPLIANT + _Generic(1, int : 1, long : 1); // COMPLIANT M1; M2; diff --git a/c/misra/test/rules/RULE-23-4/test.c b/c/misra/test/rules/RULE-23-4/test.c index 135ab4d0f7..cfef26318c 100644 --- a/c/misra/test/rules/RULE-23-4/test.c +++ b/c/misra/test/rules/RULE-23-4/test.c @@ -7,41 +7,41 @@ union empty_union {}; void f() { _Generic(1, - int: 1, // COMPLIANT - const int: 1, // NON-COMPLIANT - volatile int: 1, // NON-COMPLIANT - _Atomic int: 1, // NON-COMPLIANT - int *: 1, // COMPLIANT - int const *: 1, // COMPLIANT - const volatile int: 1, // NON-COMPLIANT - int volatile const *: 1, // COMPLIANT - struct {}: 1, // NON-COMPLIANT - struct {} *: 1, // NON-COMPLIANT - empty_struct_t: 1, // COMPLIANT - struct empty_struct: 1, // COMPLIANT - empty_struct_t *: 1, // COMPLIANT - struct empty_struct *: 1, // COMPLIANT - union {}: 1, // NON-COMPLIANT - union {} *: 1, // NON-COMPLIANT - empty_union_t: 1, // COMPLIANT - union empty_union: 1, // COMPLIANT - empty_union_t *: 1, // COMPLIANT - union empty_union *: 1, // COMPLIANT - // int[]: 1, // compile error - int[3]: 1, // NON-COMPLIANT - int(*)[3]: 1, // COMPLIANT: pointer to array OK - // int (int*): 1, // compile error - int (*)(int *): 1, // COMPLIANT: function pointers OK - default: 1 // COMPLIANT + int : 1, // COMPLIANT + const int : 1, // NON-COMPLIANT + volatile int : 1, // NON-COMPLIANT + _Atomic int : 1, // NON-COMPLIANT + int * : 1, // COMPLIANT + int const * : 1, // COMPLIANT + const volatile int : 1, // NON-COMPLIANT + int volatile const * : 1, // COMPLIANT + struct {} : 1, // NON-COMPLIANT + struct {} * : 1, // NON-COMPLIANT + empty_struct_t : 1, // COMPLIANT + struct empty_struct : 1, // COMPLIANT + empty_struct_t * : 1, // COMPLIANT + struct empty_struct * : 1, // COMPLIANT + union {} : 1, // NON-COMPLIANT + union {} * : 1, // NON-COMPLIANT + empty_union_t : 1, // COMPLIANT + union empty_union : 1, // COMPLIANT + empty_union_t * : 1, // COMPLIANT + union empty_union * : 1, // COMPLIANT + // int[]: 1, // compile error + int[3] : 1, // NON-COMPLIANT + int(*)[3] : 1, // COMPLIANT: pointer to array OK + // int (int*): 1, // compile error + int (*)(int *) : 1, // COMPLIANT: function pointers OK + default : 1 // COMPLIANT ); } // NON-COMPLIANT -#define M1(X) _Generic((X), const int: 1, default: 0) +#define M1(X) _Generic((X), const int : 1, default : 0) // NON-COMPLIANT -#define M2(X) _Generic(1, X[3]: 1, default: 0) +#define M2(X) _Generic(1, X[3] : 1, default : 0) // COMPLIANT -#define M3(X) _Generic(1, X: 1, default: 0) +#define M3(X) _Generic(1, X : 1, default : 0) void f2() { M1(1); @@ -60,12 +60,12 @@ typedef long const *long_const_ptr; void f3() { _Generic(1, - int_t: 1, // COMPLIANT - const_int: 1, // NON-COMPLIANT - const_int_ptr: 1, // COMPLIANT - long_const_ptr: 1, // COMPLIANT - const int_ptr: 1, // COMPLIANT - default: 1 // COMPLIANT + int_t : 1, // COMPLIANT + const_int : 1, // NON-COMPLIANT + const_int_ptr : 1, // COMPLIANT + long_const_ptr : 1, // COMPLIANT + const int_ptr : 1, // COMPLIANT + default : 1 // COMPLIANT ); } diff --git a/c/misra/test/rules/RULE-23-5/test.c b/c/misra/test/rules/RULE-23-5/test.c index d9e140f0af..5d48cc58bd 100644 --- a/c/misra/test/rules/RULE-23-5/test.c +++ b/c/misra/test/rules/RULE-23-5/test.c @@ -19,85 +19,85 @@ void f2() { void *: f1, const void *: f1, default: f1); // COMPLIANT - _Generic(l2, int: f1, default: f1); // COMPLIANT - _Generic(l3, int: f1, default: f1); // COMPLIANT - _Generic(l4, int: f1, default: f1); // COMPLIANT - _Generic(l5, int: f1, default: f1); // COMPLIANT + _Generic(l2, int : f1, default : f1); // COMPLIANT + _Generic(l3, int : f1, default : f1); // COMPLIANT + _Generic(l4, int : f1, default : f1); // COMPLIANT + _Generic(l5, int : f1, default : f1); // COMPLIANT // Compliant, default case is not matched - _Generic(l1, int: f1); // COMPLIANT - _Generic(l2, int *: f1); // COMPLIANT - _Generic(l3, const int *: f1); // COMPLIANT - _Generic(l4, volatile int *: f1); // COMPLIANT - _Generic(l5, volatile const int *: f1); // COMPLIANT - _Generic(l6, void *: f1); // COMPLIANT - _Generic(l7, const void *: f1); // COMPLIANT - _Generic(l8, volatile void *: f1); // COMPLIANT - _Generic(l9, const volatile void *: f1); // COMPLIANT + _Generic(l1, int : f1); // COMPLIANT + _Generic(l2, int * : f1); // COMPLIANT + _Generic(l3, const int * : f1); // COMPLIANT + _Generic(l4, volatile int * : f1); // COMPLIANT + _Generic(l5, volatile const int * : f1); // COMPLIANT + _Generic(l6, void * : f1); // COMPLIANT + _Generic(l7, const void * : f1); // COMPLIANT + _Generic(l8, volatile void * : f1); // COMPLIANT + _Generic(l9, const volatile void * : f1); // COMPLIANT // Violation, match default case due to lack of pointer to pointer // conversions: - _Generic(l2, int *: f1, default: f1); // COMPLIANT - _Generic(l2, const int *: f1, default: f1); // NON-COMPLIANT - _Generic(l2, volatile int *: f1, default: f1); // NON-COMPLIANT - _Generic(l2, const volatile int *: f1, default: f1); // NON-COMPLIANT - _Generic(l2, void *: f1, default: f1); // NON-COMPLIANT - _Generic(l2, const void *: f1, default: f1); // NON-COMPLIANT - _Generic(l2, const volatile void *: f1, default: f1); // NON-COMPLIANT - - _Generic(l3, int *: f1, default: f1); // NON-COMPLIANT - _Generic(l3, const int *: f1, default: f1); // COMPLIANT - _Generic(l3, void *: f1, default: f1); // NON-COMPLIANT - _Generic(l3, const void *: f1, default: f1); // NON-COMPLIANT - _Generic(l3, const volatile void *: f1, default: f1); // NON-COMPLIANT + _Generic(l2, int * : f1, default : f1); // COMPLIANT + _Generic(l2, const int * : f1, default : f1); // NON-COMPLIANT + _Generic(l2, volatile int * : f1, default : f1); // NON-COMPLIANT + _Generic(l2, const volatile int * : f1, default : f1); // NON-COMPLIANT + _Generic(l2, void * : f1, default : f1); // NON-COMPLIANT + _Generic(l2, const void * : f1, default : f1); // NON-COMPLIANT + _Generic(l2, const volatile void * : f1, default : f1); // NON-COMPLIANT + + _Generic(l3, int * : f1, default : f1); // NON-COMPLIANT + _Generic(l3, const int * : f1, default : f1); // COMPLIANT + _Generic(l3, void * : f1, default : f1); // NON-COMPLIANT + _Generic(l3, const void * : f1, default : f1); // NON-COMPLIANT + _Generic(l3, const volatile void * : f1, default : f1); // NON-COMPLIANT // Obviously not volatile: - _Generic(l3, volatile int *: f1, default: f1); // COMPLIANT + _Generic(l3, volatile int * : f1, default : f1); // COMPLIANT // Debatable, but volatile const int* is assignable to const int* so its // considered risky - _Generic(l3, const volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l3, const volatile int * : f1, default : f1); // NON-COMPLIANT - _Generic(l4, int *: f1, default: f1); // NON-COMPLIANT - _Generic(l4, volatile int *: f1, default: f1); // COMPLIANT - _Generic(l4, const volatile int *: f1, default: f1); // NON-COMPLIANT - _Generic(l4, void *: f1, default: f1); // NON-COMPLIANT - _Generic(l4, const volatile void *: f1, default: f1); // NON-COMPLIANT + _Generic(l4, int * : f1, default : f1); // NON-COMPLIANT + _Generic(l4, volatile int * : f1, default : f1); // COMPLIANT + _Generic(l4, const volatile int * : f1, default : f1); // NON-COMPLIANT + _Generic(l4, void * : f1, default : f1); // NON-COMPLIANT + _Generic(l4, const volatile void * : f1, default : f1); // NON-COMPLIANT // Debatable, but volatile int* isn't assignable to const int* or vice versa. - _Generic(l4, const int *: f1, default: f1); // COMPLIANT + _Generic(l4, const int * : f1, default : f1); // COMPLIANT // Debatable, but volatile int* isn't assignable to const void* or vice versa. - _Generic(l4, const void *: f1, default: f1); // COMPLIANT - - _Generic(l5, int *: f1, default: f1); // NON-COMPLIANT - _Generic(l5, const int *: f1, default: f1); // NON-COMPLIANT - _Generic(l5, volatile int *: f1, default: f1); // NON-COMPLIANT - _Generic(l5, const volatile int *: f1, default: f1); // COMPLIANT - _Generic(l5, void *: f1, default: f1); // NON-COMPLIANT - _Generic(l5, const void *: f1, default: f1); // NON-COMPLIANT - _Generic(l5, const volatile void *: f1, default: f1); // NON-COMPLIANT - - _Generic(l6, int *: f1, default: f1); // NON-COMPLIANT - _Generic(l6, const int *: f1, default: f1); // NON-COMPLIANT - _Generic(l6, volatile int *: f1, default: f1); // NON-COMPLIANT - _Generic(l6, const volatile int *: f1, default: f1); // NON-COMPLIANT - _Generic(l6, void *: f1, default: f1); // COMPLIANT - _Generic(l6, const void *: f1, default: f1); // NON-COMPLIANT - _Generic(l6, const volatile void *: f1, default: f1); // NON-COMPLIANT - - _Generic(l7, int *: f1, default: f1); // NON-COMPLIANT - _Generic(l7, const int *: f1, default: f1); // NON-COMPLIANT - _Generic(l7, const volatile int *: f1, default: f1); // NON-COMPLIANT - _Generic(l7, void *: f1, default: f1); // NON-COMPLIANT - _Generic(l7, const void *: f1, default: f1); // COMPLIANT - _Generic(l7, const volatile void *: f1, default: f1); // NON-COMPLIANT + _Generic(l4, const void * : f1, default : f1); // COMPLIANT + + _Generic(l5, int * : f1, default : f1); // NON-COMPLIANT + _Generic(l5, const int * : f1, default : f1); // NON-COMPLIANT + _Generic(l5, volatile int * : f1, default : f1); // NON-COMPLIANT + _Generic(l5, const volatile int * : f1, default : f1); // COMPLIANT + _Generic(l5, void * : f1, default : f1); // NON-COMPLIANT + _Generic(l5, const void * : f1, default : f1); // NON-COMPLIANT + _Generic(l5, const volatile void * : f1, default : f1); // NON-COMPLIANT + + _Generic(l6, int * : f1, default : f1); // NON-COMPLIANT + _Generic(l6, const int * : f1, default : f1); // NON-COMPLIANT + _Generic(l6, volatile int * : f1, default : f1); // NON-COMPLIANT + _Generic(l6, const volatile int * : f1, default : f1); // NON-COMPLIANT + _Generic(l6, void * : f1, default : f1); // COMPLIANT + _Generic(l6, const void * : f1, default : f1); // NON-COMPLIANT + _Generic(l6, const volatile void * : f1, default : f1); // NON-COMPLIANT + + _Generic(l7, int * : f1, default : f1); // NON-COMPLIANT + _Generic(l7, const int * : f1, default : f1); // NON-COMPLIANT + _Generic(l7, const volatile int * : f1, default : f1); // NON-COMPLIANT + _Generic(l7, void * : f1, default : f1); // NON-COMPLIANT + _Generic(l7, const void * : f1, default : f1); // COMPLIANT + _Generic(l7, const volatile void * : f1, default : f1); // NON-COMPLIANT // Debatable, but const void* isn't assignable to volatile int* or vice versa. - _Generic(l7, volatile int *: f1, default: f1); // COMPLIANT + _Generic(l7, volatile int * : f1, default : f1); // COMPLIANT - _Generic(l9, int *: f1, default: f1); // NON-COMPLIANT - _Generic(l9, const int *: f1, default: f1); // NON-COMPLIANT - _Generic(l9, volatile int *: f1, default: f1); // NON-COMPLIANT - _Generic(l9, const volatile int *: f1, default: f1); // NON-COMPLIANT - _Generic(l9, void *: f1, default: f1); // NON-COMPLIANT - _Generic(l9, const void *: f1, default: f1); // NON-COMPLIANT - _Generic(l9, const volatile void *: f1, default: f1); // COMPLIANT + _Generic(l9, int * : f1, default : f1); // NON-COMPLIANT + _Generic(l9, const int * : f1, default : f1); // NON-COMPLIANT + _Generic(l9, volatile int * : f1, default : f1); // NON-COMPLIANT + _Generic(l9, const volatile int * : f1, default : f1); // NON-COMPLIANT + _Generic(l9, void * : f1, default : f1); // NON-COMPLIANT + _Generic(l9, const void * : f1, default : f1); // NON-COMPLIANT + _Generic(l9, const volatile void * : f1, default : f1); // COMPLIANT /** * Edge case 1: The controlling expression undergoes lvalue conversion, so @@ -110,66 +110,66 @@ void f2() { int *const l14; const int *const l15; - _Generic(l10, int *: f1, default: f1); // COMPLIANT - _Generic(l11, const int *: f1, default: f1); // COMPLIANT - _Generic(l12, volatile int *: f1, default: f1); // COMPLIANT - _Generic(l13, const volatile int *: f1, default: f1); // COMPLIANT - - _Generic(l10, int *: f1, default: f1); // COMPLIANT - _Generic(l10, const int *: f1, default: f1); // NON-COMPLIANT - _Generic(l10, volatile int *: f1, default: f1); // NON-COMPLIANT - _Generic(l10, const volatile int *: f1, default: f1); // NON-COMPLIANT - _Generic(l10, void *: f1, default: f1); // NON-COMPLIANT - _Generic(l10, const void *: f1, default: f1); // NON-COMPLIANT - _Generic(l10, const volatile void *: f1, default: f1); // NON-COMPLIANT - - _Generic(l11, int *: f1, default: f1); // NON-COMPLIANT - _Generic(l11, const int *: f1, default: f1); // COMPLIANT - _Generic(l11, void *: f1, default: f1); // NON-COMPLIANT - _Generic(l11, const void *: f1, default: f1); // NON-COMPLIANT - _Generic(l11, const volatile void *: f1, default: f1); // NON-COMPLIANT + _Generic(l10, int * : f1, default : f1); // COMPLIANT + _Generic(l11, const int * : f1, default : f1); // COMPLIANT + _Generic(l12, volatile int * : f1, default : f1); // COMPLIANT + _Generic(l13, const volatile int * : f1, default : f1); // COMPLIANT + + _Generic(l10, int * : f1, default : f1); // COMPLIANT + _Generic(l10, const int * : f1, default : f1); // NON-COMPLIANT + _Generic(l10, volatile int * : f1, default : f1); // NON-COMPLIANT + _Generic(l10, const volatile int * : f1, default : f1); // NON-COMPLIANT + _Generic(l10, void * : f1, default : f1); // NON-COMPLIANT + _Generic(l10, const void * : f1, default : f1); // NON-COMPLIANT + _Generic(l10, const volatile void * : f1, default : f1); // NON-COMPLIANT + + _Generic(l11, int * : f1, default : f1); // NON-COMPLIANT + _Generic(l11, const int * : f1, default : f1); // COMPLIANT + _Generic(l11, void * : f1, default : f1); // NON-COMPLIANT + _Generic(l11, const void * : f1, default : f1); // NON-COMPLIANT + _Generic(l11, const volatile void * : f1, default : f1); // NON-COMPLIANT // Obviously not volatile: - _Generic(l11, volatile int *: f1, default: f1); // COMPLIANT + _Generic(l11, volatile int * : f1, default : f1); // COMPLIANT // Debatable, but volatile const int* is assignable to const int* so its // considered risky - _Generic(l11, const volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l11, const volatile int * : f1, default : f1); // NON-COMPLIANT - _Generic(l12, int *: f1, default: f1); // NON-COMPLIANT - _Generic(l12, volatile int *: f1, default: f1); // COMPLIANT - _Generic(l12, const volatile int *: f1, default: f1); // NON-COMPLIANT - _Generic(l12, void *: f1, default: f1); // NON-COMPLIANT - _Generic(l12, const volatile void *: f1, default: f1); // NON-COMPLIANT + _Generic(l12, int * : f1, default : f1); // NON-COMPLIANT + _Generic(l12, volatile int * : f1, default : f1); // COMPLIANT + _Generic(l12, const volatile int * : f1, default : f1); // NON-COMPLIANT + _Generic(l12, void * : f1, default : f1); // NON-COMPLIANT + _Generic(l12, const volatile void * : f1, default : f1); // NON-COMPLIANT // Debatab12e, but volatile int* isn't assignable to const int* or vice versa. - _Generic(l12, const int *: f1, default: f1); // COMPLIANT + _Generic(l12, const int * : f1, default : f1); // COMPLIANT // Debatable, but volatile int* isn't assignable to const void* or vice versa. - _Generic(l12, const void *: f1, default: f1); // COMPLIANT - - _Generic(l13, int *: f1, default: f1); // NON-COMPLIANT - _Generic(l13, const int *: f1, default: f1); // NON-COMPLIANT - _Generic(l13, volatile int *: f1, default: f1); // NON-COMPLIANT - _Generic(l13, const volatile int *: f1, default: f1); // COMPLIANT - _Generic(l13, void *: f1, default: f1); // NON-COMPLIANT - _Generic(l13, const void *: f1, default: f1); // NON-COMPLIANT - _Generic(l13, const volatile void *: f1, default: f1); // NON-COMPLIANT - - _Generic(l14, int *: f1, default: f1); // COMPLIANT - _Generic(l14, const int *: f1, default: f1); // NON-COMPLIANT - _Generic(l14, volatile int *: f1, default: f1); // NON-COMPLIANT - _Generic(l14, const volatile int *: f1, default: f1); // NON-COMPLIANT - _Generic(l14, void *: f1, default: f1); // NON-COMPLIANT - _Generic(l14, const void *: f1, default: f1); // NON-COMPLIANT - _Generic(l14, const volatile void *: f1, default: f1); // NON-COMPLIANT - - _Generic(l15, int *: f1, default: f1); // NON-COMPLIANT - _Generic(l15, const int *: f1, default: f1); // COMPLIANT - _Generic(l15, void *: f1, default: f1); // NON-COMPLIANT - _Generic(l15, const void *: f1, default: f1); // NON-COMPLIANT - _Generic(l15, const volatile void *: f1, default: f1); // NON-COMPLIANT + _Generic(l12, const void * : f1, default : f1); // COMPLIANT + + _Generic(l13, int * : f1, default : f1); // NON-COMPLIANT + _Generic(l13, const int * : f1, default : f1); // NON-COMPLIANT + _Generic(l13, volatile int * : f1, default : f1); // NON-COMPLIANT + _Generic(l13, const volatile int * : f1, default : f1); // COMPLIANT + _Generic(l13, void * : f1, default : f1); // NON-COMPLIANT + _Generic(l13, const void * : f1, default : f1); // NON-COMPLIANT + _Generic(l13, const volatile void * : f1, default : f1); // NON-COMPLIANT + + _Generic(l14, int * : f1, default : f1); // COMPLIANT + _Generic(l14, const int * : f1, default : f1); // NON-COMPLIANT + _Generic(l14, volatile int * : f1, default : f1); // NON-COMPLIANT + _Generic(l14, const volatile int * : f1, default : f1); // NON-COMPLIANT + _Generic(l14, void * : f1, default : f1); // NON-COMPLIANT + _Generic(l14, const void * : f1, default : f1); // NON-COMPLIANT + _Generic(l14, const volatile void * : f1, default : f1); // NON-COMPLIANT + + _Generic(l15, int * : f1, default : f1); // NON-COMPLIANT + _Generic(l15, const int * : f1, default : f1); // COMPLIANT + _Generic(l15, void * : f1, default : f1); // NON-COMPLIANT + _Generic(l15, const void * : f1, default : f1); // NON-COMPLIANT + _Generic(l15, const volatile void * : f1, default : f1); // NON-COMPLIANT // Obviously not volatile: - _Generic(l15, volatile int *: f1, default: f1); // COMPLIANT + _Generic(l15, volatile int * : f1, default : f1); // COMPLIANT // Debatable, but volatile const int* is assignable to const int* so its // considered risky - _Generic(l15, const volatile int *: f1, default: f1); // NON-COMPLIANT + _Generic(l15, const volatile int * : f1, default : f1); // NON-COMPLIANT /** * Edge case 2: Types don't have to be identical to be compatible. @@ -177,18 +177,19 @@ void f2() { int(*l16)[3]; // This is a risky conversion that should be reported: - _Generic(l16, int(*const)[3]: f1, default: f1); // NON-COMPLIANT + _Generic(l16, int(*const)[3] : f1, default : f1); // NON-COMPLIANT // However, in this one, there is a match on the second selector, because it // it is an array type with a compatible element type, and sizes only have to // match if both arrays have a constant size. Therefore, the default selector // is not chosen and this is not a violation. - _Generic(l16, int(*const)[3]: f1, int(*)[]: f1, default: f1); // COMPLIANT + _Generic(l16, int(*const)[3] : f1, int(*)[] : f1, default : f1); // COMPLIANT // In this case, the second selector is not a compatible type because the // array has a constant size that doesn't match, and this should be reported. - _Generic(l16, - int(*const)[3]: f1, - int(*)[4]: f1, - default: f1); // NON-COMPLIANT + _Generic(l16, int(*const)[3] + : f1, int(*)[4] + : f1, + default + : f1); // NON-COMPLIANT /** * Edge case 3: Conversion on _Generic, make sure we use the fully converted @@ -196,10 +197,10 @@ void f2() { */ int *l17; void *l18; - _Generic((void *)l17, void *: f1, default: f1); // COMPLIANT - _Generic((void *)l17, int *: f1, default: f1); // NON-COMPLIANT - _Generic((int *)l18, void *: f1, default: f1); // NON-COMPLIANT - _Generic((int *)l18, int *: f1, default: f1); // COMPLIANT + _Generic((void *)l17, void * : f1, default : f1); // COMPLIANT + _Generic((void *)l17, int * : f1, default : f1); // NON-COMPLIANT + _Generic((int *)l18, void * : f1, default : f1); // NON-COMPLIANT + _Generic((int *)l18, int * : f1, default : f1); // COMPLIANT /** * Edge case 4: Typedefs must be resolved properly. @@ -210,27 +211,27 @@ void f2() { c_int_t *l20; volatile c_int_t *l21; - _Generic(l2, int *: f1, default: f1); // COMPLIANT - _Generic(l2, int_t *: f1, default: f1); // COMPLIANT - _Generic(l2, const int *: f1, default: f1); // NON-COMPLIANT - _Generic(l2, const int_t *: f1, default: f1); // NON-COMPLIANT - _Generic(l2, c_int_t *: f1, default: f1); // NON-COMPLIANT - - _Generic(l19, int *: f1, default: f1); // COMPLIANT - _Generic(l19, int_t *: f1, default: f1); // COMPLIANT - _Generic(l19, const int *: f1, default: f1); // NON-COMPLIANT - _Generic(l19, const int_t *: f1, default: f1); // NON-COMPLIANT - _Generic(l19, c_int_t *: f1, default: f1); // NON-COMPLIANT - - _Generic(l3, int *: f1, default: f1); // NON-COMPLIANT - _Generic(l3, int_t *: f1, default: f1); // NON-COMPLIANT - _Generic(l3, const int *: f1, default: f1); // COMPLIANT - _Generic(l3, const int_t *: f1, default: f1); // COMPLIANT - _Generic(l3, c_int_t *: f1, default: f1); // COMPLIANT - - _Generic(l20, int *: f1, default: f1); // NON-COMPLIANT - _Generic(l20, int_t *: f1, default: f1); // NON-COMPLIANT - _Generic(l20, const int *: f1, default: f1); // COMPLIANT - _Generic(l20, const int_t *: f1, default: f1); // COMPLIANT - _Generic(l20, c_int_t *: f1, default: f1); // COMPLIANT + _Generic(l2, int * : f1, default : f1); // COMPLIANT + _Generic(l2, int_t * : f1, default : f1); // COMPLIANT + _Generic(l2, const int * : f1, default : f1); // NON-COMPLIANT + _Generic(l2, const int_t * : f1, default : f1); // NON-COMPLIANT + _Generic(l2, c_int_t * : f1, default : f1); // NON-COMPLIANT + + _Generic(l19, int * : f1, default : f1); // COMPLIANT + _Generic(l19, int_t * : f1, default : f1); // COMPLIANT + _Generic(l19, const int * : f1, default : f1); // NON-COMPLIANT + _Generic(l19, const int_t * : f1, default : f1); // NON-COMPLIANT + _Generic(l19, c_int_t * : f1, default : f1); // NON-COMPLIANT + + _Generic(l3, int * : f1, default : f1); // NON-COMPLIANT + _Generic(l3, int_t * : f1, default : f1); // NON-COMPLIANT + _Generic(l3, const int * : f1, default : f1); // COMPLIANT + _Generic(l3, const int_t * : f1, default : f1); // COMPLIANT + _Generic(l3, c_int_t * : f1, default : f1); // COMPLIANT + + _Generic(l20, int * : f1, default : f1); // NON-COMPLIANT + _Generic(l20, int_t * : f1, default : f1); // NON-COMPLIANT + _Generic(l20, const int * : f1, default : f1); // COMPLIANT + _Generic(l20, const int_t * : f1, default : f1); // COMPLIANT + _Generic(l20, c_int_t * : f1, default : f1); // COMPLIANT } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-6/test.c b/c/misra/test/rules/RULE-23-6/test.c index 7d59c1e199..2b18f4cd2c 100644 --- a/c/misra/test/rules/RULE-23-6/test.c +++ b/c/misra/test/rules/RULE-23-6/test.c @@ -3,21 +3,21 @@ int l2; long l3; enum { E1 } l4; -#define M1(X) _Generic((X), int: 1, unsigned int: 1, short: 2, long: 3) +#define M1(X) _Generic((X), int : 1, unsigned int : 1, short : 2, long : 3) void f1() { M1(l1); // COMPLIANT M1(l2); // COMPLIANT M1(l3); // COMPLIANT M1(l4); // NON-COMPLIANT - M1(1); // COMPLIANT - M1(1u); // COMPLIANT - M1(l1 + l1); // NON-COMPLIANT - M1((int)(l1 + l1)); // COMPLIANT - M1('c'); // NON-COMPLIANT[false negative] - _Generic('c', int: 1); // NON-COMPLIANT - _Generic(_Generic(0, default: l1 + l1), default: 1); // NON-COMPLIANT - _Generic(((short)_Generic(0, default: (l1 + l1))), default: 1); // COMPLIANT + M1(1); // COMPLIANT + M1(1u); // COMPLIANT + M1(l1 + l1); // NON-COMPLIANT + M1((int)(l1 + l1)); // COMPLIANT + M1('c'); // NON-COMPLIANT[false negative] + _Generic('c', int : 1); // NON-COMPLIANT + _Generic(_Generic(0, default : l1 + l1), default : 1); // NON-COMPLIANT + _Generic(((short)_Generic(0, default : (l1 + l1))), default : 1); // COMPLIANT } void f2() { @@ -29,5 +29,5 @@ void f2() { struct S1 { int m1; }; - _Generic((const struct S1){.m1 = 0}, default: 1); + _Generic((const struct S1){.m1 = 0}, default : 1); } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-7/test.c b/c/misra/test/rules/RULE-23-7/test.c index 41a5d6ab6c..e2f5e98ee5 100644 --- a/c/misra/test/rules/RULE-23-7/test.c +++ b/c/misra/test/rules/RULE-23-7/test.c @@ -2,59 +2,60 @@ int f1(int p1); int f2(int p1, int p2); // COMPLIANT -- standard correct cases: -#define M1(X) _Generic((X), int: f1, default: f1)(X) -#define M2(X) _Generic((X), int: f1(X), default: f1(X)) +#define M1(X) _Generic((X), int : f1, default : f1)(X) +#define M2(X) _Generic((X), int : f1(X), default : f1(X)) // NON-COMPLIANT -- standard incorrect cases: -#define M3(X) _Generic((X), int: f1(X), default: 0) -#define M4(X) (X) + _Generic((X), int: f1(X), default: f1(X)) -#define M5(X) _Generic((X), int: f1(X), default: f1(X)) + (X) -#define M6(X) _Generic((X), int: f1((X) + (X)), default: f1(X)) +#define M3(X) _Generic((X), int : f1(X), default : 0) +#define M4(X) (X) + _Generic((X), int : f1(X), default : f1(X)) +#define M5(X) _Generic((X), int : f1(X), default : f1(X)) + (X) +#define M6(X) _Generic((X), int : f1((X) + (X)), default : f1(X)) // Compliant by exception // COMPLIANT -#define M7(X) _Generic((X), int: 1, default: 0) +#define M7(X) _Generic((X), int : 1, default : 0) // NON-COMPLIANT[FALSE NEGATIVE] -- Without an expansion, we can't tell if this // macro has only constant expressions or not. -#define M8(X) _Generic((X), int: f1(1)) +#define M8(X) _Generic((X), int : f1(1)) // NON-COMPLIANT -- If the macro is expanded we can detect constant expressions -#define M9(X) _Generic((X), int: f1) +#define M9(X) _Generic((X), int : f1) // NON-COMPLIANT -- If the macro is expanded we can detect constant expressions -#define M10(X) _Generic((X), int: f1(1)) +#define M10(X) _Generic((X), int : f1(1)) void f3() { M9(1); M10(1); } // COMPLIANT -- multiple uses in the controlling expression is OK: -#define M11(X) _Generic((X) + (X), int: f1(X), default: f1(X)) +#define M11(X) _Generic((X) + (X), int : f1(X), default : f1(X)) // NON-COMPLIANT -- the rule should still be enforced otherwise: -#define M12(X) _Generic((X) + (X), int: f1(X), default: 1) -#define M13(X) _Generic((X) + (X), int: f1(X), default: f1(X)) + (X) +#define M12(X) _Generic((X) + (X), int : f1(X), default : 1) +#define M13(X) _Generic((X) + (X), int : f1(X), default : f1(X)) + (X) // COMPLIANT -- the argument is not used in the controlling expression: -#define M14(X) _Generic(1, int: f1((X) + (X)), default: f1(X)) -#define M15(X) _Generic(1, int: f1(X), default: f1(X)) + (X) +#define M14(X) _Generic(1, int : f1((X) + (X)), default : f1(X)) +#define M15(X) _Generic(1, int : f1(X), default : f1(X)) + (X) // Test cases with more than one argument: // COMPLIANT -- Y is not used in the controlling expression: -#define M16(X, Y) _Generic((X), int: f2((X), (Y)), default: f2((X), 1)) +#define M16(X, Y) _Generic((X), int : f2((X), (Y)), default : f2((X), 1)) // NON-COMPLIANT -- Y is used in the controlling expression -#define M17(X, Y) _Generic((X) + (Y), int: f2((X), (Y)), default: f2((X), 1)) +#define M17(X, Y) _Generic((X) + (Y), int : f2((X), (Y)), default : f2((X), 1)) // COMPLIANT -- Y is used in the controlling expression correctly -#define M18(X, Y) _Generic((X) + (Y), int: f2((X), (Y)), default: f2((X), (Y))) +#define M18(X, Y) \ + _Generic((X) + (Y), int : f2((X), (Y)), default : f2((X), (Y))) // Test unevaluated contexts: // COMPLIANT -- sizeof is not evaluated: -#define M19(X) _Generic((X), int[sizeof(X)]: f1, default: f1)(X) -#define M20(X) _Generic((X), int: f1(sizeof(X)), default: f1)(X) -#define M21(X) _Generic((X), int: f1(X), default: f1(X)) + sizeof(X) +#define M19(X) _Generic((X), int[sizeof(X)] : f1, default : f1)(X) +#define M20(X) _Generic((X), int : f1(sizeof(X)), default : f1)(X) +#define M21(X) _Generic((X), int : f1(X), default : f1(X)) + sizeof(X) // NON-COMPLIANT[FALSE NEGATIVE] -- sizeof plus evaluated context -#define M22(X) _Generic((X), int: f1(sizeof(X) + X), default: f1(X))(X) +#define M22(X) _Generic((X), int : f1(sizeof(X) + X), default : f1(X))(X) // NON-COMPLIANT[FALSE NEGATIVE] -- array type sizes may be evaluated -#define M23(X) _Generic((X), int[X]: f1, default: f1)(X) +#define M23(X) _Generic((X), int[X] : f1, default : f1)(X) // COMPLIANT -- alignof, typeof are not evaluated: -#define M24(X) _Generic((X), int[X]: f1, default: f1)(X) +#define M24(X) _Generic((X), int[X] : f1, default : f1)(X) // Nested macros: #define ONCE(X) (X) @@ -64,8 +65,8 @@ void f3() { // COMPLIANT #define M25(X) _Generic((X), int: ONCE(f1(X)), default: ONCE(f1(X)) // COMPLIANT[FALSE POSITIVE] -#define M26(X) _Generic((X), int: IGNORE_2ND(X, X), default: IGNORE_2ND(X, X)) -#define M27(X) _Generic((X), int: f1(IGNORE(X)), default: f1(IGNORE(X)))(X) +#define M26(X) _Generic((X), int : IGNORE_2ND(X, X), default : IGNORE_2ND(X, X)) +#define M27(X) _Generic((X), int : f1(IGNORE(X)), default : f1(IGNORE(X)))(X) // NON-COMPLIANT[FASE NEGATIVE] -#define M28(X) _Generic((X), int: f1(IGNORE(X)), default: f1(IGNORE(X))) -#define M29(X) _Generic((X), int: TWICE(f1(X)), default: TWICE(f1(X))) \ No newline at end of file +#define M28(X) _Generic((X), int : f1(IGNORE(X)), default : f1(IGNORE(X))) +#define M29(X) _Generic((X), int : TWICE(f1(X)), default : TWICE(f1(X))) \ No newline at end of file diff --git a/c/misra/test/rules/RULE-23-8/test.c b/c/misra/test/rules/RULE-23-8/test.c index fdd6e66044..340ddb16db 100644 --- a/c/misra/test/rules/RULE-23-8/test.c +++ b/c/misra/test/rules/RULE-23-8/test.c @@ -2,21 +2,21 @@ * Cases where the macro itself is always compliant or non compliant: */ // COMPLIANT -#define M1(X) _Generic((X), int: 1, unsigned int: 2) +#define M1(X) _Generic((X), int : 1, unsigned int : 2) // COMPLIANT -#define M2(X) _Generic((X), int: 1, unsigned int: 2, default: 0) +#define M2(X) _Generic((X), int : 1, unsigned int : 2, default : 0) // COMPLIANT -#define M3(X) _Generic((X), default: 0, int: 1, unsigned int: 2) +#define M3(X) _Generic((X), default : 0, int : 1, unsigned int : 2) // NON-COMPLIANT -#define M4(X) _Generic((X), int: 1, default: 0, unsigned int: 2) +#define M4(X) _Generic((X), int : 1, default : 0, unsigned int : 2) /** * Macros that are compliant or not based on use: */ // NON-COMPLIANT: because every use is non compliant -#define M5(...) _Generic(0, __VA_ARGS__, default: 0, int: 1) +#define M5(...) _Generic(0, __VA_ARGS__, default : 0, int : 1) // COMPLIANT: because some uses are compliant -#define M6(...) _Generic(0, __VA_ARGS__, int: 1) +#define M6(...) _Generic(0, __VA_ARGS__, int : 1) void f1() { M1(0); // COMPLIANT @@ -42,8 +42,8 @@ void f1() { * RULE-23-1. */ void f2() { - _Generic(0, int: 1, unsigned int: 2); // COMPLIANT - _Generic(0, int: 1, unsigned int: 2, default: 0); // COMPLIANT - _Generic(0, default: 0, int: 1, unsigned int: 2); // COMPLIANT - _Generic(0, int: 1, default: 0, unsigned int: 2); // NON-COMPLIANT + _Generic(0, int : 1, unsigned int : 2); // COMPLIANT + _Generic(0, int : 1, unsigned int : 2, default : 0); // COMPLIANT + _Generic(0, default : 0, int : 1, unsigned int : 2); // COMPLIANT + _Generic(0, int : 1, default : 0, unsigned int : 2); // NON-COMPLIANT } \ No newline at end of file From b2aef27eb8227aabb772ff1da27c597a4678c169 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 9 Mar 2025 23:10:33 -0700 Subject: [PATCH 238/370] Format Type.qll --- cpp/common/src/codingstandards/cpp/Type.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/Type.qll b/cpp/common/src/codingstandards/cpp/Type.qll index 32c139fd89..052096559a 100644 --- a/cpp/common/src/codingstandards/cpp/Type.qll +++ b/cpp/common/src/codingstandards/cpp/Type.qll @@ -1,2 +1,2 @@ import codingstandards.cpp.types.Type -import codingstandards.cpp.types.Uses \ No newline at end of file +import codingstandards.cpp.types.Uses From 183100e621e5eb5c72ba36552d7111d14bdef32c Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 9 Mar 2025 23:10:44 -0700 Subject: [PATCH 239/370] Fix Generics.json package --- rule_packages/c/Generics.json | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/rule_packages/c/Generics.json b/rule_packages/c/Generics.json index 1183bdc709..02c7cb2364 100644 --- a/rule_packages/c/Generics.json +++ b/rule_packages/c/Generics.json @@ -52,9 +52,8 @@ } ], "implementation_scope": { - "items": [ + "description": "Due to limited information in the CodeQL database for macro argument expansions, this implementation reports generics not of the form `_Generic((X)` where all invocations of that generic contain a side effect in the controlling expression." - ] }, "title": "A generic selection that is not expanded from a macro shall not contain potential side effects in the controlling expression" }, @@ -138,9 +137,8 @@ } ], "implementation_scope": { - "items": [ + "description": "The CodeQL extractor will expand character literals passed into macros into integer literals, and therefore the essential type system for character literals will not necessarily be analyzed correctly." - ] }, "title": "The controlling expression of a generic selection shall have an essential type that matches its standard type" }, @@ -164,9 +162,8 @@ } ], "implementation_scope": { - "items": [ + "description": "Due to limited information in the CodeQL database for macro argument expansions, this implementation performs string matching on the macro parameters against the macro body to determine where parameters are expanded. If text indicating a nonevaluated context such as sizeof() or _Alignof() appear, there will be no positive result." - ] }, "title": "A generic selection that is expanded from a macro should evaluate its argument only once" }, @@ -176,7 +173,7 @@ }, "queries": [ { - "description": "A default association shall appear as either the first or the last association of a generic selection", + "description": "A default association shall appear as either the first or the last association of a generic selection.", "kind": "problem", "name": "A default association shall appear as either the first or the last association of a generic", "precision": "very-high", From 61b2852f614e0143f4af11abb99c8126ce43d033 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 9 Mar 2025 23:10:59 -0700 Subject: [PATCH 240/370] Fix DeduplicateMacroResults test --- .../DeduplicateMacroResults.expected | 14 +++++++------- .../cpp/alertreporting/DeduplicateMacroResults.ql | 6 ++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.expected b/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.expected index d9a7fe6a07..c273346e3b 100644 --- a/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.expected +++ b/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.expected @@ -1,7 +1,7 @@ -| deduplicatemacroresults.cpp:4:8:4:9 | definition of g1 | Findme var 'g1'. | deduplicatemacroresults.cpp:4:8:4:9 | deduplicatemacroresults.cpp:4:8:4:9 | (ignored) | -| deduplicatemacroresults.cpp:10:1:10:34 | SOMETIMES_HAS_RESULTS1(type,name) | Invocation of macro $@ has findme var 'g3'. | deduplicatemacroresults.cpp:6:1:6:52 | deduplicatemacroresults.cpp:6:1:6:52 | SOMETIMES_HAS_RESULTS1 | -| deduplicatemacroresults.cpp:13:1:13:34 | SOMETIMES_HAS_RESULTS2(type,name) | Invocation of macro $@ has findme var 'g5'. | deduplicatemacroresults.cpp:7:1:7:53 | deduplicatemacroresults.cpp:7:1:7:53 | SOMETIMES_HAS_RESULTS2 | -| deduplicatemacroresults.cpp:15:1:15:50 | #define ALWAYS_HAS_SAME_RESULT() extern findme g6; | Macro ALWAYS_HAS_SAME_RESULT always has findme var named g6 | deduplicatemacroresults.cpp:15:1:15:50 | deduplicatemacroresults.cpp:15:1:15:50 | (ignored) | -| deduplicatemacroresults.cpp:21:1:21:70 | #define ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(name) extern findme name; | Macro ALWAYS_HAS_RESULT_VARIED_DESCRIPTION always has findme var, for example '$@'. | deduplicatemacroresults.cpp:23:38:23:39 | deduplicatemacroresults.cpp:23:38:23:39 | g7 | -| deduplicatemacroresults.cpp:30:1:31:50 | #define OUTER_ALWAYS_HAS_SAME_RESULT() extern INNER_SOMETIMES_HAS_RESULTS(findme, g10); | Macro OUTER_ALWAYS_HAS_SAME_RESULT always has findme var named g10 | deduplicatemacroresults.cpp:30:1:31:50 | deduplicatemacroresults.cpp:30:1:31:50 | (ignored) | -| deduplicatemacroresults.cpp:37:1:38:52 | #define OUTER_ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(name) INNER_SOMETIMES_HAS_RESULTS(findme, name ## suffix); | Macro OUTER_ALWAYS_HAS_RESULT_VARIED_DESCRIPTION always has findme var, for example '$@'. | deduplicatemacroresults.cpp:40:44:40:47 | deduplicatemacroresults.cpp:40:44:40:47 | g11suffix | +| deduplicatemacroresults.cpp:4:8:4:9 | definition of g1 | Findme var 'g1'. | deduplicatemacroresults.cpp:4:8:4:9 | definition of g1 | | +| deduplicatemacroresults.cpp:10:1:10:34 | SOMETIMES_HAS_RESULTS1(type,name) | Invocation of macro $@ has findme var 'g3'. | deduplicatemacroresults.cpp:6:1:6:52 | #define SOMETIMES_HAS_RESULTS1(type,name) type name | SOMETIMES_HAS_RESULTS1 | +| deduplicatemacroresults.cpp:13:1:13:34 | SOMETIMES_HAS_RESULTS2(type,name) | Invocation of macro $@ has findme var 'g5'. | deduplicatemacroresults.cpp:7:1:7:53 | #define SOMETIMES_HAS_RESULTS2(type,name) type name; | SOMETIMES_HAS_RESULTS2 | +| deduplicatemacroresults.cpp:15:1:15:50 | #define ALWAYS_HAS_SAME_RESULT() extern findme g6; | Macro ALWAYS_HAS_SAME_RESULT always has findme var named g6 | deduplicatemacroresults.cpp:15:1:15:50 | #define ALWAYS_HAS_SAME_RESULT() extern findme g6; | (ignored) | +| deduplicatemacroresults.cpp:21:1:21:70 | #define ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(name) extern findme name; | Macro ALWAYS_HAS_RESULT_VARIED_DESCRIPTION always has findme var, for example '$@'. | deduplicatemacroresults.cpp:23:38:23:39 | declaration of g7 | g7 | +| deduplicatemacroresults.cpp:30:1:31:50 | #define OUTER_ALWAYS_HAS_SAME_RESULT() extern INNER_SOMETIMES_HAS_RESULTS(findme, g10); | Macro OUTER_ALWAYS_HAS_SAME_RESULT always has findme var named g10 | deduplicatemacroresults.cpp:30:1:31:50 | #define OUTER_ALWAYS_HAS_SAME_RESULT() extern INNER_SOMETIMES_HAS_RESULTS(findme, g10); | (ignored) | +| deduplicatemacroresults.cpp:37:1:38:52 | #define OUTER_ALWAYS_HAS_RESULT_VARIED_DESCRIPTION(name) INNER_SOMETIMES_HAS_RESULTS(findme, name ## suffix); | Macro OUTER_ALWAYS_HAS_RESULT_VARIED_DESCRIPTION always has findme var, for example '$@'. | deduplicatemacroresults.cpp:40:44:40:47 | definition of g11suffix | g11suffix | diff --git a/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.ql b/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.ql index 3c9f2fc345..68cfc9a78f 100644 --- a/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.ql +++ b/cpp/common/test/library/codingstandards/cpp/alertreporting/DeduplicateMacroResults.ql @@ -23,12 +23,14 @@ module FindMeReportConfig implements MacroReportConfigSig { result = "Invocation of macro $@ has findme var '" + f.getName() + "'." } - string getMessageNotInMacro(FindMe f) { result = "Findme var '" + f.getName() + "'." } + string getMessageNotInMacro(FindMe f, Locatable extra, string extraString) { + result = "Findme var '" + f.getName() + "'." and extra = f and extraString = "" + } } import DeduplicateMacroResults import DeduplicateMacroResults::Report from ReportResult report -select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocation(), +select report.getPrimaryElement(), report.getMessage(), report.getOptionalPlaceholderLocatable(), report.getOptionalPlaceholderMessage() From 30748787907f4ac2ccf2042f2adec6417bb87f92 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 9 Mar 2025 23:17:48 -0700 Subject: [PATCH 241/370] Fix query formats --- c/common/src/codingstandards/c/Generic.qll | 11 +++-------- .../GenericSelectionNotExpandedFromAMacro.ql | 6 ++---- .../GenericSelectionNotFromMacroWithSideEffects.ql | 2 +- .../GenericWithoutNonDefaultAssociation.ql | 3 ++- .../GenericAssociationWithUnselectableType.ql | 4 ++-- .../GenericExpressionWithIncorrectEssentialType.ql | 6 +++--- .../DefaultGenericSelectionNotFirstOrLast.ql | 9 ++++++--- .../DeclarationsOfAFunctionSameNameAndType.ql | 14 +++++++++----- .../DeclarationsOfAnObjectSameNameAndType.ql | 4 ++-- 9 files changed, 30 insertions(+), 29 deletions(-) diff --git a/c/common/src/codingstandards/c/Generic.qll b/c/common/src/codingstandards/c/Generic.qll index 1bf4282017..784c16778e 100644 --- a/c/common/src/codingstandards/c/Generic.qll +++ b/c/common/src/codingstandards/c/Generic.qll @@ -10,7 +10,6 @@ string deparenthesize(string input) { result = input.substring(1, input.length() - 1) } - class GenericMacro extends Macro { string ctrlExpr; @@ -61,9 +60,7 @@ class ParsedGenericMacro extends Macro { ) } - string getAParameter() { - result = this.(FunctionLikeMacro).getAParameter() - } + string getAParameter() { result = this.(FunctionLikeMacro).getAParameter() } int getAParsedGenericCommaSeparatorOffset() { exists(ParsedText text | @@ -118,9 +115,7 @@ class ParsedGenericMacro extends Macro { ) } - string getControllingExprString() { - result = getSelectionString(1) - } + string getControllingExprString() { result = getSelectionString(1) } bindingset[str, word] private int countWordInString(string word, string str) { @@ -152,4 +147,4 @@ class ParsedGenericMacro extends Macro { not idx = 0 and result = expansionsInsideSelection(parameter, idx + 1) } -} \ No newline at end of file +} diff --git a/c/misra/src/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.ql b/c/misra/src/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.ql index ef2a2e75c5..540804ffc4 100644 --- a/c/misra/src/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.ql +++ b/c/misra/src/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.ql @@ -18,8 +18,6 @@ from C11GenericExpr generic, Expr ctrlExpr where not isExcluded(generic, GenericsPackage::genericSelectionNotExpandedFromAMacroQuery()) and ctrlExpr = generic.getControllingExpr() and - not exists(MacroInvocation mi | - mi.getAGeneratedElement() = generic.getExpr() - ) + not exists(MacroInvocation mi | mi.getAGeneratedElement() = generic.getExpr()) select generic, "Generic expression with controlling expression $@ is not expanded froma macro", -ctrlExpr, ctrlExpr.toString() + ctrlExpr, ctrlExpr.toString() diff --git a/c/misra/src/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.ql b/c/misra/src/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.ql index 3ec53a08bf..4b1a2d26c3 100644 --- a/c/misra/src/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.ql +++ b/c/misra/src/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.ql @@ -84,4 +84,4 @@ where not isExcluded(res.getPrimaryElement(), GenericsPackage::genericSelectionNotFromMacroWithSideEffectsQuery()) select res.getPrimaryElement(), res.getMessage(), res.getOptionalPlaceholderLocatable(), - res.getOptionalPlaceholderMessage() \ No newline at end of file + res.getOptionalPlaceholderMessage() diff --git a/c/misra/src/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.ql b/c/misra/src/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.ql index f3a0227022..bb2d57a714 100644 --- a/c/misra/src/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.ql +++ b/c/misra/src/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.ql @@ -31,5 +31,6 @@ where not exists(Type t | t = generic.getAnAssociationType() and not t instanceof VoidType - ) and primaryElement = MacroUnwrapper::unwrapElement(generic) + ) and + primaryElement = MacroUnwrapper::unwrapElement(generic) select primaryElement, "Generic selection contains no non-default association." diff --git a/c/misra/src/rules/RULE-23-4/GenericAssociationWithUnselectableType.ql b/c/misra/src/rules/RULE-23-4/GenericAssociationWithUnselectableType.ql index e8ed88f757..2d707548fa 100644 --- a/c/misra/src/rules/RULE-23-4/GenericAssociationWithUnselectableType.ql +++ b/c/misra/src/rules/RULE-23-4/GenericAssociationWithUnselectableType.ql @@ -20,10 +20,10 @@ import codingstandards.cpp.alertreporting.DeduplicateMacroResults /** * Check if a type contains an unmatchable anonymous struct or union. - * + * * Anonymous structs and unions are only equal to themselves. So any anonymous struct, or compound * type containing an anonymous struct, is unmatchable. - * + * * However, there is an exception if the anonymous struct is behind a typedef. All uses of that * typedef will resolve to the same anonymous struct, and so the typedef is matchable. */ diff --git a/c/misra/src/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.ql b/c/misra/src/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.ql index c27ce3dc55..6bf93947d8 100644 --- a/c/misra/src/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.ql +++ b/c/misra/src/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.ql @@ -57,6 +57,6 @@ where ) ) select generic, - "Controlling expression in generic " + extraMessage + - "has standard type " + ctrlType.toString() + ", which doesn't match its essential type " + - ctrlEssentialType.toString() + ".", extraElement, extraString \ No newline at end of file + "Controlling expression in generic " + extraMessage + "has standard type " + ctrlType.toString() + + ", which doesn't match its essential type " + ctrlEssentialType.toString() + ".", extraElement, + extraString diff --git a/c/misra/src/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.ql b/c/misra/src/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.ql index 04b12ac436..164ffffb1e 100644 --- a/c/misra/src/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.ql +++ b/c/misra/src/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.ql @@ -53,13 +53,15 @@ module GenericMisplacedDefaultReportConfig implements bindingset[description] string getMessageSameResultInAllExpansions(Macro m, string description) { result = - "Generic macro " + m.getName() + " has default as " + description + " association, which is not first or last." + "Generic macro " + m.getName() + " has default as " + description + + " association, which is not first or last." } /* Create a message to describe this macro, using '$@' to describe an example `ResultElement`. */ string getMessageVariedResultInAllExpansions(Macro m) { result = - "Generic macro " + m.getName() + " has a default association which is not first or last, for example $@." + "Generic macro " + m.getName() + + " has a default association which is not first or last, for example $@." } /** @@ -68,7 +70,8 @@ module GenericMisplacedDefaultReportConfig implements */ string getMessageResultInIsolatedExpansion(GenericWithMisplacedDefault element) { result = - "Generic macro $@, in this expansion, has default as " + describe(element) + " association, which is not first or last." + "Generic macro $@, in this expansion, has default as " + describe(element) + + " association, which is not first or last." } /** diff --git a/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql index a0d7c0c9ab..2de2e4fd0a 100644 --- a/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql +++ b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql @@ -25,15 +25,19 @@ where //return type check ( not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, f2) and - case = "return type" and pluralDo = "does" + case = "return type" and + pluralDo = "does" or //parameter type check not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, f2) and - case = "parameter types" and pluralDo = "do" + case = "parameter types" and + pluralDo = "do" or //parameter name check parameterNamesUnmatched(f1, f2) and - case = "parameter names" and pluralDo = "do" + case = "parameter names" and + pluralDo = "do" ) -select f1, "The " + case + " of re-declaration of $@ " + pluralDo + " not use the same type names as declaration $@", f1, - f1.getName(), f2, f2.getName() +select f1, + "The " + case + " of re-declaration of $@ " + pluralDo + + " not use the same type names as declaration $@", f1, f1.getName(), f2, f2.getName() diff --git a/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql b/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql index 83c67e2efa..12ff583b6b 100644 --- a/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql +++ b/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql @@ -52,5 +52,5 @@ where decl2.getType()) select decl1, "The object $@ of type " + decl1.getType().toString() + - " does not use the same type names as re-declaration $@ of type " + decl2.getType().toString(), decl1, - decl1.getName(), decl2, decl2.getName() + " does not use the same type names as re-declaration $@ of type " + decl2.getType().toString(), + decl1, decl1.getName(), decl2, decl2.getName() From f1ec355fc7d08bcf8f1cc05c1dc61d0d1a15f47a Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 9 Mar 2025 23:19:09 -0700 Subject: [PATCH 242/370] Fix query metadata --- .../RULE-23-6/GenericExpressionWithIncorrectEssentialType.ql | 4 +++- .../rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.ql | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/c/misra/src/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.ql b/c/misra/src/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.ql index 6bf93947d8..f02f92b45a 100644 --- a/c/misra/src/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.ql +++ b/c/misra/src/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.ql @@ -4,9 +4,11 @@ * @description The controlling expression of a generic selection shall have an essential type that * matches its standard type. * @kind problem - * @precision very-high + * @precision high * @problem.severity error * @tags external/misra/id/rule-23-6 + * correctness + * external/misra/c/2012/amendment3 * external/misra/obligation/required */ diff --git a/c/misra/src/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.ql b/c/misra/src/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.ql index 164ffffb1e..6e443bd162 100644 --- a/c/misra/src/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.ql +++ b/c/misra/src/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.ql @@ -2,7 +2,7 @@ * @id c/misra/default-generic-selection-not-first-or-last * @name RULE-23-8: A default association shall appear as either the first or the last association of a generic * @description A default association shall appear as either the first or the last association of a - * generic selection + * generic selection. * @kind problem * @precision very-high * @problem.severity warning From c8433d72c106e85a1a740942123a83791aeb439e Mon Sep 17 00:00:00 2001 From: knewbury01 Date: Tue, 11 Mar 2025 17:54:55 +0000 Subject: [PATCH 243/370] Bump version to 2.43.0-dev --- c/cert/src/qlpack.yml | 2 +- c/cert/test/qlpack.yml | 2 +- c/common/src/qlpack.yml | 2 +- c/common/test/qlpack.yml | 2 +- c/misra/src/qlpack.yml | 2 +- c/misra/test/qlpack.yml | 2 +- cpp/autosar/src/qlpack.yml | 2 +- cpp/autosar/test/qlpack.yml | 2 +- cpp/cert/src/qlpack.yml | 2 +- cpp/cert/test/qlpack.yml | 2 +- cpp/common/src/qlpack.yml | 2 +- cpp/common/test/qlpack.yml | 2 +- cpp/misra/src/qlpack.yml | 2 +- cpp/misra/test/qlpack.yml | 2 +- cpp/report/src/qlpack.yml | 2 +- docs/user_manual.md | 12 ++++++------ 16 files changed, 21 insertions(+), 21 deletions(-) diff --git a/c/cert/src/qlpack.yml b/c/cert/src/qlpack.yml index 6e023bc238..8498e9447d 100644 --- a/c/cert/src/qlpack.yml +++ b/c/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards -version: 2.42.0-dev +version: 2.43.0-dev description: CERT C 2016 suites: codeql-suites license: MIT diff --git a/c/cert/test/qlpack.yml b/c/cert/test/qlpack.yml index 98d9895612..2b44a05fdf 100644 --- a/c/cert/test/qlpack.yml +++ b/c/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards-tests -version: 2.42.0-dev +version: 2.43.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/common/src/qlpack.yml b/c/common/src/qlpack.yml index 9188ad8bda..685a3a0144 100644 --- a/c/common/src/qlpack.yml +++ b/c/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards -version: 2.42.0-dev +version: 2.43.0-dev license: MIT dependencies: codeql/common-cpp-coding-standards: '*' diff --git a/c/common/test/qlpack.yml b/c/common/test/qlpack.yml index f76badccfc..8f8486949b 100644 --- a/c/common/test/qlpack.yml +++ b/c/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards-tests -version: 2.42.0-dev +version: 2.43.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/misra/src/qlpack.yml b/c/misra/src/qlpack.yml index 721a052e6b..5b8b1fc0b2 100644 --- a/c/misra/src/qlpack.yml +++ b/c/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards -version: 2.42.0-dev +version: 2.43.0-dev description: MISRA C 2012 suites: codeql-suites license: MIT diff --git a/c/misra/test/qlpack.yml b/c/misra/test/qlpack.yml index bf45171e18..aa5c5d86ae 100644 --- a/c/misra/test/qlpack.yml +++ b/c/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards-tests -version: 2.42.0-dev +version: 2.43.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/autosar/src/qlpack.yml b/cpp/autosar/src/qlpack.yml index e4d17b7309..1116e9534d 100644 --- a/cpp/autosar/src/qlpack.yml +++ b/cpp/autosar/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards -version: 2.42.0-dev +version: 2.43.0-dev description: AUTOSAR C++14 Guidelines R22-11, R21-11, R20-11, R19-11 and R19-03 suites: codeql-suites license: MIT diff --git a/cpp/autosar/test/qlpack.yml b/cpp/autosar/test/qlpack.yml index a1c802fec5..d540b01a32 100644 --- a/cpp/autosar/test/qlpack.yml +++ b/cpp/autosar/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards-tests -version: 2.42.0-dev +version: 2.43.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/cert/src/qlpack.yml b/cpp/cert/src/qlpack.yml index b0645353f6..89b5196f23 100644 --- a/cpp/cert/src/qlpack.yml +++ b/cpp/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards -version: 2.42.0-dev +version: 2.43.0-dev description: CERT C++ 2016 suites: codeql-suites license: MIT diff --git a/cpp/cert/test/qlpack.yml b/cpp/cert/test/qlpack.yml index 9c49caac9f..ceedca4647 100644 --- a/cpp/cert/test/qlpack.yml +++ b/cpp/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards-tests -version: 2.42.0-dev +version: 2.43.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/common/src/qlpack.yml b/cpp/common/src/qlpack.yml index 4b4619e6b9..ce7e896ced 100644 --- a/cpp/common/src/qlpack.yml +++ b/cpp/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards -version: 2.42.0-dev +version: 2.43.0-dev license: MIT dependencies: codeql/cpp-all: 2.1.1 diff --git a/cpp/common/test/qlpack.yml b/cpp/common/test/qlpack.yml index a207965a5e..e2201b887e 100644 --- a/cpp/common/test/qlpack.yml +++ b/cpp/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards-tests -version: 2.42.0-dev +version: 2.43.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/misra/src/qlpack.yml b/cpp/misra/src/qlpack.yml index 2c8f21a82f..7c104631d1 100644 --- a/cpp/misra/src/qlpack.yml +++ b/cpp/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards -version: 2.42.0-dev +version: 2.43.0-dev description: MISRA C++ 2023 default-suite: codeql-suites/misra-cpp-default.qls license: MIT diff --git a/cpp/misra/test/qlpack.yml b/cpp/misra/test/qlpack.yml index d0bd3a8b5a..08bdda24eb 100644 --- a/cpp/misra/test/qlpack.yml +++ b/cpp/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards-tests -version: 2.42.0-dev +version: 2.43.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/report/src/qlpack.yml b/cpp/report/src/qlpack.yml index 3203133ffc..73a6e189a3 100644 --- a/cpp/report/src/qlpack.yml +++ b/cpp/report/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/report-cpp-coding-standards -version: 2.42.0-dev +version: 2.43.0-dev license: MIT dependencies: codeql/cpp-all: 2.1.1 diff --git a/docs/user_manual.md b/docs/user_manual.md index df3ce9a6b8..d7924a9fcd 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -34,14 +34,14 @@ ## Release information -This user manual documents release `2.42.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). +This user manual documents release `2.43.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). The release page documents the release notes and contains the following artifacts part of the release: - `coding-standards-codeql-packs-2.37.0-dev.zip`: CodeQL packs that can be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `code-scanning-cpp-query-pack-2.42.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `supported_rules_list_2.42.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. -- `supported_rules_list_2.42.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. -- `user_manual_2.42.0-dev.md`: This user manual. +- `code-scanning-cpp-query-pack-2.43.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. +- `supported_rules_list_2.43.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. +- `supported_rules_list_2.43.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. +- `user_manual_2.43.0-dev.md`: This user manual. - `Source Code (zip)`: A zip archive containing the contents of https://github.com/github/codeql-coding-standards - `Source Code (tar.gz)`: A GZip compressed tar archive containing the contents of https://github.com/github/codeql-coding-standards - `checksums.txt`: A text file containing sha256 checksums for the aforementioned artifacts. @@ -583,7 +583,7 @@ This section describes known failure modes for "CodeQL Coding Standards" and des | | Out of space | Less output. Some files may be only be partially analyzed, or not analyzed at all. | Error reported on the command line. | Increase space. If it remains an issue report space consumption issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False positives | More output. Results are reported which are not violations of the guidelines. | All reported results must be reviewed. | Report false positive issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False negatives | Less output. Violations of the guidelines are not reported. | Other validation and verification processes during software development should be used to complement the analysis performed by CodeQL Coding Standards. | Report false negative issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.42.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | +| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.43.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | | | Incorrect deviation record specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation records with a reason. Ensure that all deviation records are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Incorrect deviation permit specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation permits with a reason. Ensure that all deviation permits are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Unapproved use of a deviation record | Less output. Results for guideline violations are not reported. | Validate that the deviation record use is approved by verifying the approved-by attribute of the deviation record specification. | Ensure that each raised deviation record is approved by an independent approver through an auditable process. | From 63b8e77d7aa9954a503abc9708d0dc8e45314c71 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 11 Mar 2025 17:30:51 -0700 Subject: [PATCH 244/370] Use regexpFind instead of regexpMatch Otherwise we need to match the entire receiver. --- .../src/codingstandards/cpp/HardwareOrProtocolInterface.qll | 2 +- .../OrderingPredicateMustBeStrictlyWeak.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/autosar/src/codingstandards/cpp/HardwareOrProtocolInterface.qll b/cpp/autosar/src/codingstandards/cpp/HardwareOrProtocolInterface.qll index 410fa1292f..b0b20b82d9 100644 --- a/cpp/autosar/src/codingstandards/cpp/HardwareOrProtocolInterface.qll +++ b/cpp/autosar/src/codingstandards/cpp/HardwareOrProtocolInterface.qll @@ -5,7 +5,7 @@ abstract class HardwareOrProtocolInterfaceClass extends Class { } class HardwareOrProtocolInterfaceComment extends Comment { HardwareOrProtocolInterfaceComment() { - getContents().regexpMatch("(?m)^\\s*(//|\\*)\\s*@HardwareOrProtocolInterface\\s*$") + exists(getContents().regexpFind("(?m)^\\s*(//|\\*)\\s*@HardwareOrProtocolInterface\\s*$", _, _)) } } diff --git a/cpp/common/src/codingstandards/cpp/rules/orderingpredicatemustbestrictlyweak/OrderingPredicateMustBeStrictlyWeak.qll b/cpp/common/src/codingstandards/cpp/rules/orderingpredicatemustbestrictlyweak/OrderingPredicateMustBeStrictlyWeak.qll index 66563bb9ff..1e9c025e4d 100644 --- a/cpp/common/src/codingstandards/cpp/rules/orderingpredicatemustbestrictlyweak/OrderingPredicateMustBeStrictlyWeak.qll +++ b/cpp/common/src/codingstandards/cpp/rules/orderingpredicatemustbestrictlyweak/OrderingPredicateMustBeStrictlyWeak.qll @@ -16,7 +16,7 @@ Query getQuery() { result instanceof OrderingPredicateMustBeStrictlyWeakSharedQu class IsStrictlyWeaklyOrderedComment extends Comment { IsStrictlyWeaklyOrderedComment() { - getContents().regexpMatch("(?m)^\\s*(//|\\*)\\s*@IsStrictlyWeaklyOrdered\\s*$") + exists(getContents().regexpFind("(?m)^\\s*(//|\\*)\\s*@IsStrictlyWeaklyOrdered\\s*$", _, _)) } } From c73badfcc7697b291b05ffa1da41c6afe902d826 Mon Sep 17 00:00:00 2001 From: Luke Cartey <5377966+lcartey@users.noreply.github.com> Date: Wed, 12 Mar 2025 00:36:26 +0000 Subject: [PATCH 245/370] Update change_notes/2025-03-09-rule-8-7.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- change_notes/2025-03-09-rule-8-7.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change_notes/2025-03-09-rule-8-7.md b/change_notes/2025-03-09-rule-8-7.md index 5308c97ce3..3c3678ca6d 100644 --- a/change_notes/2025-03-09-rule-8-7.md +++ b/change_notes/2025-03-09-rule-8-7.md @@ -1,4 +1,4 @@ - `RULE-8-7` - `ShouldNotBeDefinedWithExternalLinkage.ql`: - - Remove false positives where the declation is not defined in the database. + - Remove false positives where the declaration is not defined in the database. - Remove false positives where the definition and reference are in different translation units. - Remove false positives where the reference occurs in a header file. \ No newline at end of file From ce45538a5a72d80440a2c36d2210790309c54995 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 11 Mar 2025 17:42:41 -0700 Subject: [PATCH 246/370] Reformat C test case --- c/misra/test/rules/RULE-8-7/test.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/c/misra/test/rules/RULE-8-7/test.c b/c/misra/test/rules/RULE-8-7/test.c index 591f15a2c4..3789a1d269 100644 --- a/c/misra/test/rules/RULE-8-7/test.c +++ b/c/misra/test/rules/RULE-8-7/test.c @@ -1,11 +1,11 @@ #include "test.h" int i = 0; int i1 = 0; -int i2; // NON_COMPLIANT - accessed one translation unit -void f1() {} // Definition -void f2() {} // Definition -static void f3() {}; // COMPLIANT - internal linkage -void f4() {} // Definition +int i2; // NON_COMPLIANT - accessed one translation unit +void f1() {} // Definition +void f2() {} // Definition +static void f3(){}; // COMPLIANT - internal linkage +void f4() {} // Definition void f() { i = 0; i1 = 0; From 076b1c4faa72573c0a5f1488049332e47ecfa29a Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 11 Mar 2025 18:15:17 -0700 Subject: [PATCH 247/370] Implement EssentialTypes2 package --- c/common/src/codingstandards/c/TgMath.qll | 68 ++++ .../TgMathArgumentWithInvalidEssentialType.ql | 47 +++ ...gMathArgumentsWithDifferingStandardType.ql | 65 ++++ ...hArgumentWithInvalidEssentialType.expected | 132 +++++++ ...MathArgumentWithInvalidEssentialType.qlref | 1 + c/misra/test/rules/RULE-21-22/test.c | 323 ++++++++++++++++++ ...rgumentsWithDifferingStandardType.expected | 139 ++++++++ ...thArgumentsWithDifferingStandardType.qlref | 1 + c/misra/test/rules/RULE-21-23/test.c | 288 ++++++++++++++++ .../cpp/exclusions/c/EssentialTypes2.qll | 44 +++ .../cpp/exclusions/c/RuleMetadata.qll | 3 + rule_packages/c/EssentialTypes2.json | 47 +++ 12 files changed, 1158 insertions(+) create mode 100644 c/common/src/codingstandards/c/TgMath.qll create mode 100644 c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql create mode 100644 c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql create mode 100644 c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected create mode 100644 c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.qlref create mode 100644 c/misra/test/rules/RULE-21-22/test.c create mode 100644 c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected create mode 100644 c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.qlref create mode 100644 c/misra/test/rules/RULE-21-23/test.c create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/c/EssentialTypes2.qll create mode 100644 rule_packages/c/EssentialTypes2.json diff --git a/c/common/src/codingstandards/c/TgMath.qll b/c/common/src/codingstandards/c/TgMath.qll new file mode 100644 index 0000000000..f5488194c6 --- /dev/null +++ b/c/common/src/codingstandards/c/TgMath.qll @@ -0,0 +1,68 @@ + +import cpp + +private string getATgMathMacroName(boolean allowComplex) { + allowComplex = true and + result = + [ + "acos", "acosh", "asin", "asinh", "atan", "atanh", "carg", "cimag", "conj", "cos", "cosh", + "cproj", "creal", "exp", "fabs", "log", "pow", "sin", "sinh", "sqrt", "tan", "tanh" + ] + or + allowComplex = false and + result = + [ + "atan2", "cbrt", "ceil", "copysign", "erf", "erfc", "exp2", "expm1", "fdim", "floor", "fma", + "fmax", "fmin", "fmod", "frexp", "hypot", "ilogb", "ldexp", "lgamma", "llrint", "llround", + "log10", "log1p", "log2", "logb", "lrint", "lround", "nearbyint", "nextafter", "nexttoward", + "remainder", "remquo", "rint", "round", "scalbn", "scalbln", "tgamma", "trunc", + ] +} + +private predicate hasOutputArgument(string macroName, int index) { + macroName = "frexp" and index = 1 + or + macroName = "remquo" and index = 2 +} + +class TgMathInvocation extends MacroInvocation { + Call call; + boolean allowComplex; + + TgMathInvocation() { + this.getMacro().getName() = getATgMathMacroName(allowComplex) and + call = getBestCallInExpansion(this) + } + + Expr getOperandArgument(int i) { + result = call.getArgument(i) + and not hasOutputArgument(call.getTarget().getName(), i) + } + + int getNumberOfOperandArguments() { + result = call.getNumberOfArguments() - count(int i | hasOutputArgument(getMacroName(), i)) + } + + Expr getAnOperandArgument() { + result = getOperandArgument(_) + } + + predicate allowsComplex() { + allowComplex = true + } +} + +private Call getACallInExpansion(MacroInvocation mi) { result = mi.getAnExpandedElement() } + +private Call getNameMatchedCallInExpansion(MacroInvocation mi) { + result = getACallInExpansion(mi) and result.getTarget().getName() = mi.getMacroName() +} + +private Call getBestCallInExpansion(MacroInvocation mi) { + count(getACallInExpansion(mi)) = 1 and result = getACallInExpansion(mi) + or + count(getNameMatchedCallInExpansion(mi)) = 1 and result = getNameMatchedCallInExpansion(mi) + or + count(getNameMatchedCallInExpansion(mi)) > 1 and + result = rank[1](Call c | c = getACallInExpansion(mi) | c order by c.getTarget().getName()) +} \ No newline at end of file diff --git a/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql b/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql new file mode 100644 index 0000000000..f06ca54979 --- /dev/null +++ b/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql @@ -0,0 +1,47 @@ +/** + * @id c/misra/tg-math-argument-with-invalid-essential-type + * @name RULE-21-22: All operand arguments to any type-generic macros in shall have an appropriate essential + * @description All operand arguments to any type-generic macros in shall have an + * appropriate essential type + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-21-22 + * correctness + * external/misra/c/2012/amendment3 + * external/misra/obligation/mandatory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.TgMath +import codingstandards.c.misra.EssentialTypes + +EssentialTypeCategory getAnAllowedEssentialTypeCategory(TgMathInvocation call) { + result = EssentiallySignedType() + or + result = EssentiallyUnsignedType() + or + result = EssentiallyFloatingType(Real()) + or + call.allowsComplex() and + result = EssentiallyFloatingType(Complex()) +} + +string getAllowedTypesString(TgMathInvocation call) { + if call.allowsComplex() + then result = "essentially signed, unsigned, or floating type" + else result = "essentially signed, unsigned, or real floating type" +} + +from TgMathInvocation call, Expr arg, int argIndex, Type type, EssentialTypeCategory category +where + not isExcluded(call, EssentialTypes2Package::tgMathArgumentWithInvalidEssentialTypeQuery()) and + arg = call.getOperandArgument(argIndex) and + type = getEssentialType(arg) and + category = getEssentialTypeCategory(type) and + not category = getAnAllowedEssentialTypeCategory(call) +select arg, + "Argument " + (argIndex + 1) + " provided to type-generic macro '" + call.getMacroName() + + "' has " + category.toString().toLowerCase() + ", which is not " + getAllowedTypesString(call) + + "." diff --git a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql new file mode 100644 index 0000000000..b6daf7bb6a --- /dev/null +++ b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql @@ -0,0 +1,65 @@ +/** + * @id c/misra/tg-math-arguments-with-differing-standard-type + * @name RULE-21-23: All operand arguments to any multi-argument type-generic macros in shall have the same + * @description All operand arguments to any multi-argument type-generic macros in shall + * have the same standard type + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-21-23 + * correctness + * external/misra/c/2012/amendment3 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.TgMath + +Expr getFullyExplicitlyConverted(Expr e) { + if e.hasExplicitConversion() + then result = getFullyExplicitlyConverted(e.getExplicitlyConverted()) + else result = e +} + +string argTypesString(TgMathInvocation call, int i) { + exists(string typeStr | + typeStr = getEffectiveStandardType(call.getOperandArgument(i)).toString() and + ( + i = 0 and result = typeStr + or + i > 0 and result = argTypesString(call, i - 1) + ", " + typeStr + ) + ) +} + +predicate promotes(Type type) { type.(IntegralType).getSize() < any(IntType t).getSize() } + +Type integerPromote(Type type) { + promotes(type) and result.(IntType).isSigned() + or + not promotes(type) and result = type +} + +Type canonicalize(Type type) { + if type instanceof IntegralType + then result = type.(IntegralType).getCanonicalArithmeticType() + else result = type +} + +Type getEffectiveStandardType(Expr e) { + result = + canonicalize(integerPromote(getFullyExplicitlyConverted(e).getType().stripTopLevelSpecifiers())) +} + +from TgMathInvocation call, Type firstType +where + not isExcluded(call, EssentialTypes2Package::tgMathArgumentsWithDifferingStandardTypeQuery()) and + firstType = getEffectiveStandardType(call.getAnOperandArgument()) and + not forall(Expr arg | arg = call.getAnOperandArgument() | + firstType = getEffectiveStandardType(arg) + ) +select call, + "Call to type-generic macro '" + call.getMacroName() + + "' has arguments with differing standard types (" + + argTypesString(call, call.getNumberOfOperandArguments() - 1) + ")." diff --git a/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected new file mode 100644 index 0000000000..7c30f68204 --- /dev/null +++ b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected @@ -0,0 +1,132 @@ +| test.c:29:7:29:7 | c | Argument 1 provided to type-generic macro 'cos' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:40:7:40:7 | e | Argument 1 provided to type-generic macro 'cos' has essentially enum type, which is not essentially signed, unsigned, or floating type. | +| test.c:41:7:41:7 | b | Argument 1 provided to type-generic macro 'cos' has essentially boolean type, which is not essentially signed, unsigned, or floating type. | +| test.c:156:8:156:8 | c | Argument 1 provided to type-generic macro 'acos' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:157:9:157:9 | c | Argument 1 provided to type-generic macro 'acosh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:158:8:158:8 | c | Argument 1 provided to type-generic macro 'asin' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:159:9:159:9 | c | Argument 1 provided to type-generic macro 'asinh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:160:9:160:9 | c | Argument 1 provided to type-generic macro 'atan2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:161:12:161:12 | c | Argument 2 provided to type-generic macro 'atan2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:162:9:162:9 | c | Argument 1 provided to type-generic macro 'atanh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:163:8:163:8 | c | Argument 1 provided to type-generic macro 'carg' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:164:8:164:8 | c | Argument 1 provided to type-generic macro 'ceil' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:165:9:165:9 | c | Argument 1 provided to type-generic macro 'cimag' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:166:8:166:8 | c | Argument 1 provided to type-generic macro 'conj' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:167:15:167:15 | c | Argument 2 provided to type-generic macro 'copysign' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:168:12:168:12 | c | Argument 1 provided to type-generic macro 'copysign' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:169:8:169:8 | c | Argument 1 provided to type-generic macro 'cosh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:170:9:170:9 | c | Argument 1 provided to type-generic macro 'cproj' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:171:9:171:9 | c | Argument 1 provided to type-generic macro 'creal' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:172:7:172:7 | c | Argument 1 provided to type-generic macro 'erf' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:173:8:173:8 | c | Argument 1 provided to type-generic macro 'erfc' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:174:7:174:7 | c | Argument 1 provided to type-generic macro 'exp' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:175:8:175:8 | c | Argument 1 provided to type-generic macro 'exp2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:176:9:176:9 | c | Argument 1 provided to type-generic macro 'expm1' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:177:8:177:8 | c | Argument 1 provided to type-generic macro 'fabs' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:178:8:178:8 | c | Argument 1 provided to type-generic macro 'fdim' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:179:11:179:11 | c | Argument 2 provided to type-generic macro 'fdim' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:180:9:180:9 | c | Argument 1 provided to type-generic macro 'floor' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:181:7:181:7 | c | Argument 1 provided to type-generic macro 'fma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:182:10:182:10 | c | Argument 2 provided to type-generic macro 'fma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:183:13:183:13 | c | Argument 3 provided to type-generic macro 'fma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:184:8:184:8 | c | Argument 1 provided to type-generic macro 'fmax' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:185:11:185:11 | c | Argument 2 provided to type-generic macro 'fmax' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:186:8:186:8 | c | Argument 1 provided to type-generic macro 'fmin' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:187:11:187:11 | c | Argument 2 provided to type-generic macro 'fmin' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:188:8:188:8 | c | Argument 1 provided to type-generic macro 'fmod' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:189:11:189:11 | c | Argument 2 provided to type-generic macro 'fmod' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:190:9:190:9 | c | Argument 1 provided to type-generic macro 'frexp' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:191:9:191:9 | c | Argument 1 provided to type-generic macro 'hypot' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:192:12:192:12 | c | Argument 2 provided to type-generic macro 'hypot' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:193:9:193:9 | c | Argument 1 provided to type-generic macro 'ilogb' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:194:9:194:9 | c | Argument 1 provided to type-generic macro 'ldexp' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:195:12:195:12 | c | Argument 2 provided to type-generic macro 'ldexp' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:196:10:196:10 | c | Argument 1 provided to type-generic macro 'lgamma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:197:10:197:10 | c | Argument 1 provided to type-generic macro 'llrint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:198:11:198:11 | c | Argument 1 provided to type-generic macro 'llround' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:199:7:199:7 | c | Argument 1 provided to type-generic macro 'log' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:200:9:200:9 | c | Argument 1 provided to type-generic macro 'log10' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:201:9:201:9 | c | Argument 1 provided to type-generic macro 'log1p' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:202:8:202:8 | c | Argument 1 provided to type-generic macro 'log2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:203:8:203:8 | c | Argument 1 provided to type-generic macro 'logb' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:204:9:204:9 | c | Argument 1 provided to type-generic macro 'lrint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:205:10:205:10 | c | Argument 1 provided to type-generic macro 'lround' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:206:13:206:13 | c | Argument 1 provided to type-generic macro 'nearbyint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:207:13:207:13 | c | Argument 1 provided to type-generic macro 'nextafter' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:208:16:208:16 | c | Argument 2 provided to type-generic macro 'nextafter' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:209:14:209:14 | c | Argument 1 provided to type-generic macro 'nexttoward' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:210:17:210:17 | c | Argument 2 provided to type-generic macro 'nexttoward' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:211:7:211:7 | c | Argument 1 provided to type-generic macro 'pow' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:212:10:212:10 | c | Argument 2 provided to type-generic macro 'pow' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:213:13:213:13 | c | Argument 1 provided to type-generic macro 'remainder' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:214:16:214:16 | c | Argument 2 provided to type-generic macro 'remainder' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:215:10:215:10 | c | Argument 1 provided to type-generic macro 'remquo' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:216:13:216:13 | c | Argument 2 provided to type-generic macro 'remquo' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:217:8:217:8 | c | Argument 1 provided to type-generic macro 'rint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:218:9:218:9 | c | Argument 1 provided to type-generic macro 'round' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:219:10:219:10 | c | Argument 1 provided to type-generic macro 'scalbn' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:220:13:220:13 | c | Argument 2 provided to type-generic macro 'scalbn' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:221:11:221:11 | c | Argument 1 provided to type-generic macro 'scalbln' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:222:14:222:14 | c | Argument 2 provided to type-generic macro 'scalbln' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:223:7:223:7 | c | Argument 1 provided to type-generic macro 'sin' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:224:8:224:8 | c | Argument 1 provided to type-generic macro 'sinh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:225:8:225:8 | c | Argument 1 provided to type-generic macro 'sqrt' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:226:7:226:7 | c | Argument 1 provided to type-generic macro 'tan' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:227:8:227:8 | c | Argument 1 provided to type-generic macro 'tanh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:228:10:228:10 | c | Argument 1 provided to type-generic macro 'tgamma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:229:9:229:9 | c | Argument 1 provided to type-generic macro 'trunc' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:239:9:239:10 | cf | Argument 1 provided to type-generic macro 'atan2' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:240:12:240:13 | cf | Argument 2 provided to type-generic macro 'atan2' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:243:8:243:9 | cf | Argument 1 provided to type-generic macro 'cbrt' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:244:8:244:9 | cf | Argument 1 provided to type-generic macro 'ceil' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:247:15:247:16 | cf | Argument 2 provided to type-generic macro 'copysign' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:248:12:248:13 | cf | Argument 1 provided to type-generic macro 'copysign' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:249:15:249:16 | cf | Argument 2 provided to type-generic macro 'copysign' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:254:7:254:8 | cf | Argument 1 provided to type-generic macro 'erf' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:255:8:255:9 | cf | Argument 1 provided to type-generic macro 'erfc' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:257:8:257:9 | cf | Argument 1 provided to type-generic macro 'exp2' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:258:9:258:10 | cf | Argument 1 provided to type-generic macro 'expm1' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:260:8:260:9 | cf | Argument 1 provided to type-generic macro 'fdim' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:261:11:261:12 | cf | Argument 2 provided to type-generic macro 'fdim' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:262:9:262:10 | cf | Argument 1 provided to type-generic macro 'floor' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:263:7:263:8 | cf | Argument 1 provided to type-generic macro 'fma' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:264:10:264:11 | cf | Argument 2 provided to type-generic macro 'fma' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:265:13:265:14 | cf | Argument 3 provided to type-generic macro 'fma' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:266:8:266:9 | cf | Argument 1 provided to type-generic macro 'fmax' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:267:11:267:12 | cf | Argument 2 provided to type-generic macro 'fmax' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:268:8:268:9 | cf | Argument 1 provided to type-generic macro 'fmin' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:269:11:269:12 | cf | Argument 2 provided to type-generic macro 'fmin' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:270:8:270:9 | cf | Argument 1 provided to type-generic macro 'fmod' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:271:11:271:12 | cf | Argument 2 provided to type-generic macro 'fmod' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:272:9:272:10 | cf | Argument 1 provided to type-generic macro 'frexp' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:273:9:273:10 | cf | Argument 1 provided to type-generic macro 'hypot' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:274:12:274:13 | cf | Argument 2 provided to type-generic macro 'hypot' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:275:9:275:10 | cf | Argument 1 provided to type-generic macro 'ilogb' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:276:9:276:10 | cf | Argument 1 provided to type-generic macro 'ldexp' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:277:12:277:13 | cf | Argument 2 provided to type-generic macro 'ldexp' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:278:10:278:11 | cf | Argument 1 provided to type-generic macro 'lgamma' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:279:10:279:11 | cf | Argument 1 provided to type-generic macro 'llrint' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:280:11:280:12 | cf | Argument 1 provided to type-generic macro 'llround' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:282:9:282:10 | cf | Argument 1 provided to type-generic macro 'log10' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:283:9:283:10 | cf | Argument 1 provided to type-generic macro 'log1p' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:284:8:284:9 | cf | Argument 1 provided to type-generic macro 'log2' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:285:8:285:9 | cf | Argument 1 provided to type-generic macro 'logb' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:286:9:286:10 | cf | Argument 1 provided to type-generic macro 'lrint' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:287:10:287:11 | cf | Argument 1 provided to type-generic macro 'lround' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:288:13:288:14 | cf | Argument 1 provided to type-generic macro 'nearbyint' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:289:13:289:14 | cf | Argument 1 provided to type-generic macro 'nextafter' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:290:16:290:17 | cf | Argument 2 provided to type-generic macro 'nextafter' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:291:14:291:15 | cf | Argument 1 provided to type-generic macro 'nexttoward' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:292:17:292:18 | cf | Argument 2 provided to type-generic macro 'nexttoward' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:294:13:294:14 | cf | Argument 1 provided to type-generic macro 'remainder' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:295:16:295:17 | cf | Argument 2 provided to type-generic macro 'remainder' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:296:10:296:11 | cf | Argument 1 provided to type-generic macro 'remquo' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:297:13:297:14 | cf | Argument 2 provided to type-generic macro 'remquo' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:298:8:298:9 | cf | Argument 1 provided to type-generic macro 'rint' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:299:9:299:10 | cf | Argument 1 provided to type-generic macro 'round' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:300:10:300:11 | cf | Argument 1 provided to type-generic macro 'scalbn' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:301:13:301:14 | cf | Argument 2 provided to type-generic macro 'scalbn' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:302:11:302:12 | cf | Argument 1 provided to type-generic macro 'scalbln' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:303:14:303:15 | cf | Argument 2 provided to type-generic macro 'scalbln' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:309:10:309:11 | cf | Argument 1 provided to type-generic macro 'tgamma' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:310:9:310:10 | cf | Argument 1 provided to type-generic macro 'trunc' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | diff --git a/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.qlref b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.qlref new file mode 100644 index 0000000000..cb7206db11 --- /dev/null +++ b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.qlref @@ -0,0 +1 @@ +rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-22/test.c b/c/misra/test/rules/RULE-21-22/test.c new file mode 100644 index 0000000000..cc456c17fb --- /dev/null +++ b/c/misra/test/rules/RULE-21-22/test.c @@ -0,0 +1,323 @@ +#include +#include +#include +#include + +void f1() { + int i = 0; + unsigned int ui = 0; + short s = 0; + unsigned short us = 0; + char c = 0; + unsigned char uc = 0; + signed char sc = 0; + long l = 0; + unsigned long ul = 0; + float f = 0.0f; + float _Complex cf = 0.0f + 0.0f * I; + double d = 0.0; + char *p = 0; + void *vp = 0; + uintptr_t uip = p; + enum { e1 } e = e1; + bool b = true; + + cos(i); // COMPLIANT + cos(ui); // COMPLIANT + cos(s); // COMPLIANT + cos(us); // COMPLIANT + cos(c); // NON-COMPLIANT + cos(uc); // COMPLIANT + cos(sc); // COMPLIANT + cos(l); // COMPLIANT + cos(ul); // COMPLIANT + cos(f); // COMPLIANT + cos(cf); // COMPLIANT + cos(d); // COMPLIANT + // cos(p); // Doesn't compile + // cos(vp); // Doesn't compile + cos(uip); // COMPLIANT + cos(e); // NON-COMPLIANT + cos(b); // NON-COMPLIANT + cos(1); // COMPLIANT + cos(1.1f); // COMPLIANT + cos('a'); // NON-COMPLIANT[false negative] + + /** + * Int, float, and complex allowed: + */ + acos(i); // COMPLIANT + acos(f); // COMPLIANT + acosh(i); // COMPLIANT + acosh(f); // COMPLIANT + asin(i); // COMPLIANT + asin(f); // COMPLIANT + asinh(i); // COMPLIANT + asinh(f); // COMPLIANT + atan(i); // COMPLIANT + atan(f); // COMPLIANT + atan2(i, i); // COMPLIANT + atan2(f, f); // COMPLIANT + atanh(i); // COMPLIANT + atanh(f); // COMPLIANT + carg(i); // COMPLIANT + carg(f); // COMPLIANT + cbrt(i); // COMPLIANT + cbrt(f); // COMPLIANT + ceil(i); // COMPLIANT + ceil(f); // COMPLIANT + cimag(i); // COMPLIANT + cimag(f); // COMPLIANT + conj(i); // COMPLIANT + conj(f); // COMPLIANT + copysign(i, i); // COMPLIANT + copysign(f, f); // COMPLIANT + cos(i); // COMPLIANT + cos(f); // COMPLIANT + cosh(i); // COMPLIANT + cosh(f); // COMPLIANT + cproj(i); // COMPLIANT + cproj(f); // COMPLIANT + creal(i); // COMPLIANT + creal(f); // COMPLIANT + erf(i); // COMPLIANT + erf(f); // COMPLIANT + erfc(i); // COMPLIANT + erfc(f); // COMPLIANT + exp(i); // COMPLIANT + exp(f); // COMPLIANT + exp2(i); // COMPLIANT + exp2(f); // COMPLIANT + expm1(i); // COMPLIANT + expm1(f); // COMPLIANT + fabs(i); // COMPLIANT + fabs(f); // COMPLIANT + fdim(i, i); // COMPLIANT + fdim(f, f); // COMPLIANT + floor(i); // COMPLIANT + floor(f); // COMPLIANT + fma(i, i, i); // COMPLIANT + fma(f, f, f); // COMPLIANT + fmax(i, i); // COMPLIANT + fmax(f, f); // COMPLIANT + fmin(i, i); // COMPLIANT + fmin(f, f); // COMPLIANT + fmod(i, i); // COMPLIANT + fmod(f, f); // COMPLIANT + frexp(i, &i); // COMPLIANT + frexp(f, &p); // COMPLIANT + hypot(i, i); // COMPLIANT + hypot(f, f); // COMPLIANT + ilogb(i); // COMPLIANT + ilogb(f); // COMPLIANT + llrint(i); // COMPLIANT + llrint(f); // COMPLIANT + ldexp(i, i); // COMPLIANT + ldexp(f, f); // COMPLIANT + lgamma(i); // COMPLIANT + lgamma(f); // COMPLIANT + llround(i); // COMPLIANT + llround(f); // COMPLIANT + log(i); // COMPLIANT + log(f); // COMPLIANT + pow(i, i); // COMPLIANT + pow(f, f); // COMPLIANT + remainder(i, i); // COMPLIANT + remainder(f, f); // COMPLIANT + remquo(i, i, &i); // COMPLIANT + remquo(f, f, &f); // COMPLIANT + rint(i); // COMPLIANT + rint(f); // COMPLIANT + round(i); // COMPLIANT + round(f); // COMPLIANT + scalbn(i, i); // COMPLIANT + scalbn(f, f); // COMPLIANT + scalbln(i, i); // COMPLIANT + scalbln(f, f); // COMPLIANT + sin(i); // COMPLIANT + sin(f); // COMPLIANT + sin(cf); // COMPLIANT + sinh(i); // COMPLIANT + sinh(f); // COMPLIANT + sqrt(i); // COMPLIANT + sqrt(f); // COMPLIANT + tan(i); // COMPLIANT + tan(f); // COMPLIANT + tanh(i); // COMPLIANT + tanh(f); // COMPLIANT + tgamma(i); // COMPLIANT + tgamma(f); // COMPLIANT + trunc(i); // COMPLIANT + trunc(f); // COMPLIANT + + /** + * Char not allowed: + */ + acos(c); // NON-COMPLIANT + acosh(c); // NON-COMPLIANT + asin(c); // NON-COMPLIANT + asinh(c); // NON-COMPLIANT + atan2(c, i); // NON-COMPLIANT + atan2(i, c); // NON-COMPLIANT + atanh(c); // NON-COMPLIANT + carg(c); // NON-COMPLIANT + ceil(c); // NON-COMPLIANT + cimag(c); // NON-COMPLIANT + conj(c); // NON-COMPLIANT + copysign(i, c); // NON-COMPLIANT + copysign(c, i); // NON-COMPLIANT + cosh(c); // NON-COMPLIANT + cproj(c); // NON-COMPLIANT + creal(c); // NON-COMPLIANT + erf(c); // NON-COMPLIANT + erfc(c); // NON-COMPLIANT + exp(c); // NON-COMPLIANT + exp2(c); // NON-COMPLIANT + expm1(c); // NON-COMPLIANT + fabs(c); // NON-COMPLIANT + fdim(c, i); // NON-COMPLIANT + fdim(i, c); // NON-COMPLIANT + floor(c); // NON-COMPLIANT + fma(c, i, i); // NON-COMPLIANT + fma(i, c, i); // NON-COMPLIANT + fma(i, i, c); // NON-COMPLIANT + fmax(c, i); // NON-COMPLIANT + fmax(i, c); // NON-COMPLIANT + fmin(c, i); // NON-COMPLIANT + fmin(i, c); // NON-COMPLIANT + fmod(c, i); // NON-COMPLIANT + fmod(i, c); // NON-COMPLIANT + frexp(c, i); // NON-COMPLIANT + hypot(c, i); // NON-COMPLIANT + hypot(i, c); // NON-COMPLIANT + ilogb(c); // NON-COMPLIANT + ldexp(c, i); // NON-COMPLIANT + ldexp(i, c); // NON-COMPLIANT + lgamma(c); // NON-COMPLIANT + llrint(c); // NON-COMPLIANT + llround(c); // NON-COMPLIANT + log(c); // NON-COMPLIANT + log10(c); // NON-COMPLIANT + log1p(c); // NON-COMPLIANT + log2(c); // NON-COMPLIANT + logb(c); // NON-COMPLIANT + lrint(c); // NON-COMPLIANT + lround(c); // NON-COMPLIANT + nearbyint(c); // NON-COMPLIANT + nextafter(c, i); // NON-COMPLIANT + nextafter(i, c); // NON-COMPLIANT + nexttoward(c, i); // NON-COMPLIANT + nexttoward(i, c); // NON-COMPLIANT + pow(c, i); // NON-COMPLIANT + pow(i, c); // NON-COMPLIANT + remainder(c, i); // NON-COMPLIANT + remainder(i, c); // NON-COMPLIANT + remquo(c, i, i); // NON-COMPLIANT + remquo(i, c, i); // NON-COMPLIANT + rint(c); // NON-COMPLIANT + round(c); // NON-COMPLIANT + scalbn(c, i); // NON-COMPLIANT + scalbn(i, c); // NON-COMPLIANT + scalbln(c, i); // NON-COMPLIANT + scalbln(i, c); // NON-COMPLIANT + sin(c); // NON-COMPLIANT + sinh(c); // NON-COMPLIANT + sqrt(c); // NON-COMPLIANT + tan(c); // NON-COMPLIANT + tanh(c); // NON-COMPLIANT + tgamma(c); // NON-COMPLIANT + trunc(c); // NON-COMPLIANT + + /** + * Complex types allowed in some calls, not others: + */ + acos(cf); // COMPLIANT + acosh(cf); // COMPLIANT + asin(cf); // COMPLIANT + asinh(cf); // COMPLIANT + atan(cf); // COMPLIANT + atan2(cf, i); // NON-COMPLIANT + atan2(i, cf); // NON-COMPLIANT + atanh(cf); // COMPLIANT + carg(cf); // COMPLIANT + cbrt(cf); // NON-COMPLIANT + ceil(cf); // NON-COMPLIANT + cimag(cf); // COMPLIANT + conj(cf); // COMPLIANT + copysign(i, cf); // NON-COMPLIANT + copysign(cf, i); // NON-COMPLIANT + copysign(i, cf); // NON-COMPLIANT + cos(cf); // COMPLIANT + cosh(cf); // COMPLIANT + cproj(cf); // COMPLIANT + creal(cf); // COMPLIANT + erf(cf); // NON-COMPLIANT + erfc(cf); // NON-COMPLIANT + exp(cf); // COMPLIANT + exp2(cf); // NON-COMPLIANT + expm1(cf); // NON-COMPLIANT + fabs(cf); // COMPLIANT + fdim(cf, i); // NON-COMPLIANT + fdim(i, cf); // NON-COMPLIANT + floor(cf); // NON-COMPLIANT + fma(cf, i, i); // NON-COMPLIANT + fma(i, cf, i); // NON-COMPLIANT + fma(i, i, cf); // NON-COMPLIANT + fmax(cf, i); // NON-COMPLIANT + fmax(i, cf); // NON-COMPLIANT + fmin(cf, i); // NON-COMPLIANT + fmin(i, cf); // NON-COMPLIANT + fmod(cf, i); // NON-COMPLIANT + fmod(i, cf); // NON-COMPLIANT + frexp(cf, i); // NON-COMPLIANT + hypot(cf, i); // NON-COMPLIANT + hypot(i, cf); // NON-COMPLIANT + ilogb(cf); // NON-COMPLIANT + ldexp(cf, i); // NON-COMPLIANT + ldexp(i, cf); // NON-COMPLIANT + lgamma(cf); // NON-COMPLIANT + llrint(cf); // NON-COMPLIANT + llround(cf); // NON-COMPLIANT + log(cf); // COMPLIANT + log10(cf); // NON-COMPLIANT + log1p(cf); // NON-COMPLIANT + log2(cf); // NON-COMPLIANT + logb(cf); // NON-COMPLIANT + lrint(cf); // NON-COMPLIANT + lround(cf); // NON-COMPLIANT + nearbyint(cf); // NON-COMPLIANT + nextafter(cf, i); // NON-COMPLIANT + nextafter(i, cf); // NON-COMPLIANT + nexttoward(cf, i); // NON-COMPLIANT + nexttoward(i, cf); // NON-COMPLIANT + pow(cf, cf); // COMPLIANT + remainder(cf, i); // NON-COMPLIANT + remainder(i, cf); // NON-COMPLIANT + remquo(cf, i, i); // NON-COMPLIANT + remquo(i, cf, i); // NON-COMPLIANT + rint(cf); // NON-COMPLIANT + round(cf); // NON-COMPLIANT + scalbn(cf, i); // NON-COMPLIANT + scalbn(i, cf); // NON-COMPLIANT + scalbln(cf, i); // NON-COMPLIANT + scalbln(i, cf); // NON-COMPLIANT + sin(cf); // COMPLIANT + sinh(cf); // COMPLIANT + sqrt(cf); // COMPLIANT + tan(cf); // COMPLIANT + tanh(cf); // COMPLIANT + tgamma(cf); // NON-COMPLIANT + trunc(cf); // NON-COMPLIANT + + /* Test output arguments thoroughly */ + frexp(i, &i); // COMPLIANT + frexp(i, vp); // COMPLIANT + frexp(i, 0); // COMPLIANT + frexp(i, 'c' - 'c'); // COMPLIANT + frexp(i, c); // COMPLIANT + remquo(i, i, &i); // COMPLIANT + remquo(i, i, vp); // COMPLIANT + remquo(i, i, 0); // COMPLIANT + remquo(i, i, 'c' - 'c'); // COMPLIANT + remquo(i, i, c); // COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected b/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected new file mode 100644 index 0000000000..6136aa4314 --- /dev/null +++ b/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected @@ -0,0 +1,139 @@ +| test.c:95:3:95:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:96:3:96:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:97:3:97:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:98:3:98:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:99:3:99:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:100:3:100:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:101:3:101:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:102:3:102:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:103:3:103:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:104:3:104:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:105:3:105:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:106:3:106:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:107:3:107:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:108:3:108:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:109:3:109:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:110:3:110:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:111:3:111:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:112:3:112:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:113:3:113:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:114:3:114:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:121:3:121:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:122:3:122:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:123:3:123:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:124:3:124:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:125:3:125:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:126:3:126:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:127:3:127:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:128:3:128:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:131:3:131:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:132:3:132:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:133:3:133:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:134:3:134:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:135:3:135:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:136:3:136:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:137:3:137:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:138:3:138:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:139:3:139:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:140:3:140:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:141:3:141:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:142:3:142:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:143:3:143:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:144:3:144:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:145:3:145:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:146:3:146:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:147:3:147:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:148:3:148:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:149:3:149:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:150:3:150:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:151:3:151:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:152:3:152:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:153:3:153:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:154:3:154:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:155:3:155:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:156:3:156:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:157:3:157:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:158:3:158:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:159:3:159:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:160:3:160:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:161:3:161:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:162:3:162:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:165:3:165:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:166:3:166:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:167:3:167:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:168:3:168:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:169:3:169:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:170:3:170:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:171:3:171:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:172:3:172:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:175:3:175:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (float, double). | +| test.c:176:3:176:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (float, long double). | +| test.c:177:3:177:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (double, float). | +| test.c:178:3:178:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (double, long double). | +| test.c:179:3:179:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long double, float). | +| test.c:180:3:180:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long double, double). | +| test.c:183:3:183:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:184:3:184:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:185:3:185:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:186:3:186:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:187:3:187:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:188:3:188:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:189:3:189:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:190:3:190:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:191:3:191:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:192:3:192:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:193:3:193:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:194:3:194:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:195:3:195:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:196:3:196:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:197:3:197:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:198:3:198:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:199:3:199:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:200:3:200:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:201:3:201:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:202:3:202:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:203:3:203:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:204:3:204:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:205:3:205:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:206:3:206:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:207:3:207:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:208:3:208:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:209:3:209:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:210:3:210:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:211:3:211:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:212:3:212:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:213:3:213:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, float). | +| test.c:214:3:214:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, double). | +| test.c:215:3:215:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long double). | +| test.c:216:3:216:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, float). | +| test.c:217:3:217:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, double). | +| test.c:218:3:218:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long double). | +| test.c:219:3:219:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, float). | +| test.c:220:3:220:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, double). | +| test.c:221:3:221:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, long double). | +| test.c:222:3:222:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, float). | +| test.c:223:3:223:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, double). | +| test.c:224:3:224:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, long double). | +| test.c:225:3:225:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, float). | +| test.c:226:3:226:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, double). | +| test.c:227:3:227:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long double). | +| test.c:228:3:228:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, float). | +| test.c:229:3:229:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, double). | +| test.c:230:3:230:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long double). | +| test.c:235:3:235:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:242:3:242:16 | copysign(x,y) | Call to type-generic macro 'copysign' has arguments with differing standard types (int, float). | +| test.c:245:3:245:12 | fdim(x,y) | Call to type-generic macro 'fdim' has arguments with differing standard types (int, float). | +| test.c:248:3:248:14 | fma(x,y,z) | Call to type-generic macro 'fma' has arguments with differing standard types (float, int, int). | +| test.c:249:3:249:14 | fma(x,y,z) | Call to type-generic macro 'fma' has arguments with differing standard types (int, float, int). | +| test.c:250:3:250:14 | fma(x,y,z) | Call to type-generic macro 'fma' has arguments with differing standard types (int, int, float). | +| test.c:253:3:253:12 | fmax(x,y) | Call to type-generic macro 'fmax' has arguments with differing standard types (int, float). | +| test.c:256:3:256:12 | fmin(x,y) | Call to type-generic macro 'fmin' has arguments with differing standard types (int, float). | +| test.c:259:3:259:12 | fmod(x,y) | Call to type-generic macro 'fmod' has arguments with differing standard types (int, float). | +| test.c:262:3:262:13 | hypot(x,y) | Call to type-generic macro 'hypot' has arguments with differing standard types (int, float). | +| test.c:265:3:265:13 | ldexp(x,y) | Call to type-generic macro 'ldexp' has arguments with differing standard types (int, float). | +| test.c:268:3:268:17 | nextafter(x,y) | Call to type-generic macro 'nextafter' has arguments with differing standard types (int, float). | +| test.c:271:3:271:18 | nexttoward(x,y) | Call to type-generic macro 'nexttoward' has arguments with differing standard types (int, float). | +| test.c:274:3:274:17 | remainder(x,y) | Call to type-generic macro 'remainder' has arguments with differing standard types (int, float). | +| test.c:277:3:277:17 | remquo(x,y,z) | Call to type-generic macro 'remquo' has arguments with differing standard types (int, float). | +| test.c:280:3:280:15 | scalbln(x,y) | Call to type-generic macro 'scalbln' has arguments with differing standard types (int, float). | +| test.c:283:3:283:14 | scalbn(x,y) | Call to type-generic macro 'scalbn' has arguments with differing standard types (int, float). | diff --git a/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.qlref b/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.qlref new file mode 100644 index 0000000000..550893822f --- /dev/null +++ b/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.qlref @@ -0,0 +1 @@ +rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-23/test.c b/c/misra/test/rules/RULE-21-23/test.c new file mode 100644 index 0000000000..08df1184a7 --- /dev/null +++ b/c/misra/test/rules/RULE-21-23/test.c @@ -0,0 +1,288 @@ +#include +#include + +void f1() { + signed char c = 0; + unsigned char uc = 0; + short s = 0; + unsigned short us = 0; + int i = 0; + unsigned int ui = 0; + long l = 0; + unsigned long ul = 0; + float f = 0.0f; + double d = 0.0; + long double ld = 0.0; + uint8_t u8 = 0; + int8_t i8 = 0; + uint16_t u16 = 0; + int16_t i16 = 0; + uint32_t u32 = 0; + int32_t i32 = 0; + uint64_t u64 = 0; + int64_t i64 = 0; + + /** + * Test exact types + */ + atan2(c, c); // COMPLIANT + atan2(uc, uc); // COMPLIANT + atan2(s, s); // COMPLIANT + atan2(us, us); // COMPLIANT + atan2(i, i); // COMPLIANT + atan2(ui, ui); // COMPLIANT + atan2(ui, ui); // COMPLIANT + atan2(l, l); // COMPLIANT + atan2(ul, ul); // COMPLIANT + atan2(f, f); // COMPLIANT + atan2(d, d); // COMPLIANT + atan2(ld, ld); // COMPLIANT + atan2(u8, u8); // COMPLIANT + atan2(i8, i8); // COMPLIANT + atan2(u16, u16); // COMPLIANT + atan2(i16, i16); // COMPLIANT + atan2(u32, u32); // COMPLIANT + atan2(i32, i32); // COMPLIANT + atan2(u64, u64); // COMPLIANT + atan2(i64, i64); // COMPLIANT + + /** Test equivalent types */ + atan2(c, i8); // COMPLIANT + atan2(i8, c); // COMPLIANT + atan2(uc, u8); // COMPLIANT + atan2(u8, uc); // COMPLIANT + atan2(s, i16); // COMPLIANT + atan2(i16, s); // COMPLIANT + atan2(us, u16); // COMPLIANT + atan2(u16, us); // COMPLIANT + atan2(i, i32); // COMPLIANT + atan2(i32, i); // COMPLIANT + atan2(ui, u32); // COMPLIANT + atan2(u32, ui); // COMPLIANT + atan2(l, i64); // COMPLIANT + atan2(i64, l); // COMPLIANT + atan2(ul, u64); // COMPLIANT + atan2(u64, ul); // COMPLIANT + + /** Types are the same after integer promotion */ + atan2(c, i8); // COMPLIANT + atan2(c, u8); // COMPLIANT + atan2(c, i16); // COMPLIANT + atan2(c, u16); // COMPLIANT + atan2(c, i32); // COMPLIANT + atan2(uc, i8); // COMPLIANT + atan2(uc, u8); // COMPLIANT + atan2(uc, i16); // COMPLIANT + atan2(uc, u16); // COMPLIANT + atan2(uc, i32); // COMPLIANT + atan2(s, i8); // COMPLIANT + atan2(s, u8); // COMPLIANT + atan2(s, i16); // COMPLIANT + atan2(s, u16); // COMPLIANT + atan2(s, i32); // COMPLIANT + atan2(us, i8); // COMPLIANT + atan2(us, u8); // COMPLIANT + atan2(us, i16); // COMPLIANT + atan2(us, u16); // COMPLIANT + atan2(us, i32); // COMPLIANT + atan2(i, i8); // COMPLIANT + atan2(i, u8); // COMPLIANT + atan2(i, i16); // COMPLIANT + atan2(i, u16); // COMPLIANT + atan2(i, i32); // COMPLIANT + + /** Integer promotion makes a signed int, not an unsigned int */ + atan2(c, ui); // NON-COMPLIANT + atan2(c, u32); // NON-COMPLIANT + atan2(i8, ui); // NON-COMPLIANT + atan2(i8, u32); // NON-COMPLIANT + atan2(uc, ui); // NON-COMPLIANT + atan2(uc, u32); // NON-COMPLIANT + atan2(u8, ui); // NON-COMPLIANT + atan2(u8, u32); // NON-COMPLIANT + atan2(s, ui); // NON-COMPLIANT + atan2(s, u32); // NON-COMPLIANT + atan2(i16, ui); // NON-COMPLIANT + atan2(i16, u32); // NON-COMPLIANT + atan2(us, ui); // NON-COMPLIANT + atan2(us, u32); // NON-COMPLIANT + atan2(u16, ui); // NON-COMPLIANT + atan2(u16, u32); // NON-COMPLIANT + atan2(i, ui); // NON-COMPLIANT + atan2(i, u32); // NON-COMPLIANT + atan2(i32, ui); // NON-COMPLIANT + atan2(i32, u32); // NON-COMPLIANT + atan2(ui, ui); // COMPLIANT + atan2(ui, u32); // COMPLIANT + atan2(u32, ui); // COMPLIANT + atan2(u32, u32); // COMPLIANT + + /** Integer promotion makes int, not long */ + atan2(c, l); // NON-COMPLIANT + atan2(i8, l); // NON-COMPLIANT + atan2(uc, l); // NON-COMPLIANT + atan2(u8, l); // NON-COMPLIANT + atan2(s, l); // NON-COMPLIANT + atan2(i16, l); // NON-COMPLIANT + atan2(us, l); // NON-COMPLIANT + atan2(u16, l); // NON-COMPLIANT + + /** Integer vs long */ + atan2(i, l); // NON-COMPLIANT + atan2(i32, l); // NON-COMPLIANT + atan2(ui, l); // NON-COMPLIANT + atan2(u32, l); // NON-COMPLIANT + atan2(l, i); // NON-COMPLIANT + atan2(l, ui); // NON-COMPLIANT + atan2(l, i32); // NON-COMPLIANT + atan2(l, u32); // NON-COMPLIANT + atan2(i, ul); // NON-COMPLIANT + atan2(i32, ul); // NON-COMPLIANT + atan2(ui, ul); // NON-COMPLIANT + atan2(u32, ul); // NON-COMPLIANT + atan2(ul, i); // NON-COMPLIANT + atan2(ul, ui); // NON-COMPLIANT + atan2(ul, i32); // NON-COMPLIANT + atan2(ul, u32); // NON-COMPLIANT + atan2(i, i64); // NON-COMPLIANT + atan2(i32, i64); // NON-COMPLIANT + atan2(ui, i64); // NON-COMPLIANT + atan2(u32, i64); // NON-COMPLIANT + atan2(i64, i); // NON-COMPLIANT + atan2(i64, ui); // NON-COMPLIANT + atan2(i64, i32); // NON-COMPLIANT + atan2(i64, u32); // NON-COMPLIANT + atan2(i, u64); // NON-COMPLIANT + atan2(i32, u64); // NON-COMPLIANT + atan2(ui, u64); // NON-COMPLIANT + atan2(u32, u64); // NON-COMPLIANT + atan2(u64, i); // NON-COMPLIANT + atan2(u64, ui); // NON-COMPLIANT + atan2(u64, i32); // NON-COMPLIANT + atan2(u64, u32); // NON-COMPLIANT + + /** Signed vs unsigned long, since those don't promote */ + atan2(l, ul); // NON-COMPLIANT + atan2(l, u64); // NON-COMPLIANT + atan2(i64, ul); // NON-COMPLIANT + atan2(i64, u64); // NON-COMPLIANT + atan2(ul, l); // NON-COMPLIANT + atan2(ul, i64); // NON-COMPLIANT + atan2(u64, l); // NON-COMPLIANT + atan2(u64, i64); // NON-COMPLIANT + + /** Mismatched float sizes */ + atan2(f, d); // NON-COMPLIANT + atan2(f, ld); // NON-COMPLIANT + atan2(d, f); // NON-COMPLIANT + atan2(d, ld); // NON-COMPLIANT + atan2(ld, f); // NON-COMPLIANT + atan2(ld, d); // NON-COMPLIANT + + /** Float vs int */ + atan2(c, f); // NON-COMPLIANT + atan2(c, d); // NON-COMPLIANT + atan2(c, ld); // NON-COMPLIANT + atan2(i8, f); // NON-COMPLIANT + atan2(i8, d); // NON-COMPLIANT + atan2(i8, ld); // NON-COMPLIANT + atan2(uc, f); // NON-COMPLIANT + atan2(uc, d); // NON-COMPLIANT + atan2(uc, ld); // NON-COMPLIANT + atan2(u8, f); // NON-COMPLIANT + atan2(u8, d); // NON-COMPLIANT + atan2(u8, ld); // NON-COMPLIANT + atan2(s, f); // NON-COMPLIANT + atan2(s, d); // NON-COMPLIANT + atan2(s, ld); // NON-COMPLIANT + atan2(i16, f); // NON-COMPLIANT + atan2(i16, d); // NON-COMPLIANT + atan2(i16, ld); // NON-COMPLIANT + atan2(us, f); // NON-COMPLIANT + atan2(us, d); // NON-COMPLIANT + atan2(us, ld); // NON-COMPLIANT + atan2(u16, f); // NON-COMPLIANT + atan2(u16, d); // NON-COMPLIANT + atan2(u16, ld); // NON-COMPLIANT + atan2(i, f); // NON-COMPLIANT + atan2(i, d); // NON-COMPLIANT + atan2(i, ld); // NON-COMPLIANT + atan2(i32, f); // NON-COMPLIANT + atan2(i32, d); // NON-COMPLIANT + atan2(i32, ld); // NON-COMPLIANT + atan2(ui, f); // NON-COMPLIANT + atan2(ui, d); // NON-COMPLIANT + atan2(ui, ld); // NON-COMPLIANT + atan2(u32, f); // NON-COMPLIANT + atan2(u32, d); // NON-COMPLIANT + atan2(u32, ld); // NON-COMPLIANT + atan2(l, f); // NON-COMPLIANT + atan2(l, d); // NON-COMPLIANT + atan2(l, ld); // NON-COMPLIANT + atan2(i64, f); // NON-COMPLIANT + atan2(i64, d); // NON-COMPLIANT + atan2(i64, ld); // NON-COMPLIANT + atan2(ul, f); // NON-COMPLIANT + atan2(ul, d); // NON-COMPLIANT + atan2(ul, ld); // NON-COMPLIANT + atan2(u64, f); // NON-COMPLIANT + atan2(u64, d); // NON-COMPLIANT + atan2(u64, ld); // NON-COMPLIANT + + /** Casts and conversions */ + atan2((float)i, f); // COMPLIANT + atan2(i, (int)f); // COMPLIANT + atan2((i), f); // NON-COMPLIANT + atan2(((float)i), f); // COMPLIANT + atan2((float)((int)l), f); // COMPLIANT + + /** Other functions */ + copysign(f, f); // COMPLIANT + copysign(i, i); // COMPLIANT + copysign(i, f); // NON-COMPLIANT + fdim(f, f); // COMPLIANT + fdim(i, i); // COMPLIANT + fdim(i, f); // NON-COMPLIANT + fma(f, f, f); // COMPLIANT + fma(i, i, i); // COMPLIANT + fma(f, i, i); // NON-COMPLIANT + fma(i, f, i); // NON-COMPLIANT + fma(i, i, f); // NON-COMPLIANT + fmax(f, f); // COMPLIANT + fmax(i, i); // COMPLIANT + fmax(i, f); // NON-COMPLIANT + fmin(f, f); // COMPLIANT + fmin(i, i); // COMPLIANT + fmin(i, f); // NON-COMPLIANT + fmod(f, f); // COMPLIANT + fmod(i, i); // COMPLIANT + fmod(i, f); // NON-COMPLIANT + hypot(f, f); // COMPLIANT + hypot(i, i); // COMPLIANT + hypot(i, f); // NON-COMPLIANT + ldexp(f, f); // COMPLIANT + ldexp(i, i); // COMPLIANT + ldexp(i, f); // NON-COMPLIANT + nextafter(f, f); // COMPLIANT + nextafter(i, i); // COMPLIANT + nextafter(i, f); // NON-COMPLIANT + nexttoward(f, f); // COMPLIANT + nexttoward(i, i); // COMPLIANT + nexttoward(i, f); // NON-COMPLIANT + remainder(f, f); // COMPLIANT + remainder(i, i); // COMPLIANT + remainder(i, f); // NON-COMPLIANT + remquo(f, f, 0); // COMPLIANT + remquo(i, i, 0); // COMPLIANT + remquo(i, f, 0); // NON-COMPLIANT + scalbln(f, f); // COMPLIANT + scalbln(i, i); // COMPLIANT + scalbln(i, f); // NON-COMPLIANT + scalbn(f, f); // COMPLIANT + scalbn(i, i); // COMPLIANT + scalbn(i, f); // NON-COMPLIANT + + // `frexp` has two parameters, but the second is an output parameter, and + // should not be covered by this rule. + frexp(f, 0); // COMPLIANT +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/EssentialTypes2.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/EssentialTypes2.qll new file mode 100644 index 0000000000..e1dd8d5636 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/EssentialTypes2.qll @@ -0,0 +1,44 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype EssentialTypes2Query = + TTgMathArgumentWithInvalidEssentialTypeQuery() or + TTgMathArgumentsWithDifferingStandardTypeQuery() + +predicate isEssentialTypes2QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `tgMathArgumentWithInvalidEssentialType` query + EssentialTypes2Package::tgMathArgumentWithInvalidEssentialTypeQuery() and + queryId = + // `@id` for the `tgMathArgumentWithInvalidEssentialType` query + "c/misra/tg-math-argument-with-invalid-essential-type" and + ruleId = "RULE-21-22" and + category = "mandatory" + or + query = + // `Query` instance for the `tgMathArgumentsWithDifferingStandardType` query + EssentialTypes2Package::tgMathArgumentsWithDifferingStandardTypeQuery() and + queryId = + // `@id` for the `tgMathArgumentsWithDifferingStandardType` query + "c/misra/tg-math-arguments-with-differing-standard-type" and + ruleId = "RULE-21-23" and + category = "required" +} + +module EssentialTypes2Package { + Query tgMathArgumentWithInvalidEssentialTypeQuery() { + //autogenerate `Query` type + result = + // `Query` type for `tgMathArgumentWithInvalidEssentialType` query + TQueryC(TEssentialTypes2PackageQuery(TTgMathArgumentWithInvalidEssentialTypeQuery())) + } + + Query tgMathArgumentsWithDifferingStandardTypeQuery() { + //autogenerate `Query` type + result = + // `Query` type for `tgMathArgumentsWithDifferingStandardType` query + TQueryC(TEssentialTypes2PackageQuery(TTgMathArgumentsWithDifferingStandardTypeQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index 2c3969861c..9b3e3efdd9 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -34,6 +34,7 @@ import Declarations6 import Declarations7 import Declarations8 import EssentialTypes +import EssentialTypes2 import Expressions import FloatingTypes import FunctionTypes @@ -118,6 +119,7 @@ newtype TCQuery = TDeclarations7PackageQuery(Declarations7Query q) or TDeclarations8PackageQuery(Declarations8Query q) or TEssentialTypesPackageQuery(EssentialTypesQuery q) or + TEssentialTypes2PackageQuery(EssentialTypes2Query q) or TExpressionsPackageQuery(ExpressionsQuery q) or TFloatingTypesPackageQuery(FloatingTypesQuery q) or TFunctionTypesPackageQuery(FunctionTypesQuery q) or @@ -202,6 +204,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isDeclarations7QueryMetadata(query, queryId, ruleId, category) or isDeclarations8QueryMetadata(query, queryId, ruleId, category) or isEssentialTypesQueryMetadata(query, queryId, ruleId, category) or + isEssentialTypes2QueryMetadata(query, queryId, ruleId, category) or isExpressionsQueryMetadata(query, queryId, ruleId, category) or isFloatingTypesQueryMetadata(query, queryId, ruleId, category) or isFunctionTypesQueryMetadata(query, queryId, ruleId, category) or diff --git a/rule_packages/c/EssentialTypes2.json b/rule_packages/c/EssentialTypes2.json new file mode 100644 index 0000000000..aded94817f --- /dev/null +++ b/rule_packages/c/EssentialTypes2.json @@ -0,0 +1,47 @@ +{ + "MISRA-C-2012": { + "RULE-21-22": { + "properties": { + "obligation": "mandatory" + }, + "queries": [ + { + "description": "All operand arguments to any type-generic macros in shall have an appropriate essential type", + "kind": "problem", + "name": "All operand arguments to any type-generic macros in shall have an appropriate essential", + "precision": "high", + "severity": "error", + "short_name": "TgMathArgumentWithInvalidEssentialType", + "tags": [ + "correctness", + "external/misra/c/2012/amendment3" + ] + } + ], + "implementation_scope": { + "description": "The CodeQL database may not contain the necessary information to determine the essential type of literal macro arguments such as character literals." + }, + "title": "All operand arguments to any type-generic macros in shall have an appropriate essential type" + }, + "RULE-21-23": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "All operand arguments to any multi-argument type-generic macros in shall have the same standard type", + "kind": "problem", + "name": "All operand arguments to any multi-argument type-generic macros in shall have the same", + "precision": "high", + "severity": "error", + "short_name": "TgMathArgumentsWithDifferingStandardType", + "tags": [ + "correctness", + "external/misra/c/2012/amendment3" + ] + } + ], + "title": "All operand arguments to any multi-argument type-generic macros in shall have the same standard type" + } + } +} \ No newline at end of file From 6148518eb42b967f04bacb0cf18d7631f3478a28 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 11 Mar 2025 18:32:51 -0700 Subject: [PATCH 248/370] Format qll, update package metadata --- c/common/src/codingstandards/c/TgMath.qll | 15 +++++---------- .../TgMathArgumentWithInvalidEssentialType.ql | 4 ++-- .../TgMathArgumentsWithDifferingStandardType.ql | 4 ++-- rule_packages/c/EssentialTypes2.json | 8 ++++---- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/c/common/src/codingstandards/c/TgMath.qll b/c/common/src/codingstandards/c/TgMath.qll index f5488194c6..36c47fb5a2 100644 --- a/c/common/src/codingstandards/c/TgMath.qll +++ b/c/common/src/codingstandards/c/TgMath.qll @@ -1,4 +1,3 @@ - import cpp private string getATgMathMacroName(boolean allowComplex) { @@ -35,21 +34,17 @@ class TgMathInvocation extends MacroInvocation { } Expr getOperandArgument(int i) { - result = call.getArgument(i) - and not hasOutputArgument(call.getTarget().getName(), i) + result = call.getArgument(i) and + not hasOutputArgument(call.getTarget().getName(), i) } int getNumberOfOperandArguments() { result = call.getNumberOfArguments() - count(int i | hasOutputArgument(getMacroName(), i)) } - Expr getAnOperandArgument() { - result = getOperandArgument(_) - } + Expr getAnOperandArgument() { result = getOperandArgument(_) } - predicate allowsComplex() { - allowComplex = true - } + predicate allowsComplex() { allowComplex = true } } private Call getACallInExpansion(MacroInvocation mi) { result = mi.getAnExpandedElement() } @@ -65,4 +60,4 @@ private Call getBestCallInExpansion(MacroInvocation mi) { or count(getNameMatchedCallInExpansion(mi)) > 1 and result = rank[1](Call c | c = getACallInExpansion(mi) | c order by c.getTarget().getName()) -} \ No newline at end of file +} diff --git a/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql b/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql index f06ca54979..2105567d04 100644 --- a/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql +++ b/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql @@ -1,8 +1,8 @@ /** * @id c/misra/tg-math-argument-with-invalid-essential-type - * @name RULE-21-22: All operand arguments to any type-generic macros in shall have an appropriate essential + * @name RULE-21-22: All operand arguments to type-generic macros in shall have an appropriate essential type * @description All operand arguments to any type-generic macros in shall have an - * appropriate essential type + * appropriate essential type. * @kind problem * @precision high * @problem.severity error diff --git a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql index b6daf7bb6a..5156d81cef 100644 --- a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql +++ b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql @@ -1,8 +1,8 @@ /** * @id c/misra/tg-math-arguments-with-differing-standard-type - * @name RULE-21-23: All operand arguments to any multi-argument type-generic macros in shall have the same + * @name RULE-21-23: Operand arguments for an invocation of a type-generic macro shall have the same standard type * @description All operand arguments to any multi-argument type-generic macros in shall - * have the same standard type + * have the same standard type. * @kind problem * @precision high * @problem.severity error diff --git a/rule_packages/c/EssentialTypes2.json b/rule_packages/c/EssentialTypes2.json index aded94817f..5292eccdb8 100644 --- a/rule_packages/c/EssentialTypes2.json +++ b/rule_packages/c/EssentialTypes2.json @@ -6,9 +6,9 @@ }, "queries": [ { - "description": "All operand arguments to any type-generic macros in shall have an appropriate essential type", + "description": "All operand arguments to any type-generic macros in shall have an appropriate essential type.", "kind": "problem", - "name": "All operand arguments to any type-generic macros in shall have an appropriate essential", + "name": "All operand arguments to type-generic macros in shall have an appropriate essential type", "precision": "high", "severity": "error", "short_name": "TgMathArgumentWithInvalidEssentialType", @@ -29,9 +29,9 @@ }, "queries": [ { - "description": "All operand arguments to any multi-argument type-generic macros in shall have the same standard type", + "description": "All operand arguments to any multi-argument type-generic macros in shall have the same standard type.", "kind": "problem", - "name": "All operand arguments to any multi-argument type-generic macros in shall have the same", + "name": "Operand arguments for an invocation of a type-generic macro shall have the same standard type", "precision": "high", "severity": "error", "short_name": "TgMathArgumentsWithDifferingStandardType", From e30b3c34dcd9defdba2adc5dea814be68e2c585e Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 11 Mar 2025 22:12:53 -0700 Subject: [PATCH 249/370] Implement final MISRA 2023 rule amendments --- amendments.csv | 9 +- ...dLocalObjectAddressCopiedToGlobalObject.ql | 39 ++++ .../ExceptionHandlingFeaturesOfFenvhUsed.ql | 26 ++- c/misra/test/rules/DIR-4-9/test.c | 1 + .../EmergentLanguageFeaturesUsed.expected | 1 - ...ObjectAddressCopiedToGlobalObject.expected | 4 + ...calObjectAddressCopiedToGlobalObject.qlref | 1 + c/misra/test/rules/RULE-18-6/test.c | 169 ++++++++++++++++++ ...eptionHandlingFeaturesOfFenvhUsed.expected | 28 +-- c/misra/test/rules/RULE-21-12/test.c | 9 +- .../2025-03-11-various-misra-amendments.md | 8 + .../src/codingstandards/cpp/Emergent.qll | 4 - .../cpp/IrreplaceableFunctionLikeMacro.qll | 6 + .../cpp/exclusions/c/Pointers1.qll | 17 ++ ...ddressOfAutoStorageObjectToOtherObject.qll | 2 +- rule_packages/c/Pointers1.json | 12 ++ 16 files changed, 303 insertions(+), 33 deletions(-) create mode 100644 c/misra/src/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.ql create mode 100644 c/misra/test/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.expected create mode 100644 c/misra/test/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.qlref create mode 100644 c/misra/test/rules/RULE-18-6/test.c create mode 100644 change_notes/2025-03-11-various-misra-amendments.md diff --git a/amendments.csv b/amendments.csv index 6049525515..b496790f07 100644 --- a/amendments.csv +++ b/amendments.csv @@ -1,8 +1,8 @@ language,standard,amendment,rule_id,supportable,implementation_category,implemented,difficulty c,MISRA-C-2012,Amendment3,DIR-4-6,Yes,Expand,Yes,Easy -c,MISRA-C-2012,Amendment3,DIR-4-9,Yes,Refine,No,Easy +c,MISRA-C-2012,Amendment3,DIR-4-9,Yes,Refine,Yes,Easy c,MISRA-C-2012,Amendment3,DIR-4-11,Yes,Refine,No,Import -c,MISRA-C-2012,Amendment3,RULE-1-4,Yes,Replace,No,Easy +c,MISRA-C-2012,Amendment3,RULE-1-4,Yes,Replace,Yes,Easy c,MISRA-C-2012,Amendment3,RULE-10-1,Yes,Replace,Yes,Easy c,MISRA-C-2012,Amendment3,RULE-10-3,Yes,Refine,Yes,Easy c,MISRA-C-2012,Amendment3,RULE-10-4,Yes,Refine,Yes,Import @@ -10,11 +10,11 @@ c,MISRA-C-2012,Amendment3,RULE-10-5,Yes,Expand,Yes,Easy c,MISRA-C-2012,Amendment3,RULE-10-7,Yes,Refine,Yes,Import c,MISRA-C-2012,Amendment3,RULE-10-8,Yes,Refine,Yes,Import c,MISRA-C-2012,Amendment3,RULE-21-11,Yes,Clarification,Yes,Import -c,MISRA-C-2012,Amendment3,RULE-21-12,Yes,Replace,No,Easy +c,MISRA-C-2012,Amendment3,RULE-21-12,Yes,Replace,Yes,Easy c,MISRA-C-2012,Amendment4,RULE-11-3,Yes,Expand,No,Easy c,MISRA-C-2012,Amendment4,RULE-11-8,Yes,Expand,No,Easy c,MISRA-C-2012,Amendment4,RULE-13-2,Yes,Expand,No,Very Hard -c,MISRA-C-2012,Amendment4,RULE-18-6,Yes,Expand,No,Medium +c,MISRA-C-2012,Amendment4,RULE-18-6,Yes,Expand,Yes,Medium c,MISRA-C-2012,Amendment4,RULE-18-8,Yes,Split,Yes,Easy c,MISRA-C-2012,Amendment4,RULE-2-2,Yes,Clarification,Yes,Import c,MISRA-C-2012,Amendment4,RULE-2-7,Yes,Clarification,Yes,Import @@ -26,7 +26,6 @@ c,MISRA-C-2012,Amendment4,RULE-10-1,Yes,Clarification,Yes,Import c,MISRA-C-2012,Amendment4,RULE-18-3,Yes,Clarification,Yes,Import c,MISRA-C-2012,Amendment4,RULE-1-4,Yes,Replace,No,Easy c,MISRA-C-2012,Amendment4,RULE-9-1,Yes,Refine,No,Easy -c,MISRA-C-2012,Amendment4,RULE-9-2,Yes,Refine,No,Import c,MISRA-C-2012,Corrigendum2,DIR-4-10,Yes,Clarification,Yes,Import c,MISRA-C-2012,Corrigendum2,RULE-7-4,Yes,Refine,No,Easy c,MISRA-C-2012,Corrigendum2,RULE-8-2,Yes,Clarification,Yes,Import diff --git a/c/misra/src/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.ql b/c/misra/src/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.ql new file mode 100644 index 0000000000..6a520447d1 --- /dev/null +++ b/c/misra/src/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.ql @@ -0,0 +1,39 @@ +/** + * @id c/misra/thread-local-object-address-copied-to-global-object + * @name RULE-18-6: The address of an object with thread-local storage shall not be copied to a global object + * @description Storing the address of a thread-local object in a global object will result in + * undefined behavior if the address is accessed after the relevant thread is + * terminated. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-18-6 + * correctness + * external/misra/c/2012/amendment3 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.Objects +import codingstandards.cpp.Concurrency + +from AssignExpr assignment, Element threadLocal, ObjectIdentity static +where + not isExcluded(assignment, Pointers1Package::threadLocalObjectAddressCopiedToGlobalObjectQuery()) and + assignment.getLValue() = static.getASubobjectAccess() and + static.getStorageDuration().isStatic() and + ( + exists(ObjectIdentity threadLocalObj | + threadLocal = threadLocalObj and + assignment.getRValue() = threadLocalObj.getASubobjectAddressExpr() and + threadLocalObj.getStorageDuration().isThread() + ) + or + exists(TSSGetFunctionCall getCall | + threadLocal = getCall.getKey() and + assignment.getRValue() = getCall + ) + ) +select assignment, "Thread local object $@ address copied to static object $@.", + threadLocal.getLocation(), threadLocal.toString(), static.getLocation(), static.toString() diff --git a/c/misra/src/rules/RULE-21-12/ExceptionHandlingFeaturesOfFenvhUsed.ql b/c/misra/src/rules/RULE-21-12/ExceptionHandlingFeaturesOfFenvhUsed.ql index 33da2f5d03..c70e71ea1a 100644 --- a/c/misra/src/rules/RULE-21-12/ExceptionHandlingFeaturesOfFenvhUsed.ql +++ b/c/misra/src/rules/RULE-21-12/ExceptionHandlingFeaturesOfFenvhUsed.ql @@ -18,7 +18,8 @@ import codingstandards.c.misra class FPExceptionHandlingFunction extends Function { FPExceptionHandlingFunction() { this.hasName([ - "feclearexcept", "fegetexceptflag", "feraiseexcept", "fesetexceptflag", "fetestexcept" + "feclearexcept", "fegetexceptflag", "feraiseexcept", "fesetexceptflag", "fetestexcept", + "fesetenv", "feupdateenv", "fesetround" ]) and this.getFile().getBaseName() = "fenv.h" } @@ -33,22 +34,29 @@ class FPExceptionHandlingMacro extends Macro { } } -from Locatable call, string name, string kind +from Locatable element, string name, string message where - not isExcluded(call, BannedPackage::exceptionHandlingFeaturesOfFenvhUsedQuery()) and + not isExcluded(element, BannedPackage::exceptionHandlingFeaturesOfFenvhUsedQuery()) and ( + exists(Include include | + include.getIncludedFile().getBaseName() = "fenv.h" and + message = "Include of banned header" and + name = "fenv.h" and + element = include + ) + or exists(FPExceptionHandlingFunction f | - call = f.getACallToThisFunction() and + element = f.getACallToThisFunction() and name = f.getName() and - kind = "function" + message = "Call to banned function" ) or exists(FPExceptionHandlingMacro m | - call = m.getAnInvocation() and + element = m.getAnInvocation() and name = m.getName() and - kind = "macro" and + message = "Expansion of banned macro" and // Exclude macro invocations expanded from other macro invocations from macros in fenv.h. - not call.(MacroInvocation).getParentInvocation().getMacro().getFile().getBaseName() = "fenv.h" + not element.(MacroInvocation).getParentInvocation().getMacro().getFile().getBaseName() = "fenv.h" ) ) -select call, "Call to banned " + kind + " " + name + "." +select element, message + " '" + name + "'." diff --git a/c/misra/test/rules/DIR-4-9/test.c b/c/misra/test/rules/DIR-4-9/test.c index 50e6bdb042..c91e1a15a2 100644 --- a/c/misra/test/rules/DIR-4-9/test.c +++ b/c/misra/test/rules/DIR-4-9/test.c @@ -10,6 +10,7 @@ #define MACRO8(x) "NOP" // COMPLIANT #define MACRO9() printf_custom("output = %d", 7) // NON_COMPLIANT #define MACRO10(x) // COMPLIANT +#define MACRO11(x) _Generic((x), int: 1, default: 0) // COMPLIANT #define MY_ASSERT(X) assert(X) // NON_COMPLIANT[FALSE_NEGATIVE] const char a1[MACRO2(1, 1) + 6]; diff --git a/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected b/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected index 04c0e1bbd6..b0bbc467aa 100644 --- a/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected +++ b/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected @@ -1,6 +1,5 @@ | test.c:2:1:2:22 | #include | Usage of emergent language feature. | | test.c:4:1:4:20 | #include | Usage of emergent language feature. | -| test.c:6:1:6:49 | #define MACRO(x) _Generic((x), int : 0, long : 1) | Usage of emergent language feature. | | test.c:7:1:7:32 | #define __STDC_WANT_LIB_EXT1__ 1 | Usage of emergent language feature. | | test.c:12:26:12:40 | atomic_new_type | Usage of emergent language feature. | | test.c:17:15:17:15 | i | Usage of emergent language feature. | diff --git a/c/misra/test/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.expected b/c/misra/test/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.expected new file mode 100644 index 0000000000..99c5a91645 --- /dev/null +++ b/c/misra/test/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.expected @@ -0,0 +1,4 @@ +| test.c:29:3:29:10 | ... = ... | Thread local object $@ address copied to static object $@. | test.c:8:19:8:20 | test.c:8:19:8:20 | t1 | test.c:12:6:12:7 | test.c:12:6:12:7 | g2 | +| test.c:55:3:55:14 | ... = ... | Thread local object $@ address copied to static object $@. | test.c:10:17:10:18 | test.c:10:17:10:18 | t3 | test.c:13:3:13:4 | test.c:13:3:13:4 | g3 | +| test.c:152:3:152:21 | ... = ... | Thread local object $@ address copied to static object $@. | test.c:152:16:152:20 | test.c:152:16:152:20 | & ... | test.c:12:6:12:7 | test.c:12:6:12:7 | g2 | +| test.c:155:3:155:23 | ... = ... | Thread local object $@ address copied to static object $@. | test.c:155:18:155:22 | test.c:155:18:155:22 | & ... | test.c:13:3:13:4 | test.c:13:3:13:4 | g3 | diff --git a/c/misra/test/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.qlref b/c/misra/test/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.qlref new file mode 100644 index 0000000000..90cdd7a43f --- /dev/null +++ b/c/misra/test/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.qlref @@ -0,0 +1 @@ +rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-18-6/test.c b/c/misra/test/rules/RULE-18-6/test.c new file mode 100644 index 0000000000..13b1070397 --- /dev/null +++ b/c/misra/test/rules/RULE-18-6/test.c @@ -0,0 +1,169 @@ +#include + +typedef struct { + int *p; + int m +} s; + +_Thread_local int t1; +_Thread_local int *t2; +_Thread_local s t3; +int g1; +int *g2; +s g3; + +void f1() { + // Regular object accesses + t1 = t1; // COMPLIANT + t1 = *t2; // COMPLIANT + t1 = g1; // COMPLIANT + t1 = *g2; // COMPLIANT + g1 = t1; // COMPLIANT + g1 = *t2; // COMPLIANT + g1 = g1; // COMPLIANT + g1 = *g2; // COMPLIANT + t2 = &t1; // COMPLIANT + t2 = t2; // COMPLIANT + t2 = &g1; // COMPLIANT + t2 = g2; // COMPLIANT + g2 = &t1; // NON-COMPLIANT + g2 = t2; // COMPLIANT + g2 = &g1; // COMPLIANT + g2 = g2; // COMPLIANT + *t2 = t1; // COMPLIANT + *t2 = *t2; // COMPLIANT + *t2 = g1; // COMPLIANT + *t2 = *g2; // COMPLIANT + *g2 = t1; // COMPLIANT + *g2 = *t2; // COMPLIANT + *g2 = g1; // COMPLIANT + *g2 = *g2; // COMPLIANT + + // Subobject accesses + t3.m = t3.m; // COMPLIANT + t3.m = *t3.p; // COMPLIANT + t3.m = g3.m; // COMPLIANT + t3.m = *g3.p; // COMPLIANT + g3.m = t3.m; // COMPLIANT + g3.m = *t3.p; // COMPLIANT + g3.m = g3.m; // COMPLIANT + g3.m = *g3.p; // COMPLIANT + t3.p = &t3.m; // COMPLIANT + t3.p = t3.p; // COMPLIANT + t3.p = &g3.m; // COMPLIANT + t3.p = g3.p; // COMPLIANT + g3.p = &t3.m; // NON-COMPLIANT + g3.p = t3.p; // COMPLIANT + g3.p = &g3.m; // COMPLIANT + g3.p = g3.p; // COMPLIANT + *t3.p = t3.m; // COMPLIANT + *t3.p = *t3.p; // COMPLIANT + *t3.p = g3.m; // COMPLIANT + *t3.p = *g3.p; // COMPLIANT + *g3.p = t3.m; // COMPLIANT + *g3.p = *t3.p; // COMPLIANT + *g3.p = g3.m; // COMPLIANT + *g3.p = *g3.p; // COMPLIANT + + // Storing values in locals (automatic storage duration) + int l1; + int *l2; + s l3; + + l1 = l1; // COMPLIANT + l1 = *l2; // COMPLIANT + l1 = l3.m; // COMPLIANT + l1 = *l3.p; // COMPLIANT + l1 = t1; // COMPLIANT + l1 = *t2; // COMPLIANT + l1 = t3.m; // COMPLIANT + l1 = *t3.p; // COMPLIANT + l1 = g1; // COMPLIANT + l1 = *g2; // COMPLIANT + l1 = g3.m; // COMPLIANT + l1 = *g3.p; // COMPLIANT + l2 = &l1; // COMPLIANT + l2 = l2; // COMPLIANT + l2 = &l3.m; // COMPLIANT + l2 = l3.p; // COMPLIANT + l2 = &t1; // COMPLIANT + l2 = t2; // COMPLIANT + l2 = &t3.m; // COMPLIANT + l2 = t3.p; // COMPLIANT + l2 = &g1; // COMPLIANT + l2 = g2; // COMPLIANT + l2 = &g3.m; // COMPLIANT + l2 = g3.p; // COMPLIANT + *l2 = l1; // COMPLIANT + *l2 = *l2; // COMPLIANT + *l2 = l3.m; // COMPLIANT + *l2 = *l3.p; // COMPLIANT + *l2 = t1; // COMPLIANT + *l2 = *t2; // COMPLIANT + *l2 = t3.m; // COMPLIANT + *l2 = *t3.p; // COMPLIANT + *l2 = g1; // COMPLIANT + *l2 = *g2; // COMPLIANT + *l2 = g3.m; // COMPLIANT + *l2 = *g3.p; // COMPLIANT + l3.m = l1; // COMPLIANT + l3.m = *l2; // COMPLIANT + l3.m = l3.m; // COMPLIANT + l3.m = *l3.p; // COMPLIANT + l3.m = t1; // COMPLIANT + l3.m = *t2; // COMPLIANT + l3.m = t3.m; // COMPLIANT + l3.m = *t3.p; // COMPLIANT + l3.m = g1; // COMPLIANT + l3.m = *g2; // COMPLIANT + l3.m = g3.m; // COMPLIANT + l3.m = *g3.p; // COMPLIANT + l3.p = &l1; // COMPLIANT + l3.p = l2; // COMPLIANT + l3.p = &l3.m; // COMPLIANT + l3.p = l3.p; // COMPLIANT + l3.p = &t1; // COMPLIANT + l3.p = t2; // COMPLIANT + l3.p = &t3.m; // COMPLIANT + l3.p = t3.p; // COMPLIANT + l3.p = &g1; // COMPLIANT + l3.p = g2; // COMPLIANT + l3.p = &g3.m; // COMPLIANT + l3.p = g3.p; // COMPLIANT + *l3.p = l1; // COMPLIANT + *l3.p = *l2; // COMPLIANT + *l3.p = l3.m; // COMPLIANT + *l3.p = *l3.p; // COMPLIANT + *l3.p = t1; // COMPLIANT + *l3.p = *t2; // COMPLIANT + *l3.p = t3.m; // COMPLIANT + *l3.p = *t3.p; // COMPLIANT + *l3.p = g1; // COMPLIANT + *l3.p = *g2; // COMPLIANT + *l3.p = g3.m; // COMPLIANT + *l3.p = *g3.p; // COMPLIANT + + // Storing local values in globals is covered by the shared query. +} + +tss_t tss1; +void f2() { + g1 = *(int *)tss_get(&tss1); // COMPLIANT + g2 = tss_get(&tss1); // NON-COMPLIANT + *g2 = *(int *)tss_get(&tss1); // COMPLIANT + g3.m = *(int *)tss_get(&tss1); // COMPLIANT + g3.p = tss_get(&tss1); // NON-COMPLIANT + *g3.p = *(int *)tss_get(&tss1); // COMPLIANT + g1 = ((s *)tss_get(&tss1))->m; // COMPLIANT + g1 = *((s *)tss_get(&tss1))->p; // COMPLIANT + g2 = &((s *)tss_get(&tss1))->m; // NON-COMPLIANT[false negative] + g2 = *((s *)tss_get(&tss1))->p; // COMPLIANT + *g2 = ((s *)tss_get(&tss1))->m; // COMPLIANT + *g2 = *((s *)tss_get(&tss1))->p; // COMPLIANT + g3.m = ((s *)tss_get(&tss1))->m; // COMPLIANT + g3.m = *((s *)tss_get(&tss1))->p; // COMPLIANT + g3.p = &((s *)tss_get(&tss1))->m; // NON-COMPLIANT[false negative] + g3.p = *((s *)tss_get(&tss1))->p; // COMPLIANT + *g3.p = ((s *)tss_get(&tss1))->m; // COMPLIANT + *g3.p = *((s *)tss_get(&tss1))->p; // COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-12/ExceptionHandlingFeaturesOfFenvhUsed.expected b/c/misra/test/rules/RULE-21-12/ExceptionHandlingFeaturesOfFenvhUsed.expected index 747b25a2c1..8032bf38cc 100644 --- a/c/misra/test/rules/RULE-21-12/ExceptionHandlingFeaturesOfFenvhUsed.expected +++ b/c/misra/test/rules/RULE-21-12/ExceptionHandlingFeaturesOfFenvhUsed.expected @@ -1,12 +1,16 @@ -| test.c:4:11:4:23 | call to feclearexcept | Call to banned function feclearexcept. | -| test.c:4:25:4:34 | FE_INVALID | Call to banned macro FE_INVALID. | -| test.c:6:3:6:17 | call to fegetexceptflag | Call to banned function fegetexceptflag. | -| test.c:6:24:6:36 | FE_ALL_EXCEPT | Call to banned macro FE_ALL_EXCEPT. | -| test.c:7:3:7:15 | call to feraiseexcept | Call to banned function feraiseexcept. | -| test.c:7:17:7:28 | FE_DIVBYZERO | Call to banned macro FE_DIVBYZERO. | -| test.c:8:3:8:15 | call to feraiseexcept | Call to banned function feraiseexcept. | -| test.c:8:17:8:27 | FE_OVERFLOW | Call to banned macro FE_OVERFLOW. | -| test.c:9:3:9:17 | call to fesetexceptflag | Call to banned function fesetexceptflag. | -| test.c:9:24:9:36 | FE_ALL_EXCEPT | Call to banned macro FE_ALL_EXCEPT. | -| test.c:10:3:10:14 | call to fetestexcept | Call to banned function fetestexcept. | -| test.c:10:16:10:27 | FE_UNDERFLOW | Call to banned macro FE_UNDERFLOW. | +| test.c:2:1:2:17 | #include | Include of banned header 'fenv.h'. | +| test.c:6:11:6:23 | call to feclearexcept | Call to banned function 'feclearexcept'. | +| test.c:6:25:6:34 | FE_INVALID | Expansion of banned macro 'FE_INVALID'. | +| test.c:8:3:8:17 | call to fegetexceptflag | Call to banned function 'fegetexceptflag'. | +| test.c:8:24:8:36 | FE_ALL_EXCEPT | Expansion of banned macro 'FE_ALL_EXCEPT'. | +| test.c:9:3:9:15 | call to feraiseexcept | Call to banned function 'feraiseexcept'. | +| test.c:9:17:9:28 | FE_DIVBYZERO | Expansion of banned macro 'FE_DIVBYZERO'. | +| test.c:10:3:10:15 | call to feraiseexcept | Call to banned function 'feraiseexcept'. | +| test.c:10:17:10:27 | FE_OVERFLOW | Expansion of banned macro 'FE_OVERFLOW'. | +| test.c:11:3:11:17 | call to fesetexceptflag | Call to banned function 'fesetexceptflag'. | +| test.c:11:24:11:36 | FE_ALL_EXCEPT | Expansion of banned macro 'FE_ALL_EXCEPT'. | +| test.c:12:3:12:14 | call to fetestexcept | Call to banned function 'fetestexcept'. | +| test.c:12:16:12:27 | FE_UNDERFLOW | Expansion of banned macro 'FE_UNDERFLOW'. | +| test.c:15:3:15:10 | call to fesetenv | Call to banned function 'fesetenv'. | +| test.c:16:3:16:13 | call to feupdateenv | Call to banned function 'feupdateenv'. | +| test.c:17:3:17:12 | call to fesetround | Call to banned function 'fesetround'. | diff --git a/c/misra/test/rules/RULE-21-12/test.c b/c/misra/test/rules/RULE-21-12/test.c index ae4d90a402..9a049c9ed8 100644 --- a/c/misra/test/rules/RULE-21-12/test.c +++ b/c/misra/test/rules/RULE-21-12/test.c @@ -1,4 +1,6 @@ +// NON_COMPLIANT: Cannot #include fenv.h. #include + void f2(); void f1() { int i = feclearexcept(FE_INVALID); // NON_COMPLIANT @@ -8,5 +10,10 @@ void f1() { feraiseexcept(FE_OVERFLOW); // NON_COMPLIANT fesetexceptflag(&i2, FE_ALL_EXCEPT); // NON_COMPLIANT fetestexcept(FE_UNDERFLOW); // NON_COMPLIANT - f2(); // COMPLIANT + fenv_t env; + fegetenv(&env); + fesetenv(&env); // NON_COMPLIANT + feupdateenv(&env); // NON_COMPLIANT + fesetround(0); // NON_COMPLIANT + f2(); // COMPLIANT } diff --git a/change_notes/2025-03-11-various-misra-amendments.md b/change_notes/2025-03-11-various-misra-amendments.md new file mode 100644 index 0000000000..99acdcc63a --- /dev/null +++ b/change_notes/2025-03-11-various-misra-amendments.md @@ -0,0 +1,8 @@ + - `DIR-4-9` - `FunctionOverFunctionLikeMacro.ql`: + - Macros with `_Generic` now no longer reported. + - `RULE-1-4` - `EmergentLanguageFeaturesUsed.ql`: + - Ban on usage of `_Generics` removed. + - `RULE-18-6` - `ThreadLocalObjectAddressCopiedToGlobalObject.ql`: + - New query added to detect thread local objects assigned to static storage duration objects. + - `RULE-21-12` - `ExceptionHandlingFeaturesOfFenvhUsed.ql`: + - Added reports for `#include`ing "fenv.h", and for using `fesetenv`, `feupdatenv`, and `fesetround`. \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/Emergent.qll b/cpp/common/src/codingstandards/cpp/Emergent.qll index 506d024bc9..3b3fbbaebd 100644 --- a/cpp/common/src/codingstandards/cpp/Emergent.qll +++ b/cpp/common/src/codingstandards/cpp/Emergent.qll @@ -30,8 +30,4 @@ module C11 { getBody() = "1" } } - - class GenericMacro extends EmergentLanguageFeature, Macro { - GenericMacro() { getBody().indexOf("_Generic") = 0 } - } } diff --git a/cpp/common/src/codingstandards/cpp/IrreplaceableFunctionLikeMacro.qll b/cpp/common/src/codingstandards/cpp/IrreplaceableFunctionLikeMacro.qll index af62cacfd3..e3d6df7e50 100644 --- a/cpp/common/src/codingstandards/cpp/IrreplaceableFunctionLikeMacro.qll +++ b/cpp/common/src/codingstandards/cpp/IrreplaceableFunctionLikeMacro.qll @@ -56,3 +56,9 @@ private class FunctionLikeMacroWithOperatorArgument extends IrreplaceableFunctio ) } } + +private class GenericMacro extends IrreplaceableFunctionLikeMacro { + GenericMacro() { + getBody().matches("%_Generic%") + } +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Pointers1.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Pointers1.qll index e35f0f3a88..725fe46904 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/Pointers1.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Pointers1.qll @@ -19,6 +19,7 @@ newtype Pointers1Query = TDoNotUseAdditionOrSubtractionOperatorsOnPointersQuery() or TNoMoreThanTwoLevelsOfPointerNestingInDeclarationsQuery() or TAutomaticStorageObjectAddressCopiedToOtherObjectQuery() or + TThreadLocalObjectAddressCopiedToGlobalObjectQuery() or TObjectWithNoPointerDereferenceShouldBeOpaqueQuery() or TPointerShouldPointToConstTypeWhenPossibleQuery() @@ -158,6 +159,15 @@ predicate isPointers1QueryMetadata(Query query, string queryId, string ruleId, s ruleId = "RULE-18-6" and category = "required" or + query = + // `Query` instance for the `threadLocalObjectAddressCopiedToGlobalObject` query + Pointers1Package::threadLocalObjectAddressCopiedToGlobalObjectQuery() and + queryId = + // `@id` for the `threadLocalObjectAddressCopiedToGlobalObject` query + "c/misra/thread-local-object-address-copied-to-global-object" and + ruleId = "RULE-18-6" and + category = "required" + or query = // `Query` instance for the `objectWithNoPointerDereferenceShouldBeOpaque` query Pointers1Package::objectWithNoPointerDereferenceShouldBeOpaqueQuery() and @@ -283,6 +293,13 @@ module Pointers1Package { TQueryC(TPointers1PackageQuery(TAutomaticStorageObjectAddressCopiedToOtherObjectQuery())) } + Query threadLocalObjectAddressCopiedToGlobalObjectQuery() { + //autogenerate `Query` type + result = + // `Query` type for `threadLocalObjectAddressCopiedToGlobalObject` query + TQueryC(TPointers1PackageQuery(TThreadLocalObjectAddressCopiedToGlobalObjectQuery())) + } + Query objectWithNoPointerDereferenceShouldBeOpaqueQuery() { //autogenerate `Query` type result = diff --git a/cpp/common/src/codingstandards/cpp/rules/donotcopyaddressofautostorageobjecttootherobject/DoNotCopyAddressOfAutoStorageObjectToOtherObject.qll b/cpp/common/src/codingstandards/cpp/rules/donotcopyaddressofautostorageobjecttootherobject/DoNotCopyAddressOfAutoStorageObjectToOtherObject.qll index 1b22fd5c3b..214f8e9aba 100644 --- a/cpp/common/src/codingstandards/cpp/rules/donotcopyaddressofautostorageobjecttootherobject/DoNotCopyAddressOfAutoStorageObjectToOtherObject.qll +++ b/cpp/common/src/codingstandards/cpp/rules/donotcopyaddressofautostorageobjecttootherobject/DoNotCopyAddressOfAutoStorageObjectToOtherObject.qll @@ -54,4 +54,4 @@ query predicate problems(Expr use, string message, Expr source, string srcStr) { srcStr = "parameter" ) ) -} +} \ No newline at end of file diff --git a/rule_packages/c/Pointers1.json b/rule_packages/c/Pointers1.json index 5f53d15702..1b54fc1fb6 100644 --- a/rule_packages/c/Pointers1.json +++ b/rule_packages/c/Pointers1.json @@ -305,6 +305,18 @@ "correctness", "external/misra/c/2012/third-edition-first-revision" ] + }, + { + "description": "Storing the address of a thread-local object in a global object will result in undefined behavior if the address is accessed after the relevant thread is terminated.", + "kind": "problem", + "name": "The address of an object with thread-local storage shall not be copied to a global object", + "precision": "very-high", + "severity": "error", + "short_name": "ThreadLocalObjectAddressCopiedToGlobalObject", + "tags": [ + "correctness", + "external/misra/c/2012/amendment3" + ] } ], "title": "The address of an object with automatic storage shall not be copied to another object that persists after the first object has ceased to exist" From f363371916d4e8aecf6540597c07985648d01dc0 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 11 Mar 2025 22:22:30 -0700 Subject: [PATCH 250/370] Update generic test expectation offsets post formatting --- ...ectionDoesntDependOnMacroArgument.expected | 6 +- ...ricSelectionNotExpandedFromAMacro.expected | 2 +- ...ectionNotFromMacroWithSideEffects.expected | 6 +- ...nericWithoutNonDefaultAssociation.expected | 4 +- ...icAssociationWithUnselectableType.expected | 26 +-- ...faultSelectionForPointerInGeneric.expected | 168 +++++++++--------- ...ressionWithIncorrectEssentialType.expected | 8 +- ...lidGenericMacroArgumentEvaluation.expected | 24 +-- ...ultGenericSelectionNotFirstOrLast.expected | 8 +- 9 files changed, 126 insertions(+), 126 deletions(-) diff --git a/c/misra/test/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.expected b/c/misra/test/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.expected index 2534e47012..a903827391 100644 --- a/c/misra/test/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.expected +++ b/c/misra/test/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.expected @@ -1,3 +1,3 @@ -| test.c:2:1:2:30 | #define M1 _Generic(1, int: 1) | Generic macro M1 uses controlling expr 1, which doesn't match any macro parameter. | -| test.c:4:1:4:33 | #define M2(X) _Generic(1, int: X) | Generic macro M2 uses controlling expr 1, which doesn't match any macro parameter. | -| test.c:18:1:18:38 | #define M9(X) g(_Generic((Y), int: 1)) | Generic macro M9 uses controlling expr (Y), which doesn't match any macro parameter. | +| test.c:2:1:2:31 | #define M1 _Generic(1, int : 1) | Generic macro M1 uses controlling expr 1, which doesn't match any macro parameter. | +| test.c:4:1:4:34 | #define M2(X) _Generic(1, int : X) | Generic macro M2 uses controlling expr 1, which doesn't match any macro parameter. | +| test.c:18:1:18:39 | #define M9(X) g(_Generic((Y), int : 1)) | Generic macro M9 uses controlling expr (Y), which doesn't match any macro parameter. | diff --git a/c/misra/test/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.expected b/c/misra/test/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.expected index 476a9320b8..aa3516354e 100644 --- a/c/misra/test/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.expected +++ b/c/misra/test/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.expected @@ -1 +1 @@ -| test.c:21:3:21:21 | _Generic | Generic expression with controlling expression $@ is not expanded froma macro | test.c:21:12:21:12 | 1 | 1 | +| test.c:21:3:21:22 | _Generic | Generic expression with controlling expression $@ is not expanded froma macro | test.c:21:12:21:12 | 1 | 1 | diff --git a/c/misra/test/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.expected b/c/misra/test/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.expected index 1abcb4f2bb..b0a970bbcf 100644 --- a/c/misra/test/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.expected +++ b/c/misra/test/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.expected @@ -1,3 +1,3 @@ -| test.c:4:1:4:37 | #define M2(X) _Generic((X)++, int: 1) | Generic selection macro M2 contains a side effect '... ++', which is not from macro invocation arguments. | test.c:4:1:4:37 | #define M2(X) _Generic((X)++, int: 1) | (ignored) | -| test.c:7:1:7:38 | #define M3(X) _Generic(l1++, int: (X)) | Generic selection macro M3 contains a side effect '... ++', which is not from macro invocation arguments. | test.c:7:1:7:38 | #define M3(X) _Generic(l1++, int: (X)) | (ignored) | -| test.c:42:1:44:24 | #define M5(X) static volatile l ## X; _Generic(l ## X, int: 1) | Generic selection in macro M5 contains an invocation-dependent side effect which is not from macro invocation arguments, for example $@. | test.c:47:3:47:7 | _Generic | side effect 'la' | +| test.c:4:1:4:38 | #define M2(X) _Generic((X)++, int : 1) | Generic selection macro M2 contains a side effect '... ++', which is not from macro invocation arguments. | test.c:4:1:4:38 | #define M2(X) _Generic((X)++, int : 1) | (ignored) | +| test.c:7:1:7:39 | #define M3(X) _Generic(l1++, int : (X)) | Generic selection macro M3 contains a side effect '... ++', which is not from macro invocation arguments. | test.c:7:1:7:39 | #define M3(X) _Generic(l1++, int : (X)) | (ignored) | +| test.c:42:1:44:25 | #define M5(X) static volatile l ## X; _Generic(l ## X, int : 1) | Generic selection in macro M5 contains an invocation-dependent side effect which is not from macro invocation arguments, for example $@. | test.c:47:3:47:7 | _Generic | side effect 'la' | diff --git a/c/misra/test/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.expected b/c/misra/test/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.expected index 50d6277e84..6a56026947 100644 --- a/c/misra/test/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.expected +++ b/c/misra/test/rules/RULE-23-3/GenericWithoutNonDefaultAssociation.expected @@ -1,2 +1,2 @@ -| test.c:2:1:2:35 | #define M1 _Generic(1, default: 1); | Generic selection contains no non-default association. | -| test.c:14:3:14:25 | _Generic | Generic selection contains no non-default association. | +| test.c:2:1:2:36 | #define M1 _Generic(1, default : 1); | Generic selection contains no non-default association. | +| test.c:14:3:14:26 | _Generic | Generic selection contains no non-default association. | diff --git a/c/misra/test/rules/RULE-23-4/GenericAssociationWithUnselectableType.expected b/c/misra/test/rules/RULE-23-4/GenericAssociationWithUnselectableType.expected index 27030fc768..132bb82979 100644 --- a/c/misra/test/rules/RULE-23-4/GenericAssociationWithUnselectableType.expected +++ b/c/misra/test/rules/RULE-23-4/GenericAssociationWithUnselectableType.expected @@ -1,13 +1,13 @@ -| test.c:11:18:11:18 | 1 | Generic selection uses unselectable type 'const int', due to qualifiers removed'. | test.c:11:18:11:18 | 1 | side effect | -| test.c:12:21:12:21 | 1 | Generic selection uses unselectable type 'volatile int', due to qualifiers removed'. | test.c:12:21:12:21 | 1 | side effect | -| test.c:13:20:13:20 | 1 | Generic selection uses unselectable type '_Atomic(int)', due to qualifiers removed'. | test.c:13:20:13:20 | 1 | side effect | -| test.c:16:27:16:27 | 1 | Generic selection uses unselectable type 'const volatile int', due to qualifiers removed'. | test.c:16:27:16:27 | 1 | side effect | -| test.c:18:18:18:18 | 1 | Generic selection uses unselectable type '(unnamed class/struct/union)', due to containing an anonymous struct or union type'. | test.c:18:18:18:18 | 1 | side effect | -| test.c:19:20:19:20 | 1 | Generic selection uses unselectable type 'struct *', due to containing an anonymous struct or union type'. | test.c:19:20:19:20 | 1 | side effect | -| test.c:24:17:24:17 | 1 | Generic selection uses unselectable type '(unnamed class/struct/union)', due to containing an anonymous struct or union type'. | test.c:24:17:24:17 | 1 | side effect | -| test.c:25:19:25:19 | 1 | Generic selection uses unselectable type 'union *', due to containing an anonymous struct or union type'. | test.c:25:19:25:19 | 1 | side effect | -| test.c:31:15:31:15 | 1 | Generic selection uses unselectable type 'int[3]', due to array-to-pointer decay'. | test.c:31:15:31:15 | 1 | side effect | -| test.c:40:1:40:53 | #define M1(X) _Generic((X), const int: 1, default: 0) | Generic in macro M1 has unselectable type 'const int', due to qualifiers removed. | test.c:40:1:40:53 | #define M1(X) _Generic((X), const int: 1, default: 0) | (ignored) | -| test.c:42:1:42:46 | #define M2(X) _Generic(1, X[3]: 1, default: 0) | Generic in macro M2 has an invocation-dependent unselectable type, for example $@. | test.c:49:3:49:10 | 1 | 'char[3]', due to array-to-pointer decay | -| test.c:52:3:52:15 | M3(X) | Generic resulting from invocation of macro $@ contains an unselectable type 'const int', due to qualifiers removed. | test.c:44:1:44:43 | #define M3(X) _Generic(1, X: 1, default: 0) | M3 | -| test.c:64:18:64:18 | 1 | Generic selection uses unselectable type 'const_int', due to qualifiers removed'. | test.c:64:18:64:18 | 1 | side effect | +| test.c:11:24:11:24 | 1 | Generic selection uses unselectable type 'const int', due to qualifiers removed'. | test.c:11:24:11:24 | 1 | side effect | +| test.c:12:27:12:27 | 1 | Generic selection uses unselectable type 'volatile int', due to qualifiers removed'. | test.c:12:27:12:27 | 1 | side effect | +| test.c:13:26:13:26 | 1 | Generic selection uses unselectable type '_Atomic(int)', due to qualifiers removed'. | test.c:13:26:13:26 | 1 | side effect | +| test.c:16:33:16:33 | 1 | Generic selection uses unselectable type 'const volatile int', due to qualifiers removed'. | test.c:16:33:16:33 | 1 | side effect | +| test.c:18:24:18:24 | 1 | Generic selection uses unselectable type '(unnamed class/struct/union)', due to containing an anonymous struct or union type'. | test.c:18:24:18:24 | 1 | side effect | +| test.c:19:26:19:26 | 1 | Generic selection uses unselectable type 'struct *', due to containing an anonymous struct or union type'. | test.c:19:26:19:26 | 1 | side effect | +| test.c:24:23:24:23 | 1 | Generic selection uses unselectable type '(unnamed class/struct/union)', due to containing an anonymous struct or union type'. | test.c:24:23:24:23 | 1 | side effect | +| test.c:25:25:25:25 | 1 | Generic selection uses unselectable type 'union *', due to containing an anonymous struct or union type'. | test.c:25:25:25:25 | 1 | side effect | +| test.c:31:21:31:21 | 1 | Generic selection uses unselectable type 'int[3]', due to array-to-pointer decay'. | test.c:31:21:31:21 | 1 | side effect | +| test.c:40:1:40:55 | #define M1(X) _Generic((X), const int : 1, default : 0) | Generic in macro M1 has unselectable type 'const int', due to qualifiers removed. | test.c:40:1:40:55 | #define M1(X) _Generic((X), const int : 1, default : 0) | (ignored) | +| test.c:42:1:42:48 | #define M2(X) _Generic(1, X[3] : 1, default : 0) | Generic in macro M2 has an invocation-dependent unselectable type, for example $@. | test.c:49:3:49:10 | 1 | 'char[3]', due to array-to-pointer decay | +| test.c:52:3:52:15 | M3(X) | Generic resulting from invocation of macro $@ contains an unselectable type 'const int', due to qualifiers removed. | test.c:44:1:44:45 | #define M3(X) _Generic(1, X : 1, default : 0) | M3 | +| test.c:64:24:64:24 | 1 | Generic selection uses unselectable type 'const_int', due to qualifiers removed'. | test.c:64:24:64:24 | 1 | side effect | diff --git a/c/misra/test/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.expected b/c/misra/test/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.expected index 994d55968c..3ed6b3f26b 100644 --- a/c/misra/test/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.expected +++ b/c/misra/test/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.expected @@ -1,84 +1,84 @@ -| test.c:41:3:41:44 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const int *. | test.c:41:3:41:44 | _Generic | | -| test.c:42:3:42:47 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to volatile int *. | test.c:42:3:42:47 | _Generic | | -| test.c:43:3:43:53 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile int *. | test.c:43:3:43:53 | _Generic | | -| test.c:44:3:44:39 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to void *. | test.c:44:3:44:39 | _Generic | | -| test.c:45:3:45:45 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const void *. | test.c:45:3:45:45 | _Generic | | -| test.c:46:3:46:54 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile void *. | test.c:46:3:46:54 | _Generic | | -| test.c:48:3:48:38 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to int *. | test.c:48:3:48:38 | _Generic | | -| test.c:50:3:50:39 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to void *. | test.c:50:3:50:39 | _Generic | | -| test.c:51:3:51:45 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const void *. | test.c:51:3:51:45 | _Generic | | -| test.c:52:3:52:54 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile void *. | test.c:52:3:52:54 | _Generic | | -| test.c:57:3:57:53 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile int *. | test.c:57:3:57:53 | _Generic | | -| test.c:59:3:59:38 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to int *. | test.c:59:3:59:38 | _Generic | | -| test.c:61:3:61:53 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to const volatile int *. | test.c:61:3:61:53 | _Generic | | -| test.c:62:3:62:39 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to void *. | test.c:62:3:62:39 | _Generic | | -| test.c:63:3:63:54 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to const volatile void *. | test.c:63:3:63:54 | _Generic | | -| test.c:69:3:69:38 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to int *. | test.c:69:3:69:38 | _Generic | | -| test.c:70:3:70:44 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const int *. | test.c:70:3:70:44 | _Generic | | -| test.c:71:3:71:47 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to volatile int *. | test.c:71:3:71:47 | _Generic | | -| test.c:73:3:73:39 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to void *. | test.c:73:3:73:39 | _Generic | | -| test.c:74:3:74:45 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const void *. | test.c:74:3:74:45 | _Generic | | -| test.c:75:3:75:54 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const volatile void *. | test.c:75:3:75:54 | _Generic | | -| test.c:77:3:77:38 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to int *. | test.c:77:3:77:38 | _Generic | | -| test.c:78:3:78:44 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to const int *. | test.c:78:3:78:44 | _Generic | | -| test.c:79:3:79:47 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to volatile int *. | test.c:79:3:79:47 | _Generic | | -| test.c:80:3:80:53 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to const volatile int *. | test.c:80:3:80:53 | _Generic | | -| test.c:82:3:82:45 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to const void *. | test.c:82:3:82:45 | _Generic | | -| test.c:83:3:83:54 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to const volatile void *. | test.c:83:3:83:54 | _Generic | | -| test.c:85:3:85:38 | _Generic | Generic matched default selection, as controlling argument type const void * does not undergo pointer conversion to int *. | test.c:85:3:85:38 | _Generic | | -| test.c:86:3:86:44 | _Generic | Generic matched default selection, as controlling argument type const void * does not undergo pointer conversion to const int *. | test.c:86:3:86:44 | _Generic | | -| test.c:87:3:87:53 | _Generic | Generic matched default selection, as controlling argument type const void * does not undergo pointer conversion to const volatile int *. | test.c:87:3:87:53 | _Generic | | -| test.c:88:3:88:39 | _Generic | Generic matched default selection, as controlling argument type const void * does not undergo pointer conversion to void *. | test.c:88:3:88:39 | _Generic | | -| test.c:90:3:90:54 | _Generic | Generic matched default selection, as controlling argument type const void * does not undergo pointer conversion to const volatile void *. | test.c:90:3:90:54 | _Generic | | -| test.c:94:3:94:38 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to int *. | test.c:94:3:94:38 | _Generic | | -| test.c:95:3:95:44 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to const int *. | test.c:95:3:95:44 | _Generic | | -| test.c:96:3:96:47 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to volatile int *. | test.c:96:3:96:47 | _Generic | | -| test.c:97:3:97:53 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to const volatile int *. | test.c:97:3:97:53 | _Generic | | -| test.c:98:3:98:39 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to void *. | test.c:98:3:98:39 | _Generic | | -| test.c:99:3:99:45 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to const void *. | test.c:99:3:99:45 | _Generic | | -| test.c:119:3:119:45 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const int *. | test.c:119:3:119:45 | _Generic | | -| test.c:120:3:120:48 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to volatile int *. | test.c:120:3:120:48 | _Generic | | -| test.c:121:3:121:54 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile int *. | test.c:121:3:121:54 | _Generic | | -| test.c:122:3:122:40 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to void *. | test.c:122:3:122:40 | _Generic | | -| test.c:123:3:123:46 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const void *. | test.c:123:3:123:46 | _Generic | | -| test.c:124:3:124:55 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile void *. | test.c:124:3:124:55 | _Generic | | -| test.c:126:3:126:39 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to int *. | test.c:126:3:126:39 | _Generic | | -| test.c:128:3:128:40 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to void *. | test.c:128:3:128:40 | _Generic | | -| test.c:129:3:129:46 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const void *. | test.c:129:3:129:46 | _Generic | | -| test.c:130:3:130:55 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile void *. | test.c:130:3:130:55 | _Generic | | -| test.c:135:3:135:54 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile int *. | test.c:135:3:135:54 | _Generic | | -| test.c:137:3:137:39 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to int *. | test.c:137:3:137:39 | _Generic | | -| test.c:139:3:139:54 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to const volatile int *. | test.c:139:3:139:54 | _Generic | | -| test.c:140:3:140:40 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to void *. | test.c:140:3:140:40 | _Generic | | -| test.c:141:3:141:55 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to const volatile void *. | test.c:141:3:141:55 | _Generic | | -| test.c:147:3:147:39 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to int *. | test.c:147:3:147:39 | _Generic | | -| test.c:148:3:148:45 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const int *. | test.c:148:3:148:45 | _Generic | | -| test.c:149:3:149:48 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to volatile int *. | test.c:149:3:149:48 | _Generic | | -| test.c:151:3:151:40 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to void *. | test.c:151:3:151:40 | _Generic | | -| test.c:152:3:152:46 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const void *. | test.c:152:3:152:46 | _Generic | | -| test.c:153:3:153:55 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const volatile void *. | test.c:153:3:153:55 | _Generic | | -| test.c:156:3:156:45 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const int *. | test.c:156:3:156:45 | _Generic | | -| test.c:157:3:157:48 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to volatile int *. | test.c:157:3:157:48 | _Generic | | -| test.c:158:3:158:54 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile int *. | test.c:158:3:158:54 | _Generic | | -| test.c:159:3:159:40 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to void *. | test.c:159:3:159:40 | _Generic | | -| test.c:160:3:160:46 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const void *. | test.c:160:3:160:46 | _Generic | | -| test.c:161:3:161:55 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile void *. | test.c:161:3:161:55 | _Generic | | -| test.c:163:3:163:39 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to int *. | test.c:163:3:163:39 | _Generic | | -| test.c:165:3:165:40 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to void *. | test.c:165:3:165:40 | _Generic | | -| test.c:166:3:166:46 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const void *. | test.c:166:3:166:46 | _Generic | | -| test.c:167:3:167:55 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile void *. | test.c:167:3:167:55 | _Generic | | -| test.c:172:3:172:54 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile int *. | test.c:172:3:172:54 | _Generic | | -| test.c:180:3:180:48 | _Generic | Generic matched default selection, as controlling argument type int(*)[3] does not undergo pointer conversion to int(*const)[3]. | test.c:180:3:180:48 | _Generic | | -| test.c:188:3:191:18 | _Generic | Generic matched default selection, as controlling argument type int(*)[3] does not undergo pointer conversion to int(*const)[3]. | test.c:188:3:191:18 | _Generic | | -| test.c:200:3:200:47 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to int *. | test.c:200:3:200:47 | _Generic | | -| test.c:201:3:201:47 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to void *. | test.c:201:3:201:47 | _Generic | | -| test.c:215:3:215:44 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const int *. | test.c:215:3:215:44 | _Generic | | -| test.c:216:3:216:46 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const int_t *. | test.c:216:3:216:46 | _Generic | | -| test.c:217:3:217:42 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to c_int_t *. | test.c:217:3:217:42 | _Generic | | -| test.c:221:3:221:45 | _Generic | Generic matched default selection, as controlling argument type int_t * does not undergo pointer conversion to const int *. | test.c:221:3:221:45 | _Generic | | -| test.c:222:3:222:47 | _Generic | Generic matched default selection, as controlling argument type int_t * does not undergo pointer conversion to const int_t *. | test.c:222:3:222:47 | _Generic | | -| test.c:223:3:223:43 | _Generic | Generic matched default selection, as controlling argument type int_t * does not undergo pointer conversion to c_int_t *. | test.c:223:3:223:43 | _Generic | | -| test.c:225:3:225:38 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to int *. | test.c:225:3:225:38 | _Generic | | -| test.c:226:3:226:40 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to int_t *. | test.c:226:3:226:40 | _Generic | | -| test.c:231:3:231:39 | _Generic | Generic matched default selection, as controlling argument type c_int_t * does not undergo pointer conversion to int *. | test.c:231:3:231:39 | _Generic | | -| test.c:232:3:232:41 | _Generic | Generic matched default selection, as controlling argument type c_int_t * does not undergo pointer conversion to int_t *. | test.c:232:3:232:41 | _Generic | | +| test.c:41:3:41:46 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const int *. | test.c:41:3:41:46 | _Generic | | +| test.c:42:3:42:49 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to volatile int *. | test.c:42:3:42:49 | _Generic | | +| test.c:43:3:43:55 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile int *. | test.c:43:3:43:55 | _Generic | | +| test.c:44:3:44:41 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to void *. | test.c:44:3:44:41 | _Generic | | +| test.c:45:3:45:47 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const void *. | test.c:45:3:45:47 | _Generic | | +| test.c:46:3:46:56 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile void *. | test.c:46:3:46:56 | _Generic | | +| test.c:48:3:48:40 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to int *. | test.c:48:3:48:40 | _Generic | | +| test.c:50:3:50:41 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to void *. | test.c:50:3:50:41 | _Generic | | +| test.c:51:3:51:47 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const void *. | test.c:51:3:51:47 | _Generic | | +| test.c:52:3:52:56 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile void *. | test.c:52:3:52:56 | _Generic | | +| test.c:57:3:57:55 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile int *. | test.c:57:3:57:55 | _Generic | | +| test.c:59:3:59:40 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to int *. | test.c:59:3:59:40 | _Generic | | +| test.c:61:3:61:55 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to const volatile int *. | test.c:61:3:61:55 | _Generic | | +| test.c:62:3:62:41 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to void *. | test.c:62:3:62:41 | _Generic | | +| test.c:63:3:63:56 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to const volatile void *. | test.c:63:3:63:56 | _Generic | | +| test.c:69:3:69:40 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to int *. | test.c:69:3:69:40 | _Generic | | +| test.c:70:3:70:46 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const int *. | test.c:70:3:70:46 | _Generic | | +| test.c:71:3:71:49 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to volatile int *. | test.c:71:3:71:49 | _Generic | | +| test.c:73:3:73:41 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to void *. | test.c:73:3:73:41 | _Generic | | +| test.c:74:3:74:47 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const void *. | test.c:74:3:74:47 | _Generic | | +| test.c:75:3:75:56 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const volatile void *. | test.c:75:3:75:56 | _Generic | | +| test.c:77:3:77:40 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to int *. | test.c:77:3:77:40 | _Generic | | +| test.c:78:3:78:46 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to const int *. | test.c:78:3:78:46 | _Generic | | +| test.c:79:3:79:49 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to volatile int *. | test.c:79:3:79:49 | _Generic | | +| test.c:80:3:80:55 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to const volatile int *. | test.c:80:3:80:55 | _Generic | | +| test.c:82:3:82:47 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to const void *. | test.c:82:3:82:47 | _Generic | | +| test.c:83:3:83:56 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to const volatile void *. | test.c:83:3:83:56 | _Generic | | +| test.c:85:3:85:40 | _Generic | Generic matched default selection, as controlling argument type const void * does not undergo pointer conversion to int *. | test.c:85:3:85:40 | _Generic | | +| test.c:86:3:86:46 | _Generic | Generic matched default selection, as controlling argument type const void * does not undergo pointer conversion to const int *. | test.c:86:3:86:46 | _Generic | | +| test.c:87:3:87:55 | _Generic | Generic matched default selection, as controlling argument type const void * does not undergo pointer conversion to const volatile int *. | test.c:87:3:87:55 | _Generic | | +| test.c:88:3:88:41 | _Generic | Generic matched default selection, as controlling argument type const void * does not undergo pointer conversion to void *. | test.c:88:3:88:41 | _Generic | | +| test.c:90:3:90:56 | _Generic | Generic matched default selection, as controlling argument type const void * does not undergo pointer conversion to const volatile void *. | test.c:90:3:90:56 | _Generic | | +| test.c:94:3:94:40 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to int *. | test.c:94:3:94:40 | _Generic | | +| test.c:95:3:95:46 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to const int *. | test.c:95:3:95:46 | _Generic | | +| test.c:96:3:96:49 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to volatile int *. | test.c:96:3:96:49 | _Generic | | +| test.c:97:3:97:55 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to const volatile int *. | test.c:97:3:97:55 | _Generic | | +| test.c:98:3:98:41 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to void *. | test.c:98:3:98:41 | _Generic | | +| test.c:99:3:99:47 | _Generic | Generic matched default selection, as controlling argument type const volatile void * does not undergo pointer conversion to const void *. | test.c:99:3:99:47 | _Generic | | +| test.c:119:3:119:47 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const int *. | test.c:119:3:119:47 | _Generic | | +| test.c:120:3:120:50 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to volatile int *. | test.c:120:3:120:50 | _Generic | | +| test.c:121:3:121:56 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile int *. | test.c:121:3:121:56 | _Generic | | +| test.c:122:3:122:42 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to void *. | test.c:122:3:122:42 | _Generic | | +| test.c:123:3:123:48 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const void *. | test.c:123:3:123:48 | _Generic | | +| test.c:124:3:124:57 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile void *. | test.c:124:3:124:57 | _Generic | | +| test.c:126:3:126:41 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to int *. | test.c:126:3:126:41 | _Generic | | +| test.c:128:3:128:42 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to void *. | test.c:128:3:128:42 | _Generic | | +| test.c:129:3:129:48 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const void *. | test.c:129:3:129:48 | _Generic | | +| test.c:130:3:130:57 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile void *. | test.c:130:3:130:57 | _Generic | | +| test.c:135:3:135:56 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile int *. | test.c:135:3:135:56 | _Generic | | +| test.c:137:3:137:41 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to int *. | test.c:137:3:137:41 | _Generic | | +| test.c:139:3:139:56 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to const volatile int *. | test.c:139:3:139:56 | _Generic | | +| test.c:140:3:140:42 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to void *. | test.c:140:3:140:42 | _Generic | | +| test.c:141:3:141:57 | _Generic | Generic matched default selection, as controlling argument type volatile int * does not undergo pointer conversion to const volatile void *. | test.c:141:3:141:57 | _Generic | | +| test.c:147:3:147:41 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to int *. | test.c:147:3:147:41 | _Generic | | +| test.c:148:3:148:47 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const int *. | test.c:148:3:148:47 | _Generic | | +| test.c:149:3:149:50 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to volatile int *. | test.c:149:3:149:50 | _Generic | | +| test.c:151:3:151:42 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to void *. | test.c:151:3:151:42 | _Generic | | +| test.c:152:3:152:48 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const void *. | test.c:152:3:152:48 | _Generic | | +| test.c:153:3:153:57 | _Generic | Generic matched default selection, as controlling argument type const volatile int * does not undergo pointer conversion to const volatile void *. | test.c:153:3:153:57 | _Generic | | +| test.c:156:3:156:47 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const int *. | test.c:156:3:156:47 | _Generic | | +| test.c:157:3:157:50 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to volatile int *. | test.c:157:3:157:50 | _Generic | | +| test.c:158:3:158:56 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile int *. | test.c:158:3:158:56 | _Generic | | +| test.c:159:3:159:42 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to void *. | test.c:159:3:159:42 | _Generic | | +| test.c:160:3:160:48 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const void *. | test.c:160:3:160:48 | _Generic | | +| test.c:161:3:161:57 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const volatile void *. | test.c:161:3:161:57 | _Generic | | +| test.c:163:3:163:41 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to int *. | test.c:163:3:163:41 | _Generic | | +| test.c:165:3:165:42 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to void *. | test.c:165:3:165:42 | _Generic | | +| test.c:166:3:166:48 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const void *. | test.c:166:3:166:48 | _Generic | | +| test.c:167:3:167:57 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile void *. | test.c:167:3:167:57 | _Generic | | +| test.c:172:3:172:56 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to const volatile int *. | test.c:172:3:172:56 | _Generic | | +| test.c:180:3:180:50 | _Generic | Generic matched default selection, as controlling argument type int(*)[3] does not undergo pointer conversion to int(*const)[3]. | test.c:180:3:180:50 | _Generic | | +| test.c:188:3:192:16 | _Generic | Generic matched default selection, as controlling argument type int(*)[3] does not undergo pointer conversion to int(*const)[3]. | test.c:188:3:192:16 | _Generic | | +| test.c:201:3:201:49 | _Generic | Generic matched default selection, as controlling argument type void * does not undergo pointer conversion to int *. | test.c:201:3:201:49 | _Generic | | +| test.c:202:3:202:49 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to void *. | test.c:202:3:202:49 | _Generic | | +| test.c:216:3:216:46 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const int *. | test.c:216:3:216:46 | _Generic | | +| test.c:217:3:217:48 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to const int_t *. | test.c:217:3:217:48 | _Generic | | +| test.c:218:3:218:44 | _Generic | Generic matched default selection, as controlling argument type int * does not undergo pointer conversion to c_int_t *. | test.c:218:3:218:44 | _Generic | | +| test.c:222:3:222:47 | _Generic | Generic matched default selection, as controlling argument type int_t * does not undergo pointer conversion to const int *. | test.c:222:3:222:47 | _Generic | | +| test.c:223:3:223:49 | _Generic | Generic matched default selection, as controlling argument type int_t * does not undergo pointer conversion to const int_t *. | test.c:223:3:223:49 | _Generic | | +| test.c:224:3:224:45 | _Generic | Generic matched default selection, as controlling argument type int_t * does not undergo pointer conversion to c_int_t *. | test.c:224:3:224:45 | _Generic | | +| test.c:226:3:226:40 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to int *. | test.c:226:3:226:40 | _Generic | | +| test.c:227:3:227:42 | _Generic | Generic matched default selection, as controlling argument type const int * does not undergo pointer conversion to int_t *. | test.c:227:3:227:42 | _Generic | | +| test.c:232:3:232:41 | _Generic | Generic matched default selection, as controlling argument type c_int_t * does not undergo pointer conversion to int *. | test.c:232:3:232:41 | _Generic | | +| test.c:233:3:233:43 | _Generic | Generic matched default selection, as controlling argument type c_int_t * does not undergo pointer conversion to int_t *. | test.c:233:3:233:43 | _Generic | | diff --git a/c/misra/test/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.expected b/c/misra/test/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.expected index 1cdcc82698..4f02d039ce 100644 --- a/c/misra/test/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.expected +++ b/c/misra/test/rules/RULE-23-6/GenericExpressionWithIncorrectEssentialType.expected @@ -1,4 +1,4 @@ -| test.c:11:3:11:8 | _Generic | Controlling expression in generic macro $@ has standard type (unnamed enum), which doesn't match its essential type (unnamed enum). | test.c:6:1:6:71 | #define M1(X) _Generic((X), int: 1, unsigned int: 1, short: 2, long: 3) | M1 | -| test.c:15:3:15:13 | _Generic | Controlling expression in generic macro $@ has standard type int, which doesn't match its essential type short. | test.c:6:1:6:71 | #define M1(X) _Generic((X), int: 1, unsigned int: 1, short: 2, long: 3) | M1 | -| test.c:18:3:18:23 | _Generic | Controlling expression in generic has standard type int, which doesn't match its essential type char. | test.c:18:3:18:23 | _Generic | | -| test.c:19:3:19:53 | _Generic | Controlling expression in generic has standard type int, which doesn't match its essential type short. | test.c:19:3:19:53 | _Generic | | +| test.c:11:3:11:8 | _Generic | Controlling expression in generic macro $@ has standard type (unnamed enum), which doesn't match its essential type (unnamed enum). | test.c:6:1:6:75 | #define M1(X) _Generic((X), int : 1, unsigned int : 1, short : 2, long : 3) | M1 | +| test.c:15:3:15:13 | _Generic | Controlling expression in generic macro $@ has standard type int, which doesn't match its essential type short. | test.c:6:1:6:75 | #define M1(X) _Generic((X), int : 1, unsigned int : 1, short : 2, long : 3) | M1 | +| test.c:18:3:18:24 | _Generic | Controlling expression in generic has standard type int, which doesn't match its essential type char. | test.c:18:3:18:24 | _Generic | | +| test.c:19:3:19:55 | _Generic | Controlling expression in generic has standard type int, which doesn't match its essential type short. | test.c:19:3:19:55 | _Generic | | diff --git a/c/misra/test/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.expected b/c/misra/test/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.expected index 57eecd6be8..47a8acce92 100644 --- a/c/misra/test/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.expected +++ b/c/misra/test/rules/RULE-23-7/InvalidGenericMacroArgumentEvaluation.expected @@ -1,12 +1,12 @@ -| test.c:9:1:9:51 | #define M3(X) _Generic((X), int: f1(X), default: 0) | Generic macro M3 may have unexpected behavior from side effects in parameter X, as it is not expanded in generic selection 2. | -| test.c:10:1:10:61 | #define M4(X) (X) + _Generic((X), int: f1(X), default: f1(X)) | Generic macro M4 may have unexpected behavior from side effects in parameter X, as it is expanded outside the generic selection and inside the generic selection. | -| test.c:11:1:11:61 | #define M5(X) _Generic((X), int: f1(X), default: f1(X)) + (X) | Generic macro M5 may have unexpected behavior from side effects in parameter X, as it is expanded outside the generic selection and inside the generic selection. | -| test.c:12:1:12:63 | #define M6(X) _Generic((X), int: f1((X) + (X)), default: f1(X)) | Generic macro M6 may have unexpected behavior from side effects in parameter X, as it is expanded in generic selection 1 more than once. | -| test.c:21:1:21:36 | #define M9(X) _Generic((X), int: f1) | Generic macro M9 may have unexpected behavior from side effects in parameter X, as it is not expanded in generic selection 1. | -| test.c:23:1:23:40 | #define M10(X) _Generic((X), int: f1(1)) | Generic macro M10 may have unexpected behavior from side effects in parameter X, as it is not expanded in generic selection 1. | -| test.c:32:1:32:58 | #define M12(X) _Generic((X) + (X), int: f1(X), default: 1) | Generic macro M12 may have unexpected behavior from side effects in parameter X, as it is not expanded in generic selection 2. | -| test.c:33:1:33:68 | #define M13(X) _Generic((X) + (X), int: f1(X), default: f1(X)) + (X) | Generic macro M13 may have unexpected behavior from side effects in parameter X, as it is expanded outside the generic selection and inside the generic selection. | -| test.c:43:1:43:77 | #define M17(X,Y) _Generic((X) + (Y), int: f2((X), (Y)), default: f2((X), 1)) | Generic macro M17 may have unexpected behavior from side effects in parameter Y, as it is not expanded in generic selection 2. | -| test.c:67:1:67:78 | #define M26(X) _Generic((X), int: IGNORE_2ND(X, X), default: IGNORE_2ND(X, X)) | Generic macro M26 may have unexpected behavior from side effects in parameter X, as it is expanded in generic selection 1 more than once. | -| test.c:67:1:67:78 | #define M26(X) _Generic((X), int: IGNORE_2ND(X, X), default: IGNORE_2ND(X, X)) | Generic macro M26 may have unexpected behavior from side effects in parameter X, as it is expanded in generic selection 2 more than once. | -| test.c:68:1:68:75 | #define M27(X) _Generic((X), int: f1(IGNORE(X)), default: f1(IGNORE(X)))(X) | Generic macro M27 may have unexpected behavior from side effects in parameter X, as it is expanded outside the generic selection and inside the generic selection. | +| test.c:9:1:9:53 | #define M3(X) _Generic((X), int : f1(X), default : 0) | Generic macro M3 may have unexpected behavior from side effects in parameter X, as it is not expanded in generic selection 2. | +| test.c:10:1:10:63 | #define M4(X) (X) + _Generic((X), int : f1(X), default : f1(X)) | Generic macro M4 may have unexpected behavior from side effects in parameter X, as it is expanded outside the generic selection and inside the generic selection. | +| test.c:11:1:11:63 | #define M5(X) _Generic((X), int : f1(X), default : f1(X)) + (X) | Generic macro M5 may have unexpected behavior from side effects in parameter X, as it is expanded outside the generic selection and inside the generic selection. | +| test.c:12:1:12:65 | #define M6(X) _Generic((X), int : f1((X) + (X)), default : f1(X)) | Generic macro M6 may have unexpected behavior from side effects in parameter X, as it is expanded in generic selection 1 more than once. | +| test.c:21:1:21:37 | #define M9(X) _Generic((X), int : f1) | Generic macro M9 may have unexpected behavior from side effects in parameter X, as it is not expanded in generic selection 1. | +| test.c:23:1:23:41 | #define M10(X) _Generic((X), int : f1(1)) | Generic macro M10 may have unexpected behavior from side effects in parameter X, as it is not expanded in generic selection 1. | +| test.c:32:1:32:60 | #define M12(X) _Generic((X) + (X), int : f1(X), default : 1) | Generic macro M12 may have unexpected behavior from side effects in parameter X, as it is not expanded in generic selection 2. | +| test.c:33:1:33:70 | #define M13(X) _Generic((X) + (X), int : f1(X), default : f1(X)) + (X) | Generic macro M13 may have unexpected behavior from side effects in parameter X, as it is expanded outside the generic selection and inside the generic selection. | +| test.c:43:1:43:79 | #define M17(X,Y) _Generic((X) + (Y), int : f2((X), (Y)), default : f2((X), 1)) | Generic macro M17 may have unexpected behavior from side effects in parameter Y, as it is not expanded in generic selection 2. | +| test.c:68:1:68:80 | #define M26(X) _Generic((X), int : IGNORE_2ND(X, X), default : IGNORE_2ND(X, X)) | Generic macro M26 may have unexpected behavior from side effects in parameter X, as it is expanded in generic selection 1 more than once. | +| test.c:68:1:68:80 | #define M26(X) _Generic((X), int : IGNORE_2ND(X, X), default : IGNORE_2ND(X, X)) | Generic macro M26 may have unexpected behavior from side effects in parameter X, as it is expanded in generic selection 2 more than once. | +| test.c:69:1:69:77 | #define M27(X) _Generic((X), int : f1(IGNORE(X)), default : f1(IGNORE(X)))(X) | Generic macro M27 may have unexpected behavior from side effects in parameter X, as it is expanded outside the generic selection and inside the generic selection. | diff --git a/c/misra/test/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.expected b/c/misra/test/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.expected index 5951834d00..fb407e2ff1 100644 --- a/c/misra/test/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.expected +++ b/c/misra/test/rules/RULE-23-8/DefaultGenericSelectionNotFirstOrLast.expected @@ -1,4 +1,4 @@ -| test.c:11:1:11:64 | #define M4(X) _Generic((X), int: 1, default: 0, unsigned int: 2) | Generic macro M4 has default as 2nd association, which is not first or last. | test.c:11:1:11:64 | #define M4(X) _Generic((X), int: 1, default: 0, unsigned int: 2) | (ignored) | -| test.c:17:1:17:60 | #define M5(__VA_ARGS__...) _Generic(0, __VA_ARGS__, default: 0, int: 1) | Generic macro M5 has a default association which is not first or last, for example $@. | test.c:28:5:28:23 | _Generic | 2nd | -| test.c:34:5:34:27 | M6(__VA_ARGS__...) | Generic macro $@, in this expansion, has default as 2nd association, which is not first or last. | test.c:19:1:19:48 | #define M6(__VA_ARGS__...) _Generic(0, __VA_ARGS__, int: 1) | M6 | -| test.c:44:5:44:52 | _Generic | Generic has default as 2nd association, which is not first or last. | test.c:44:5:44:52 | _Generic | | +| test.c:11:1:11:67 | #define M4(X) _Generic((X), int : 1, default : 0, unsigned int : 2) | Generic macro M4 has default as 2nd association, which is not first or last. | test.c:11:1:11:67 | #define M4(X) _Generic((X), int : 1, default : 0, unsigned int : 2) | (ignored) | +| test.c:17:1:17:62 | #define M5(__VA_ARGS__...) _Generic(0, __VA_ARGS__, default : 0, int : 1) | Generic macro M5 has a default association which is not first or last, for example $@. | test.c:30:3:30:22 | _Generic | 2nd | +| test.c:37:3:37:27 | M6(__VA_ARGS__...) | Generic macro $@, in this expansion, has default as 2nd association, which is not first or last. | test.c:19:1:19:49 | #define M6(__VA_ARGS__...) _Generic(0, __VA_ARGS__, int : 1) | M6 | +| test.c:48:3:48:53 | _Generic | Generic has default as 2nd association, which is not first or last. | test.c:48:3:48:53 | _Generic | | From a1142f3b4ef9e4768f5ffa5ea13025c92dcf2bf2 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 12 Mar 2025 11:38:15 -0700 Subject: [PATCH 251/370] reformat (and reformat generic with clang-format 11) --- .../rules/RULE-21-12/ExceptionHandlingFeaturesOfFenvhUsed.ql | 3 ++- c/misra/test/rules/DIR-4-9/test.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/c/misra/src/rules/RULE-21-12/ExceptionHandlingFeaturesOfFenvhUsed.ql b/c/misra/src/rules/RULE-21-12/ExceptionHandlingFeaturesOfFenvhUsed.ql index c70e71ea1a..b8d17de8aa 100644 --- a/c/misra/src/rules/RULE-21-12/ExceptionHandlingFeaturesOfFenvhUsed.ql +++ b/c/misra/src/rules/RULE-21-12/ExceptionHandlingFeaturesOfFenvhUsed.ql @@ -56,7 +56,8 @@ where name = m.getName() and message = "Expansion of banned macro" and // Exclude macro invocations expanded from other macro invocations from macros in fenv.h. - not element.(MacroInvocation).getParentInvocation().getMacro().getFile().getBaseName() = "fenv.h" + not element.(MacroInvocation).getParentInvocation().getMacro().getFile().getBaseName() = + "fenv.h" ) ) select element, message + " '" + name + "'." diff --git a/c/misra/test/rules/DIR-4-9/test.c b/c/misra/test/rules/DIR-4-9/test.c index c91e1a15a2..304c4bd004 100644 --- a/c/misra/test/rules/DIR-4-9/test.c +++ b/c/misra/test/rules/DIR-4-9/test.c @@ -10,7 +10,7 @@ #define MACRO8(x) "NOP" // COMPLIANT #define MACRO9() printf_custom("output = %d", 7) // NON_COMPLIANT #define MACRO10(x) // COMPLIANT -#define MACRO11(x) _Generic((x), int: 1, default: 0) // COMPLIANT +#define MACRO11(x) _Generic((x), int : 1, default : 0) // COMPLIANT #define MY_ASSERT(X) assert(X) // NON_COMPLIANT[FALSE_NEGATIVE] const char a1[MACRO2(1, 1) + 6]; From fd9fc0daf28ef5d8ecae6e065f25729ce2bbb2b5 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 12 Mar 2025 11:41:17 -0700 Subject: [PATCH 252/370] format IrreplaceableFunctionLikeMacro.qll --- .../codingstandards/cpp/IrreplaceableFunctionLikeMacro.qll | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/IrreplaceableFunctionLikeMacro.qll b/cpp/common/src/codingstandards/cpp/IrreplaceableFunctionLikeMacro.qll index e3d6df7e50..8daf129622 100644 --- a/cpp/common/src/codingstandards/cpp/IrreplaceableFunctionLikeMacro.qll +++ b/cpp/common/src/codingstandards/cpp/IrreplaceableFunctionLikeMacro.qll @@ -58,7 +58,5 @@ private class FunctionLikeMacroWithOperatorArgument extends IrreplaceableFunctio } private class GenericMacro extends IrreplaceableFunctionLikeMacro { - GenericMacro() { - getBody().matches("%_Generic%") - } -} \ No newline at end of file + GenericMacro() { getBody().matches("%_Generic%") } +} From fbbb19d74d534f680989888ac887f13b295b46f4 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 12 Mar 2025 11:44:17 -0700 Subject: [PATCH 253/370] Readd removed newline --- .../DoNotCopyAddressOfAutoStorageObjectToOtherObject.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/rules/donotcopyaddressofautostorageobjecttootherobject/DoNotCopyAddressOfAutoStorageObjectToOtherObject.qll b/cpp/common/src/codingstandards/cpp/rules/donotcopyaddressofautostorageobjecttootherobject/DoNotCopyAddressOfAutoStorageObjectToOtherObject.qll index 214f8e9aba..1b22fd5c3b 100644 --- a/cpp/common/src/codingstandards/cpp/rules/donotcopyaddressofautostorageobjecttootherobject/DoNotCopyAddressOfAutoStorageObjectToOtherObject.qll +++ b/cpp/common/src/codingstandards/cpp/rules/donotcopyaddressofautostorageobjecttootherobject/DoNotCopyAddressOfAutoStorageObjectToOtherObject.qll @@ -54,4 +54,4 @@ query predicate problems(Expr use, string message, Expr source, string srcStr) { srcStr = "parameter" ) ) -} \ No newline at end of file +} From 855310353f8f206cf0134c16d1b2b0a7852fad1c Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 12 Mar 2025 12:47:47 -0700 Subject: [PATCH 254/370] regenerate query metadata --- .../RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.ql | 2 +- .../rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/c/misra/src/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.ql b/c/misra/src/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.ql index 966b948d81..ec4631ef1b 100644 --- a/c/misra/src/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.ql +++ b/c/misra/src/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.ql @@ -2,7 +2,7 @@ * @id c/misra/thread-resource-disposed-before-threads-joined * @name RULE-22-15: Thread synchronization objects and thread-specific storage pointers shall not be disposed unsafely * @description Thread synchronization objects and thread-specific storage pointers shall not be - * destroyed until after all threads accessing them have terminated + * destroyed until after all threads accessing them have terminated. * @kind problem * @precision medium * @problem.severity error diff --git a/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql b/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql index 5b848f9e1e..4b70a21527 100644 --- a/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql +++ b/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql @@ -10,7 +10,7 @@ * correctness * concurrency * external/misra/c/2012/amendment4 - * audit + * external/misra/audit * external/misra/obligation/required */ From 433b887be461f785761ad1de2510d0f1f25363eb Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 12 Mar 2025 16:15:38 -0700 Subject: [PATCH 255/370] Address feedback --- c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql | 1 - rule_packages/c/SideEffects3.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql b/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql index 68f00be15f..c7fdde4539 100644 --- a/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql +++ b/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql @@ -37,7 +37,6 @@ class AtomicAccessInFullExpressionOrdering extends Ordering::Configuration { * Note, it may be accessed directly, or by passing its address into the std atomic functions. */ class AtomicVariableAccess extends VariableAccess { - pragma[noinline] AtomicVariableAccess() { getTarget().getType().hasSpecifier("atomic") } /* Get the `atomic_()` call this VarAccess occurs in. */ diff --git a/rule_packages/c/SideEffects3.json b/rule_packages/c/SideEffects3.json index 369f5db9ee..1ff29ec166 100644 --- a/rule_packages/c/SideEffects3.json +++ b/rule_packages/c/SideEffects3.json @@ -20,7 +20,7 @@ { "description": "The value of an atomic variable shall not depend on evaluation order and interleaving of threads.", "kind": "problem", - "name": "The value of an atomic variable depend on its evaluation order and interleave of threads", + "name": "The value of an atomic variable shall not depend on the evaluation order of interleaved threads", "precision": "very-high", "severity": "error", "short_name": "UnsequencedAtomicReads", From 79a1ca36b2295694857f3dacfc66297da6e8e943 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 12 Mar 2025 16:22:33 -0700 Subject: [PATCH 256/370] Regenerate query metadata --- c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql b/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql index c7fdde4539..b5e17fc934 100644 --- a/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql +++ b/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql @@ -1,6 +1,6 @@ /** * @id c/misra/unsequenced-atomic-reads - * @name RULE-13-2: The value of an atomic variable depend on its evaluation order and interleave of threads + * @name RULE-13-2: The value of an atomic variable shall not depend on the evaluation order of interleaved threads * @description The value of an atomic variable shall not depend on evaluation order and * interleaving of threads. * @kind problem From d70ea29a5e31cca97e6a2600fa994e4b5cc13bd0 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 12 Mar 2025 17:35:21 -0700 Subject: [PATCH 257/370] Address feedback --- .../AtomicQualifierAppliedToVoid.ql | 31 +++++++++++++++---- .../AtomicQualifierAppliedToVoid.expected | 5 +++ c/misra/test/rules/RULE-11-10/test.c | 12 ++++++- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/c/misra/src/rules/RULE-11-10/AtomicQualifierAppliedToVoid.ql b/c/misra/src/rules/RULE-11-10/AtomicQualifierAppliedToVoid.ql index d867241518..6440e84070 100644 --- a/c/misra/src/rules/RULE-11-10/AtomicQualifierAppliedToVoid.ql +++ b/c/misra/src/rules/RULE-11-10/AtomicQualifierAppliedToVoid.ql @@ -23,14 +23,33 @@ class AtomicVoidType extends Type { } } -Type getNestedType(Type root) { - result = root +predicate usesAtomicVoid(Type root) { + root instanceof AtomicVoidType or - exists(DerivedType derived | derived = root | result = getNestedType(derived.getBaseType())) + usesAtomicVoid(root.(DerivedType).getBaseType()) + or + usesAtomicVoid(root.(RoutineType).getReturnType()) + or + usesAtomicVoid(root.(RoutineType).getAParameterType()) + or + usesAtomicVoid(root.(FunctionPointerType).getReturnType()) + or + usesAtomicVoid(root.(FunctionPointerType).getAParameterType()) + or + usesAtomicVoid(root.(TypedefType).getBaseType()) +} + +class ExplicitType extends Type { + Element getDeclaration(string description) { + result.(DeclarationEntry).getType() = this and description = result.(DeclarationEntry).getName() + or + result.(CStyleCast).getType() = this and description = "Cast" + } } -from DeclarationEntry decl, AtomicVoidType atomicVoid +from Element decl, ExplicitType explicitType, string elementDescription where not isExcluded(decl, Declarations9Package::atomicQualifierAppliedToVoidQuery()) and - atomicVoid = getNestedType(decl.getType()) -select decl, decl.getName() + " declared with an atomic void type." + decl = explicitType.getDeclaration(elementDescription) and + usesAtomicVoid(explicitType) +select decl, elementDescription + " declared with an atomic void type." diff --git a/c/misra/test/rules/RULE-11-10/AtomicQualifierAppliedToVoid.expected b/c/misra/test/rules/RULE-11-10/AtomicQualifierAppliedToVoid.expected index e3a6746ae7..d38aac6455 100644 --- a/c/misra/test/rules/RULE-11-10/AtomicQualifierAppliedToVoid.expected +++ b/c/misra/test/rules/RULE-11-10/AtomicQualifierAppliedToVoid.expected @@ -1,3 +1,8 @@ | test.c:3:15:3:16 | definition of g3 | g3 declared with an atomic void type. | | test.c:10:17:10:18 | definition of m3 | m3 declared with an atomic void type. | | test.c:15:22:15:23 | definition of p2 | p2 declared with an atomic void type. | +| test.c:20:23:20:24 | declaration of f2 | f2 declared with an atomic void type. | +| test.c:21:25:21:26 | declaration of f3 | f3 declared with an atomic void type. | +| test.c:22:14:22:15 | declaration of f4 | f4 declared with an atomic void type. | +| test.c:23:16:23:17 | declaration of f5 | f5 declared with an atomic void type. | +| test.c:27:3:27:19 | (_Atomic(void) *)... | Cast declared with an atomic void type. | diff --git a/c/misra/test/rules/RULE-11-10/test.c b/c/misra/test/rules/RULE-11-10/test.c index e030345dde..cd95891865 100644 --- a/c/misra/test/rules/RULE-11-10/test.c +++ b/c/misra/test/rules/RULE-11-10/test.c @@ -15,4 +15,14 @@ void f(_Atomic int p1, // COMPLIANT _Atomic void *p2 // NON_COMPLIANT // _Atomic void p3[] // doesn't compile, even though it perhaps should as // it is adjusted to void*. -) {} \ No newline at end of file +) {} + +typedef _Atomic void *f2(void); // NON_COMPLIANT +typedef _Atomic void *(*f3)(void); // NON_COMPLIANT +typedef void f4(_Atomic void *); // NON_COMPLIANT +typedef void (*f5)(_Atomic void *); // NON_COMPLIANT + +void f6() { + (void *)0; // COMPLIANT + (_Atomic void *)0; // NON_COMPLIANT +} \ No newline at end of file From db1061ecdaf9c55c5c324c50a4a4c47b92050332 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 13 Mar 2025 10:06:12 -0700 Subject: [PATCH 258/370] Update codeql warning source location expectations --- .../test/rules/RULE-13-2/UnsequencedAtomicReads.expected | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected b/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected index 2231a83735..897dd68f30 100644 --- a/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected +++ b/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected @@ -1,5 +1,5 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:87,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:87,67-75) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:87,5-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:86,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:86,67-75) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:86,5-18) | test.c:44:12:44:18 | ... + ... | Atomic variable $@ has a $@ that is unsequenced with $@. | test.c:42:15:42:16 | a1 | a1 | test.c:44:12:44:13 | a1 | previous read | test.c:44:17:44:18 | a1 | another read | | test.c:46:3:46:37 | ... + ... | Atomic variable $@ has a $@ that is unsequenced with $@. | test.c:42:15:42:16 | a1 | a1 | test.c:46:16:46:17 | a1 | previous read | test.c:46:35:46:36 | a1 | another read | From 7e8ba849c90c960e9a5c38620d130ed5400679e2 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 13 Mar 2025 10:14:22 -0700 Subject: [PATCH 259/370] Fix merge --- rules.csv | 5 ----- 1 file changed, 5 deletions(-) diff --git a/rules.csv b/rules.csv index 0ea6db3c53..3f7961b630 100644 --- a/rules.csv +++ b/rules.csv @@ -677,13 +677,8 @@ c,MISRA-C-2012,RULE-9-2,Yes,Required,,,The initializer for an aggregate or union 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,No,Required,,,Where designated initializers are used to initialize an array object the size of the array shall be specified explicitly,,,Medium, -<<<<<<< HEAD c,MISRA-C-2012,RULE-9-6,Yes,Required,,,An initializer using chained designators shall not contain initializers without designators,,Declarations10,Hard, -c,MISRA-C-2012,RULE-9-7,Yes,Mandatory,,,Atomic objects shall be appropriately initialized before being accessed,,Concurrency6,Hard, -======= -c,MISRA-C-2012,RULE-9-6,Yes,Required,,,An initializer using chained designators shall not contain initializers without designators,,Declarations9,Hard, c,MISRA-C-2012,RULE-9-7,Yes,Mandatory,,,Atomic objects shall be appropriately initialized before being accessed,,Concurrency7,Hard, ->>>>>>> origin/main c,MISRA-C-2012,RULE-10-1,Yes,Required,,,Operands shall not be of an inappropriate essential type,,EssentialTypes,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,,EssentialTypes,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,,EssentialTypes,Hard, From f1944dbc9cefc94550e4e1b390e14f3fa91a2833 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 13 Mar 2025 10:16:31 -0700 Subject: [PATCH 260/370] Format cast test cases --- c/misra/test/rules/RULE-11-10/test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/misra/test/rules/RULE-11-10/test.c b/c/misra/test/rules/RULE-11-10/test.c index cd95891865..8f8e837b66 100644 --- a/c/misra/test/rules/RULE-11-10/test.c +++ b/c/misra/test/rules/RULE-11-10/test.c @@ -23,6 +23,6 @@ typedef void f4(_Atomic void *); // NON_COMPLIANT typedef void (*f5)(_Atomic void *); // NON_COMPLIANT void f6() { - (void *)0; // COMPLIANT + (void *)0; // COMPLIANT (_Atomic void *)0; // NON_COMPLIANT } \ No newline at end of file From 66d7f2bb1230a731fd339b65c5e2044bc13eeb34 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 14 Mar 2025 14:38:56 -0700 Subject: [PATCH 261/370] Don't report '//*comment' in RULE-3-1 --- .../RULE-3-1/CharacterSequencesAndUsedWithinAComment.ql | 2 +- .../CharacterSequencesAndUsedWithinAComment.expected | 1 + c/misra/test/rules/RULE-3-1/test.c | 6 ++++++ ...24-12-13-implement-misra-c-amendment4-rule-amendments.md | 3 ++- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/c/misra/src/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.ql b/c/misra/src/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.ql index 58d449a59b..af05bfe4bc 100644 --- a/c/misra/src/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.ql +++ b/c/misra/src/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.ql @@ -43,7 +43,7 @@ where not isExcluded(comment, SyntaxPackage::characterSequencesAndUsedWithinACommentQuery()) and ( exists(IllegalCommentSequence c | illegalSequence = c | - comment.getContents().indexOf(illegalSequence) > 0 + comment.getContents().indexOf(illegalSequence) > 1 ) or exists(IllegalCCommentRegexp c | illegalSequence = c.getDescription() | diff --git a/c/misra/test/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.expected b/c/misra/test/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.expected index 5008fb100d..3c4cab00b1 100644 --- a/c/misra/test/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.expected +++ b/c/misra/test/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.expected @@ -3,3 +3,4 @@ | test.c:21:1:21:7 | // /* | Comment contains an illegal sequence '/*' | | test.c:30:1:30:27 | /* https://github.com // */ | Comment contains an illegal sequence '//' | | test.c:33:1:33:60 | /* a://b, a://b., ://a.b, a://b., a://.b, ://, a://, ://b */ | Comment contains an illegal sequence '//' | +| test.c:42:1:42:8 | ///* foo | Comment contains an illegal sequence '/*' | diff --git a/c/misra/test/rules/RULE-3-1/test.c b/c/misra/test/rules/RULE-3-1/test.c index ad61fd0f91..fd7a6574dd 100644 --- a/c/misra/test/rules/RULE-3-1/test.c +++ b/c/misra/test/rules/RULE-3-1/test.c @@ -35,4 +35,10 @@ // COMPLIANT // https://github.com +// COMPLIANT +//* foo + +// NON_COMPLIANT +///* foo + void f(){} \ No newline at end of file diff --git a/change_notes/2024-12-13-implement-misra-c-amendment4-rule-amendments.md b/change_notes/2024-12-13-implement-misra-c-amendment4-rule-amendments.md index a8fbd282d8..b168ccaf78 100644 --- a/change_notes/2024-12-13-implement-misra-c-amendment4-rule-amendments.md +++ b/change_notes/2024-12-13-implement-misra-c-amendment4-rule-amendments.md @@ -7,4 +7,5 @@ - `RULE-13-2` - `UnsequencedAtomicReads.ql` - New query to find expressions which read an atomic variable more than once between sequence points, to address new case from MISRA-C 2012 Amendment 4. - `RULE-3-1` - `CharacterSequencesAndUsedWithinAComment.ql` - - Add exception allowing URLs inside of cpp-style `/* ... */` comments, in compliance with MISRA-C 2012 Amendment 4 \ No newline at end of file + - Add exception allowing URLs inside of cpp-style `/* ... */` comments, in compliance with MISRA-C 2012 Amendment 4. + - No longer report cases of `//*some comment` in this rule. \ No newline at end of file From c55a173fae2d1d2fd1d4b15616d9cdd61acff3cc Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 14 Mar 2025 17:36:13 -0700 Subject: [PATCH 262/370] First round of feedback --- ...025-1-04-misra-c-technical-corrigenda-2.md | 2 +- ...nterArithmeticToAddressDifferentArrays.qll | 23 +++++++++++++------ .../test.cpp | 12 +++++++--- rule_packages/c/Statements5.json | 3 +++ 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/change_notes/2025-1-04-misra-c-technical-corrigenda-2.md b/change_notes/2025-1-04-misra-c-technical-corrigenda-2.md index be037074f6..6849951810 100644 --- a/change_notes/2025-1-04-misra-c-technical-corrigenda-2.md +++ b/change_notes/2025-1-04-misra-c-technical-corrigenda-2.md @@ -1,6 +1,6 @@ - `RULE-8-3` - `DeclarationsOfAFunctionSameNameAndType.ql`: - Implement new exception, unnamed parameters are not covered by this rule. - - `RULE-10-2` - `AdditionSubtractionOnEssentiallCharType.ql`: + - `RULE-10-2` - `AdditionSubtractionOnEssentiallyCharType.ql`: - Disallow `+` and `-` operations with an essentially char type and other types larger than int type. - Note, this change affects the essential type of such expressions, which may affect other essential types rules. - `RULE-18-1`, `M5-0-16` - `PointerAndDerivedPointerMustAddressSameArray.ql`, `PointerAndDerivedPointerAccessDifferentArray.ql`: diff --git a/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll b/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll index 5a45ff703e..2b11291293 100644 --- a/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll +++ b/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll @@ -104,6 +104,16 @@ class CastedToBytePointer extends ArrayLikeAccess, Conversion { } } + predicate pointerRecastBarrier(DataFlow::Node barrier) { + // Casting to a differently sized pointer + exists(CStyleCast cast, Expr casted | + cast.getExpr() = casted and casted = barrier.asConvertedExpr() + | + not casted.getType().(PointerType).getBaseType().getSize() = + cast.getType().(PointerType).getBaseType().getSize() + ) + } + /** * A data-flow configuration that tracks access to an array to type to an array index expression. * This is used to determine possible pointer to array creations. @@ -111,7 +121,11 @@ class CastedToBytePointer extends ArrayLikeAccess, Conversion { module ByteArrayToArrayExprConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { exists(CastedToBytePointer a | a.getNode() = source) } - // TODO: casting to different size pointed-to-type invalidates + predicate isBarrier(DataFlow::Node barrier) { + // Casting to a differently sized pointer invalidates this analysis. + pointerRecastBarrier(barrier) + } + predicate isSink(DataFlow::Node sink) { exists(ArrayExpr c | c.getArrayBase() = sink.asExpr()) } } @@ -126,12 +140,7 @@ module ArrayToArrayExprConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node barrier) { // Casting to a differently sized pointer invalidates this analysis. - exists(CStyleCast cast, Expr casted | - cast.getExpr() = casted and casted = barrier.asConvertedExpr() - | - not casted.getType().(PointerType).getBaseType().getSize() = - cast.getType().(PointerType).getBaseType().getSize() - ) + pointerRecastBarrier(barrier) } predicate isSink(DataFlow::Node sink) { exists(ArrayExpr c | c.getArrayBase() = sink.asExpr()) } diff --git a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp index 3a86d7963e..d9874bfb29 100644 --- a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp +++ b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp @@ -40,8 +40,14 @@ void f1() { void *p22 = &p21[0]; // COMPLIANT void *p23 = &p21[100]; // NON_COMPLIANT[FALSE_NEGATIVE] + // Casting a byte pointer to a differently sized type that isn't char + // invalidates analysis + long *p24 = (long *)p15; + void *p25 = &p24[0]; // COMPLIANT + void *p26 = &p24[100]; // NON_COMPLIANT[FALSE_NEGATIVE] + // Void pointers have size zero and can't be analyzed. - void *p24 = 0; - unsigned char *p25 = (unsigned char *)p24; - void *p26 = &p25[100]; // COMPLIANT + void *p27 = 0; + unsigned char *p28 = (unsigned char *)p27; + void *p29 = &p28[100]; // COMPLIANT } \ No newline at end of file diff --git a/rule_packages/c/Statements5.json b/rule_packages/c/Statements5.json index 329819b61f..03380f4897 100644 --- a/rule_packages/c/Statements5.json +++ b/rule_packages/c/Statements5.json @@ -20,6 +20,9 @@ ] } ], + "implementation_scope": { + "description": "Not all invariant logical expressions which contain dynamic values are detected to be invariant, for instance, `x < 3 && x > 5` where x does not have a statically known value." + }, "title": "Controlling expressions shall not be invariant" }, "RULE-15-5": { From fb6eaaa9eed6d8d377849af6ef47aa17eec7d524 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 14 Mar 2025 17:56:28 -0700 Subject: [PATCH 263/370] Format --- ...interArithmeticToAddressDifferentArrays.qll | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll b/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll index 2b11291293..2b788ea6fb 100644 --- a/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll +++ b/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll @@ -104,15 +104,15 @@ class CastedToBytePointer extends ArrayLikeAccess, Conversion { } } - predicate pointerRecastBarrier(DataFlow::Node barrier) { - // Casting to a differently sized pointer - exists(CStyleCast cast, Expr casted | - cast.getExpr() = casted and casted = barrier.asConvertedExpr() - | - not casted.getType().(PointerType).getBaseType().getSize() = - cast.getType().(PointerType).getBaseType().getSize() - ) - } +predicate pointerRecastBarrier(DataFlow::Node barrier) { + // Casting to a differently sized pointer + exists(CStyleCast cast, Expr casted | + cast.getExpr() = casted and casted = barrier.asConvertedExpr() + | + not casted.getType().(PointerType).getBaseType().getSize() = + cast.getType().(PointerType).getBaseType().getSize() + ) +} /** * A data-flow configuration that tracks access to an array to type to an array index expression. From 6acd87740d00f8130b944a08674ec7b5525c19c3 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 14 Mar 2025 18:02:51 -0700 Subject: [PATCH 264/370] Format essentialTypes --- .../src/codingstandards/c/misra/EssentialTypes.qll | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll index 05bfef87fa..de6d43e2c5 100644 --- a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll +++ b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll @@ -357,8 +357,9 @@ class EssentialBinaryOperationSubjectToUsualConversions extends EssentialExpr, B */ class EssentialAddExpr extends EssentialBinaryOperationSubjectToUsualConversions, AddExpr { override Type getEssentialType() { - exists(Type otherOperandType, - EssentialTypeCategory operandTypeCategory, EssentialTypeCategory otherOperandTypeCategory, int intTypeSize + exists( + Type otherOperandType, EssentialTypeCategory operandTypeCategory, + EssentialTypeCategory otherOperandTypeCategory, int intTypeSize | operandTypeCategory = getEssentialTypeCategory(getEssentialType(getAnOperand())) and otherOperandType = getEssentialType(getAnOperand()) and @@ -381,10 +382,8 @@ class EssentialAddExpr extends EssentialBinaryOperationSubjectToUsualConversions class EssentialSubExpr extends EssentialBinaryOperationSubjectToUsualConversions, SubExpr { override Type getEssentialType() { exists( - EssentialTypeCategory leftEssentialTypeCategory, - Type rightEssentialType, - EssentialTypeCategory rightEssentialTypeCategory, - int intTypeSize + EssentialTypeCategory leftEssentialTypeCategory, Type rightEssentialType, + EssentialTypeCategory rightEssentialTypeCategory, int intTypeSize | leftEssentialTypeCategory = getEssentialTypeCategory(getEssentialType(getLeftOperand())) and rightEssentialType = getEssentialType(getRightOperand()) and From 3e6cf77c8f653d50776c9f0afc54c5abcc818ef5 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 17 Mar 2025 17:24:37 -0700 Subject: [PATCH 265/370] Update cast to byte pointer getName() --- ...DoNotUsePointerArithmeticToAddressDifferentArrays.qll | 9 +-------- ...UsePointerArithmeticToAddressDifferentArrays.expected | 4 ++-- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll b/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll index 2b788ea6fb..5d3a7e1cda 100644 --- a/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll +++ b/cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll @@ -80,14 +80,7 @@ class CastedToBytePointer extends ArrayLikeAccess, Conversion { override Element getElement() { result = this } - override string getName() { - result = "cast to btye pointer " + this.toString() - or - exists(Cast cast | - cast.getExpr() = this and - result = cast.getType().(PointerType).getBaseType().toString() - ) - } + override string getName() { result = "cast to byte pointer" } override int getSize() { result = size } diff --git a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected index 5bb4881b81..31ff47e55c 100644 --- a/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected +++ b/cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.expected @@ -4,5 +4,5 @@ | test.cpp:11:8:11:11 | ... -- | Array pointer p7 points 1 element past the end of $@. | test.cpp:2:7:2:8 | l1 | l1 | | test.cpp:12:8:12:9 | p3 | Array pointer p8 points 1 element past the end of $@. | test.cpp:2:7:2:8 | l1 | l1 | | test.cpp:25:15:25:21 | & ... | Array pointer p14 points 1 element past the end of $@. | test.cpp:2:7:2:8 | l1 | l1 | -| test.cpp:30:15:30:21 | & ... | Array pointer p17 points 1 element past the end of $@. | test.cpp:28:24:28:42 | (unsigned char *)... | cast to btye pointer (unsigned char *)... | -| test.cpp:35:15:35:21 | & ... | Array pointer p20 points 1 element past the end of $@. | test.cpp:33:24:33:43 | (unsigned char *)... | cast to btye pointer (unsigned char *)... | +| test.cpp:30:15:30:21 | & ... | Array pointer p17 points 1 element past the end of $@. | test.cpp:28:24:28:42 | (unsigned char *)... | cast to byte pointer | +| test.cpp:35:15:35:21 | & ... | Array pointer p20 points 1 element past the end of $@. | test.cpp:33:24:33:43 | (unsigned char *)... | cast to byte pointer | From ded47aa1e71b16ac85be2acdaddfe5777fd2c508 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 20 Mar 2025 15:32:02 -0700 Subject: [PATCH 266/370] Address feedback --- .../PossibleMisuseOfUndetectedInfinity.ql | 35 +++--- .../DIR-4-15/PossibleMisuseOfUndetectedNaN.ql | 95 ++++------------ ...ossibleMisuseOfUndetectedInfinity.expected | 52 ++++----- .../PossibleMisuseOfUndetectedNaN.expected | 64 +++++------ .../src/codingstandards/cpp/FloatingPoint.qll | 72 ++++++++++++- .../cpp/RestrictedRangeAnalysis.qll | 101 +++++++++++------- .../cpp/exclusions/c/FloatingTypes2.qll | 2 +- .../UncheckedRangeDomainPoleErrors.qll | 53 +-------- .../generate_rules/coding_standards_utils.py | 4 +- 9 files changed, 230 insertions(+), 248 deletions(-) diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql index 3d54b4f829..812e9fe1e2 100644 --- a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql @@ -87,7 +87,6 @@ module InvalidInfinityUsage implements DataFlow::ConfigSig { class InvalidInfinityUsage extends DataFlow::Node { string description; - string infinityDescription; InvalidInfinityUsage() { // Case 2: NaNs and infinities shall not be cast to integers @@ -95,22 +94,18 @@ class InvalidInfinityUsage extends DataFlow::Node { asExpr() = c.getUnconverted() and c.getExpr().getType() instanceof FloatingPointType and c.getType() instanceof IntegralType and - description = "$@ casted to integer." and - infinityDescription = "Possibly infinite float value" + description = "cast to integer." ) or // Case 3: Infinities shall not underflow or otherwise produce finite values exists(BinaryOperation op | asExpr() = op.getRightOperand() and op.getOperator() = "/" and - description = "Division operation may silently underflow and produce zero, as the divisor $@." and - infinityDescription = "may be an infinite float value" + description = "divisor, which would silently underflow and produce zero." ) } string getDescription() { result = description } - - string getInfinityDescription() { result = infinityDescription } } module InvalidInfinityFlow = DataFlow::Global; @@ -119,7 +114,8 @@ import InvalidInfinityFlow::PathGraph from Element elem, InvalidInfinityFlow::PathNode source, InvalidInfinityFlow::PathNode sink, - InvalidInfinityUsage usage, Expr sourceExpr, Element extra, string extraString + InvalidInfinityUsage usage, Expr sourceExpr, string sourceString, Function function, + string computedInFunction where elem = MacroUnwrapper::unwrapElement(sink.getNode().asExpr()) and not InvalidInfinityFlow::PathGraph::edges(_, source, _, _) and @@ -129,19 +125,18 @@ where not usage.asExpr().isFromTemplateInstantiation(_) and usage = sink.getNode() and sourceExpr = source.getNode().asExpr() and + function = sourceExpr.getEnclosingFunction() and InvalidInfinityFlow::flow(source.getNode(), usage) and ( if not sourceExpr.getEnclosingFunction() = usage.asExpr().getEnclosingFunction() - then - extraString = - usage.getInfinityDescription() + " computed in function " + - sourceExpr.getEnclosingFunction().getName() and - extra = sourceExpr.getEnclosingFunction() - else ( - extra = sourceExpr and - if sourceExpr instanceof DivExpr - then extraString = usage.getInfinityDescription() + " from division by zero" - else extraString = usage.getInfinityDescription() - ) + then computedInFunction = "computed in function $@ " + else computedInFunction = "" + ) and + ( + if sourceExpr instanceof DivExpr + then sourceString = "from division by zero" + else sourceString = sourceExpr.toString() ) -select elem, source, sink, usage.getDescription(), extra, extraString +select elem, source, sink, + "Possibly infinite float value $@ " + computedInFunction + "flows to " + usage.getDescription(), + sourceExpr, sourceString, function, function.getName() diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql index 2835a454d9..e1b6762ada 100644 --- a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql @@ -1,5 +1,5 @@ /** - * @id c/misra/possible-misuse-of-undetected-na-n + * @id c/misra/possible-misuse-of-undetected-nan * @name DIR-4-15: Evaluation of floating-point expressions shall not lead to the undetected generation of NaNs * @description Evaluation of floating-point expressions shall not lead to the undetected generation * of NaNs. @@ -23,58 +23,6 @@ import semmle.code.cpp.dataflow.new.DataFlow import semmle.code.cpp.dataflow.new.TaintTracking import semmle.code.cpp.controlflow.Dominance -bindingset[name] -Function getMathVariants(string name) { result.hasGlobalOrStdName([name, name + "f", name + "l"]) } - -predicate hasDomainError(FunctionCall fc, string description) { - exists(Function functionWithDomainError | fc.getTarget() = functionWithDomainError | - functionWithDomainError = [getMathVariants(["acos", "asin", "atanh"])] and - not ( - RestrictedRangeAnalysis::upperBound(fc.getArgument(0)) <= 1.0 and - RestrictedRangeAnalysis::lowerBound(fc.getArgument(0)) >= -1.0 - ) and - description = - "the argument has a range " + RestrictedRangeAnalysis::lowerBound(fc.getArgument(0)) + "..." + - RestrictedRangeAnalysis::upperBound(fc.getArgument(0)) + - " which is outside the domain of this function (-1.0...1.0)" - or - functionWithDomainError = getMathVariants(["atan2", "pow"]) and - ( - exprMayEqualZero(fc.getArgument(0)) and - exprMayEqualZero(fc.getArgument(1)) and - description = "both arguments are equal to zero" - ) - or - functionWithDomainError = getMathVariants("pow") and - ( - RestrictedRangeAnalysis::upperBound(fc.getArgument(0)) < 0.0 and - RestrictedRangeAnalysis::upperBound(fc.getArgument(1)) < 0.0 and - description = "both arguments are less than zero" - ) - or - functionWithDomainError = getMathVariants("acosh") and - RestrictedRangeAnalysis::upperBound(fc.getArgument(0)) < 1.0 and - description = "argument is less than 1" - or - //pole error is the same as domain for logb and tgamma (but not ilogb - no pole error exists) - functionWithDomainError = getMathVariants(["ilogb", "logb", "tgamma"]) and - exprMayEqualZero(fc.getArgument(0)) and - description = "argument is equal to zero" - or - functionWithDomainError = getMathVariants(["log", "log10", "log2", "sqrt"]) and - RestrictedRangeAnalysis::upperBound(fc.getArgument(0)) < 0.0 and - description = "argument is negative" - or - functionWithDomainError = getMathVariants("log1p") and - RestrictedRangeAnalysis::upperBound(fc.getArgument(0)) < -1.0 and - description = "argument is less than 1" - or - functionWithDomainError = getMathVariants("fmod") and - exprMayEqualZero(fc.getArgument(1)) and - description = "y is 0" - ) -} - abstract class PotentiallyNaNExpr extends Expr { abstract string getReason(); } @@ -82,7 +30,7 @@ abstract class PotentiallyNaNExpr extends Expr { class DomainErrorFunctionCall extends FunctionCall, PotentiallyNaNExpr { string reason; - DomainErrorFunctionCall() { hasDomainError(this, reason) } + DomainErrorFunctionCall() { RestrictedDomainError::hasDomainError(this, reason) } override string getReason() { result = reason } } @@ -116,8 +64,13 @@ class InvalidOperationExpr extends BinaryOperation, PotentiallyNaNExpr { or // 7.1.3: multiplication of zero by infinity getOperator() = "*" and - exprMayEqualZero(getAnOperand()) and - exprMayEqualInfinity(getAnOperand(), _) and + exists(Expr zeroOp, Expr infinityOp | + zeroOp = getAnOperand() and + infinityOp = getAnOperand() and + not zeroOp = infinityOp and + exprMayEqualZero(zeroOp) and + exprMayEqualInfinity(infinityOp, _) + ) and reason = "from multiplication of zero by infinity" or // 7.1.4: Division of zero by zero, or infinity by infinity @@ -199,15 +152,13 @@ module InvalidNaNUsage implements DataFlow::ConfigSig { class InvalidNaNUsage extends DataFlow::Node { string description; - string nanDescription; InvalidNaNUsage() { // Case 1: NaNs shall not be compared, except to themselves exists(ComparisonOperation cmp | this.asExpr() = cmp.getAnOperand() and not hashCons(cmp.getLeftOperand()) = hashCons(cmp.getRightOperand()) and - description = "Comparison involving a $@, which always evaluates to false." and - nanDescription = "possibly NaN float value" + description = "comparison, which would always evaluate to false." ) or // Case 2: NaNs and infinities shall not be cast to integers @@ -215,14 +166,11 @@ class InvalidNaNUsage extends DataFlow::Node { this.asExpr() = c.getUnconverted() and c.getExpr().getType() instanceof FloatingPointType and c.getType() instanceof IntegralType and - description = "$@ casted to integer." and - nanDescription = "Possibly NaN float value" + description = "a cast to integer." ) } string getDescription() { result = description } - - string getNaNDescription() { result = nanDescription } } module InvalidNaNFlow = DataFlow::Global; @@ -231,7 +179,8 @@ import InvalidNaNFlow::PathGraph from Element elem, InvalidNaNFlow::PathNode source, InvalidNaNFlow::PathNode sink, - InvalidNaNUsage usage, Expr sourceExpr, string sourceString, Element extra, string extraString + InvalidNaNUsage usage, Expr sourceExpr, string sourceString, Function function, + string computedInFunction where not InvalidNaNFlow::PathGraph::edges(_, source, _, _) and not InvalidNaNFlow::PathGraph::edges(sink, _, _, _) and @@ -240,18 +189,14 @@ where elem = MacroUnwrapper::unwrapElement(sink.getNode().asExpr()) and usage = sink.getNode() and sourceExpr = source.getNode().asExpr() and - sourceString = " (" + source.getNode().asExpr().(PotentiallyNaNExpr).getReason() + ")" and + sourceString = source.getNode().asExpr().(PotentiallyNaNExpr).getReason() and + function = sourceExpr.getEnclosingFunction() and InvalidNaNFlow::flow(source.getNode(), usage) and ( if not sourceExpr.getEnclosingFunction() = usage.asExpr().getEnclosingFunction() - then - extraString = - usage.getNaNDescription() + sourceString + " computed in function " + - sourceExpr.getEnclosingFunction().getName() and - extra = sourceExpr.getEnclosingFunction() - else ( - extra = sourceExpr and - extraString = usage.getNaNDescription() + sourceString - ) + then computedInFunction = "computed in function $@ " + else computedInFunction = "" ) -select elem, source, sink, usage.getDescription(), extra, extraString +select elem, source, sink, + "Possible NaN value $@ " + computedInFunction + "flows to " + usage.getDescription(), sourceExpr, + sourceString, function, function.getName() diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected index f1f08b5a51..8dd5ac15b8 100644 --- a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected +++ b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected @@ -85,29 +85,29 @@ nodes | test.c:210:23:210:31 | middleInf | semmle.label | middleInf | subpaths #select -| test.c:12:8:12:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:12:8:12:9 | l2 | Division operation may silently underflow and produce zero, as the divisor $@. | test.c:8:14:8:20 | ... / ... | may be an infinite float value from division by zero | -| test.c:13:8:13:9 | l3 | test.c:8:14:8:20 | ... / ... | test.c:13:8:13:9 | l3 | Division operation may silently underflow and produce zero, as the divisor $@. | test.c:8:14:8:20 | ... / ... | may be an infinite float value from division by zero | -| test.c:18:8:18:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:18:3:18:9 | l2 | $@ casted to integer. | test.c:8:14:8:20 | ... / ... | Possibly infinite float value from division by zero | -| test.c:19:8:19:9 | l3 | test.c:8:14:8:20 | ... / ... | test.c:19:3:19:9 | l3 | $@ casted to integer. | test.c:8:14:8:20 | ... / ... | Possibly infinite float value from division by zero | -| test.c:27:19:27:20 | l2 | test.c:8:14:8:20 | ... / ... | test.c:27:19:27:20 | l2 | Division operation may silently underflow and produce zero, as the divisor $@. | test.c:8:14:8:20 | ... / ... | may be an infinite float value from division by zero | -| test.c:28:19:28:20 | l3 | test.c:8:14:8:20 | ... / ... | test.c:28:19:28:20 | l3 | Division operation may silently underflow and produce zero, as the divisor $@. | test.c:8:14:8:20 | ... / ... | may be an infinite float value from division by zero | -| test.c:38:8:38:9 | l7 | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | $@ casted to integer. | test.c:31:14:32:15 | ... / ... | Possibly infinite float value from division by zero | -| test.c:61:11:61:17 | ... / ... | test.c:61:5:61:18 | ... / ... | test.c:61:5:61:18 | ... / ... | $@ casted to integer. | test.c:61:11:61:17 | ... / ... | Possibly infinite float value from division by zero | -| test.c:66:11:66:19 | ... / ... | test.c:66:5:66:20 | ... / ... | test.c:66:5:66:20 | ... / ... | $@ casted to integer. | test.c:66:11:66:19 | ... / ... | Possibly infinite float value from division by zero | -| test.c:72:20:72:28 | ... / ... | test.c:72:14:72:29 | ... / ... | test.c:72:14:72:29 | ... / ... | $@ casted to integer. | test.c:72:20:72:28 | ... / ... | Possibly infinite float value from division by zero | -| test.c:75:24:75:32 | ... / ... | test.c:75:18:75:33 | ... / ... | test.c:75:18:75:33 | ... / ... | $@ casted to integer. | test.c:75:24:75:32 | ... / ... | Possibly infinite float value from division by zero | -| test.c:79:10:79:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:79:5:79:12 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | -| test.c:87:10:87:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:87:5:87:12 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | -| test.c:91:10:91:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:91:5:91:12 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | -| test.c:93:10:93:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:93:5:93:12 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | -| test.c:99:10:99:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:99:5:99:12 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | -| test.c:105:10:105:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:105:5:105:12 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | -| test.c:111:10:111:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:111:5:111:12 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | -| test.c:114:21:114:23 | l12 | test.c:77:15:77:21 | ... / ... | test.c:114:16:114:23 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | -| test.c:117:28:117:30 | l12 | test.c:77:15:77:21 | ... / ... | test.c:117:23:117:30 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | -| test.c:120:25:120:27 | l12 | test.c:77:15:77:21 | ... / ... | test.c:120:20:120:27 | l12 | $@ casted to integer. | test.c:77:15:77:21 | ... / ... | Possibly infinite float value from division by zero | -| test.c:163:9:164:15 | ... / ... | test.c:163:3:164:16 | ... / ... | test.c:163:3:164:16 | ... / ... | $@ casted to integer. | test.c:163:9:164:15 | ... / ... | Possibly infinite float value from division by zero | -| test.c:175:32:175:32 | p | test.c:189:51:189:59 | ... / ... | test.c:175:27:175:32 | p | $@ casted to integer. | test.c:189:6:189:24 | addInfThenCastToInt | Possibly infinite float value computed in function addInfThenCastToInt | -| test.c:175:32:175:32 | p | test.c:193:13:194:15 | ... / ... | test.c:175:27:175:32 | p | $@ casted to integer. | test.c:192:6:192:7 | f2 | Possibly infinite float value computed in function f2 | -| test.c:175:32:175:32 | p | test.c:204:19:204:27 | ... / ... | test.c:175:27:175:32 | p | $@ casted to integer. | test.c:192:6:192:7 | f2 | Possibly infinite float value computed in function f2 | -| test.c:185:18:185:18 | p | test.c:200:25:200:33 | ... / ... | test.c:185:13:185:18 | p | $@ casted to integer. | test.c:192:6:192:7 | f2 | Possibly infinite float value computed in function f2 | +| test.c:12:8:12:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:12:8:12:9 | l2 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:13:8:13:9 | l3 | test.c:8:14:8:20 | ... / ... | test.c:13:8:13:9 | l3 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:18:8:18:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:18:3:18:9 | l2 | Possibly infinite float value $@ flows to cast to integer. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:19:8:19:9 | l3 | test.c:8:14:8:20 | ... / ... | test.c:19:3:19:9 | l3 | Possibly infinite float value $@ flows to cast to integer. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:27:19:27:20 | l2 | test.c:8:14:8:20 | ... / ... | test.c:27:19:27:20 | l2 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:28:19:28:20 | l3 | test.c:8:14:8:20 | ... / ... | test.c:28:19:28:20 | l3 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:38:8:38:9 | l7 | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | Possibly infinite float value $@ flows to cast to integer. | test.c:31:14:32:15 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:61:11:61:17 | ... / ... | test.c:61:5:61:18 | ... / ... | test.c:61:5:61:18 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.c:61:11:61:17 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:66:11:66:19 | ... / ... | test.c:66:5:66:20 | ... / ... | test.c:66:5:66:20 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.c:66:11:66:19 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:72:20:72:28 | ... / ... | test.c:72:14:72:29 | ... / ... | test.c:72:14:72:29 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.c:72:20:72:28 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:75:24:75:32 | ... / ... | test.c:75:18:75:33 | ... / ... | test.c:75:18:75:33 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.c:75:24:75:32 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:79:10:79:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:79:5:79:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:87:10:87:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:87:5:87:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:91:10:91:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:91:5:91:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:93:10:93:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:93:5:93:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:99:10:99:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:99:5:99:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:105:10:105:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:105:5:105:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:111:10:111:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:111:5:111:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:114:21:114:23 | l12 | test.c:77:15:77:21 | ... / ... | test.c:114:16:114:23 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:117:28:117:30 | l12 | test.c:77:15:77:21 | ... / ... | test.c:117:23:117:30 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:120:25:120:27 | l12 | test.c:77:15:77:21 | ... / ... | test.c:120:20:120:27 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:163:9:164:15 | ... / ... | test.c:163:3:164:16 | ... / ... | test.c:163:3:164:16 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.c:163:9:164:15 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:175:32:175:32 | p | test.c:189:51:189:59 | ... / ... | test.c:175:27:175:32 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.c:189:51:189:59 | ... / ... | from division by zero | test.c:189:6:189:24 | addInfThenCastToInt | addInfThenCastToInt | +| test.c:175:32:175:32 | p | test.c:193:13:194:15 | ... / ... | test.c:175:27:175:32 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.c:193:13:194:15 | ... / ... | from division by zero | test.c:192:6:192:7 | f2 | f2 | +| test.c:175:32:175:32 | p | test.c:204:19:204:27 | ... / ... | test.c:175:27:175:32 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.c:204:19:204:27 | ... / ... | from division by zero | test.c:192:6:192:7 | f2 | f2 | +| test.c:185:18:185:18 | p | test.c:200:25:200:33 | ... / ... | test.c:185:13:185:18 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.c:200:25:200:33 | ... / ... | from division by zero | test.c:192:6:192:7 | f2 | f2 | diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected index e0047d9ef7..aeec3c943f 100644 --- a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected +++ b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected @@ -102,35 +102,35 @@ nodes | test.c:211:23:211:31 | middleNaN | semmle.label | middleNaN | subpaths #select -| test.c:36:8:36:9 | l5 | test.c:27:14:27:20 | ... / ... | test.c:36:3:36:9 | l5 | $@ casted to integer. | test.c:27:14:27:20 | ... / ... | Possibly NaN float value (from division of infinity by infinity) | -| test.c:37:8:37:9 | l6 | test.c:28:14:28:20 | ... / ... | test.c:37:3:37:9 | l6 | $@ casted to integer. | test.c:28:14:28:20 | ... / ... | Possibly NaN float value (from division of infinity by infinity) | -| test.c:38:8:38:9 | l7 | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | $@ casted to integer. | test.c:31:14:32:15 | ... / ... | Possibly NaN float value (from division of zero by zero) | -| test.c:39:8:39:9 | l8 | test.c:33:14:33:22 | ... / ... | test.c:39:3:39:9 | l8 | $@ casted to integer. | test.c:33:14:33:22 | ... / ... | Possibly NaN float value (from division of zero by zero) | -| test.c:46:3:46:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:46:3:46:4 | l5 | Comparison involving a $@, which always evaluates to false. | test.c:27:14:27:20 | ... / ... | possibly NaN float value (from division of infinity by infinity) | -| test.c:47:3:47:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:47:3:47:4 | l5 | Comparison involving a $@, which always evaluates to false. | test.c:27:14:27:20 | ... / ... | possibly NaN float value (from division of infinity by infinity) | -| test.c:48:3:48:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:48:3:48:4 | l5 | Comparison involving a $@, which always evaluates to false. | test.c:27:14:27:20 | ... / ... | possibly NaN float value (from division of infinity by infinity) | -| test.c:49:3:49:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:49:3:49:4 | l5 | Comparison involving a $@, which always evaluates to false. | test.c:27:14:27:20 | ... / ... | possibly NaN float value (from division of infinity by infinity) | -| test.c:50:3:50:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:50:3:50:4 | l5 | Comparison involving a $@, which always evaluates to false. | test.c:27:14:27:20 | ... / ... | possibly NaN float value (from division of infinity by infinity) | -| test.c:51:3:51:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:51:3:51:4 | l5 | Comparison involving a $@, which always evaluates to false. | test.c:27:14:27:20 | ... / ... | possibly NaN float value (from division of infinity by infinity) | -| test.c:52:3:52:4 | l6 | test.c:28:14:28:20 | ... / ... | test.c:52:3:52:4 | l6 | Comparison involving a $@, which always evaluates to false. | test.c:28:14:28:20 | ... / ... | possibly NaN float value (from division of infinity by infinity) | -| test.c:53:3:53:4 | l7 | test.c:31:14:32:15 | ... / ... | test.c:53:3:53:4 | l7 | Comparison involving a $@, which always evaluates to false. | test.c:31:14:32:15 | ... / ... | possibly NaN float value (from division of zero by zero) | -| test.c:54:3:54:4 | l8 | test.c:33:14:33:22 | ... / ... | test.c:54:3:54:4 | l8 | Comparison involving a $@, which always evaluates to false. | test.c:33:14:33:22 | ... / ... | possibly NaN float value (from division of zero by zero) | -| test.c:61:11:61:17 | ... / ... | test.c:61:5:61:18 | ... / ... | test.c:61:5:61:18 | ... / ... | $@ casted to integer. | test.c:61:11:61:17 | ... / ... | Possibly NaN float value (from division of zero by zero) | -| test.c:66:11:66:19 | ... / ... | test.c:66:5:66:20 | ... / ... | test.c:66:5:66:20 | ... / ... | $@ casted to integer. | test.c:66:11:66:19 | ... / ... | Possibly NaN float value (from division of zero by zero) | -| test.c:72:20:72:28 | ... / ... | test.c:72:14:72:29 | ... / ... | test.c:72:14:72:29 | ... / ... | $@ casted to integer. | test.c:72:20:72:28 | ... / ... | Possibly NaN float value (from division of zero by zero) | -| test.c:75:24:75:32 | ... / ... | test.c:75:18:75:33 | ... / ... | test.c:75:18:75:33 | ... / ... | $@ casted to integer. | test.c:75:24:75:32 | ... / ... | Possibly NaN float value (from division of zero by zero) | -| test.c:126:10:126:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:126:5:126:12 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | -| test.c:132:10:132:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:132:5:132:12 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | -| test.c:138:10:138:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:138:5:138:12 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | -| test.c:144:10:144:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:144:5:144:12 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | -| test.c:148:10:148:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:148:5:148:12 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | -| test.c:155:25:155:27 | l13 | test.c:122:15:122:21 | ... / ... | test.c:155:20:155:27 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | -| test.c:157:28:157:30 | l13 | test.c:122:15:122:21 | ... / ... | test.c:157:23:157:30 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | -| test.c:158:21:158:23 | l13 | test.c:122:15:122:21 | ... / ... | test.c:158:16:158:23 | l13 | $@ casted to integer. | test.c:122:15:122:21 | ... / ... | Possibly NaN float value (from division of zero by zero) | -| test.c:166:8:166:10 | call to pow | test.c:166:3:166:18 | call to pow | test.c:166:3:166:18 | call to pow | $@ casted to integer. | test.c:166:8:166:10 | call to pow | Possibly NaN float value (both arguments are equal to zero) | -| test.c:171:8:171:11 | call to acos | test.c:171:3:171:15 | call to acos | test.c:171:3:171:15 | call to acos | $@ casted to integer. | test.c:171:8:171:11 | call to acos | Possibly NaN float value (the argument has a range -1000000000000000...1000000000000000 which is outside the domain of this function (-1.0...1.0)) | -| test.c:175:32:175:32 | p | test.c:190:51:190:59 | ... / ... | test.c:175:27:175:32 | p | $@ casted to integer. | test.c:190:6:190:24 | addNaNThenCastToInt | Possibly NaN float value (from division of zero by zero) computed in function addNaNThenCastToInt | -| test.c:175:32:175:32 | p | test.c:195:13:195:21 | ... / ... | test.c:175:27:175:32 | p | $@ casted to integer. | test.c:192:6:192:7 | f2 | Possibly NaN float value (from division of zero by zero) computed in function f2 | -| test.c:175:32:175:32 | p | test.c:199:23:199:31 | ... / ... | test.c:175:27:175:32 | p | $@ casted to integer. | test.c:192:6:192:7 | f2 | Possibly NaN float value (from division of zero by zero) computed in function f2 | -| test.c:175:32:175:32 | p | test.c:205:19:205:27 | ... / ... | test.c:175:27:175:32 | p | $@ casted to integer. | test.c:192:6:192:7 | f2 | Possibly NaN float value (from division of zero by zero) computed in function f2 | -| test.c:185:18:185:18 | p | test.c:201:25:201:33 | ... / ... | test.c:185:13:185:18 | p | $@ casted to integer. | test.c:192:6:192:7 | f2 | Possibly NaN float value (from division of zero by zero) computed in function f2 | +| test.c:36:8:36:9 | l5 | test.c:27:14:27:20 | ... / ... | test.c:36:3:36:9 | l5 | Possible NaN value $@ flows to a cast to integer. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:37:8:37:9 | l6 | test.c:28:14:28:20 | ... / ... | test.c:37:3:37:9 | l6 | Possible NaN value $@ flows to a cast to integer. | test.c:28:14:28:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:38:8:38:9 | l7 | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | Possible NaN value $@ flows to a cast to integer. | test.c:31:14:32:15 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:39:8:39:9 | l8 | test.c:33:14:33:22 | ... / ... | test.c:39:3:39:9 | l8 | Possible NaN value $@ flows to a cast to integer. | test.c:33:14:33:22 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:46:3:46:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:46:3:46:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:47:3:47:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:47:3:47:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:48:3:48:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:48:3:48:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:49:3:49:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:49:3:49:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:50:3:50:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:50:3:50:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:51:3:51:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:51:3:51:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:52:3:52:4 | l6 | test.c:28:14:28:20 | ... / ... | test.c:52:3:52:4 | l6 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:28:14:28:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:53:3:53:4 | l7 | test.c:31:14:32:15 | ... / ... | test.c:53:3:53:4 | l7 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:31:14:32:15 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:54:3:54:4 | l8 | test.c:33:14:33:22 | ... / ... | test.c:54:3:54:4 | l8 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:33:14:33:22 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:61:11:61:17 | ... / ... | test.c:61:5:61:18 | ... / ... | test.c:61:5:61:18 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.c:61:11:61:17 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:66:11:66:19 | ... / ... | test.c:66:5:66:20 | ... / ... | test.c:66:5:66:20 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.c:66:11:66:19 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:72:20:72:28 | ... / ... | test.c:72:14:72:29 | ... / ... | test.c:72:14:72:29 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.c:72:20:72:28 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:75:24:75:32 | ... / ... | test.c:75:18:75:33 | ... / ... | test.c:75:18:75:33 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.c:75:24:75:32 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:126:10:126:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:126:5:126:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:132:10:132:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:132:5:132:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:138:10:138:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:138:5:138:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:144:10:144:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:144:5:144:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:148:10:148:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:148:5:148:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:155:25:155:27 | l13 | test.c:122:15:122:21 | ... / ... | test.c:155:20:155:27 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:157:28:157:30 | l13 | test.c:122:15:122:21 | ... / ... | test.c:157:23:157:30 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:158:21:158:23 | l13 | test.c:122:15:122:21 | ... / ... | test.c:158:16:158:23 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:166:8:166:10 | call to pow | test.c:166:3:166:18 | call to pow | test.c:166:3:166:18 | call to pow | Possible NaN value $@ flows to a cast to integer. | test.c:166:8:166:10 | call to pow | both arguments are equal to zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:171:8:171:11 | call to acos | test.c:171:3:171:15 | call to acos | test.c:171:3:171:15 | call to acos | Possible NaN value $@ flows to a cast to integer. | test.c:171:8:171:11 | call to acos | the argument has a range -1000000000000000...1000000000000000 which is outside the domain of this function (-1.0...1.0) | test.c:6:6:6:7 | f1 | f1 | +| test.c:175:32:175:32 | p | test.c:190:51:190:59 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:190:51:190:59 | ... / ... | from division of zero by zero | test.c:190:6:190:24 | addNaNThenCastToInt | addNaNThenCastToInt | +| test.c:175:32:175:32 | p | test.c:195:13:195:21 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:195:13:195:21 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | +| test.c:175:32:175:32 | p | test.c:199:23:199:31 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:199:23:199:31 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | +| test.c:175:32:175:32 | p | test.c:205:19:205:27 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:205:19:205:27 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | +| test.c:185:18:185:18 | p | test.c:201:25:201:33 | ... / ... | test.c:185:13:185:18 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:201:25:201:33 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | diff --git a/cpp/common/src/codingstandards/cpp/FloatingPoint.qll b/cpp/common/src/codingstandards/cpp/FloatingPoint.qll index f3ba8dba18..f141214c82 100644 --- a/cpp/common/src/codingstandards/cpp/FloatingPoint.qll +++ b/cpp/common/src/codingstandards/cpp/FloatingPoint.qll @@ -1,5 +1,6 @@ import codeql.util.Boolean import codingstandards.cpp.RestrictedRangeAnalysis +import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis as SimpleRangeAnalysis predicate exprMayEqualZero(Expr e) { RestrictedRangeAnalysis::upperBound(e) >= 0 and @@ -254,7 +255,7 @@ class FPClassificationGuard instanceof GuardCondition { ) } - // Helper function, gets base constraint assuming `classifier() == value` or `classifier != value`. + // Helper predicate, gets base constraint assuming `classifier() == value` or `classifier != value`. private FPClassificationConstraint getBaseConstraint(Boolean areEqual, int testResult) { exists(FPClassificationConstraint base | testResult = 0 and @@ -340,3 +341,72 @@ predicate exprMayEqualInfinity(Expr e, Boolean positive) { not guardedNotFPClass(e, TInfinite()) and not e.getType() instanceof IntegralType } + +signature float upperBoundPredicate(Expr e); + +signature float lowerBoundPredicate(Expr e); + +signature predicate exprMayEqualZeroPredicate(Expr e); + +predicate exprMayEqualZeroNaive(Expr e) { + e.getValue().toFloat() = 0 +} + +/** + * Get the math function name variants for the given name, e.g., "acos" has variants "acos", + * "acosf", and "acosl". + */ +Function getMathVariants(string name) { result.hasGlobalOrStdName([name, name + "f", name + "l"]) } + +module DomainError { + predicate hasDomainError(FunctionCall fc, string description) { + exists(Function functionWithDomainError | fc.getTarget() = functionWithDomainError | + functionWithDomainError = [getMathVariants(["acos", "asin", "atanh"])] and + not ( + ub(fc.getArgument(0)) <= 1.0 and + lb(fc.getArgument(0)) >= -1.0 + ) and + description = + "the argument has a range " + lb(fc.getArgument(0)) + "..." + ub(fc.getArgument(0)) + + " which is outside the domain of this function (-1.0...1.0)" + or + functionWithDomainError = getMathVariants(["atan2", "pow"]) and + ( + mayEqualZero(fc.getArgument(0)) and + mayEqualZero(fc.getArgument(1)) and + description = "both arguments are equal to zero" + ) + or + functionWithDomainError = getMathVariants("pow") and + ( + ub(fc.getArgument(0)) < 0.0 and + ub(fc.getArgument(1)) < 0.0 and + description = "both arguments are less than zero" + ) + or + functionWithDomainError = getMathVariants("acosh") and + ub(fc.getArgument(0)) < 1.0 and + description = "argument is less than 1" + or + //pole error is the same as domain for logb and tgamma (but not ilogb - no pole error exists) + functionWithDomainError = getMathVariants(["ilogb", "logb", "tgamma"]) and + fc.getArgument(0).getValue().toFloat() = 0 and + description = "argument is equal to zero" + or + functionWithDomainError = getMathVariants(["log", "log10", "log2", "sqrt"]) and + ub(fc.getArgument(0)) < 0.0 and + description = "argument is negative" + or + functionWithDomainError = getMathVariants("log1p") and + ub(fc.getArgument(0)) < -1.0 and + description = "argument is less than 1" + or + functionWithDomainError = getMathVariants("fmod") and + fc.getArgument(1).getValue().toFloat() = 0 and + description = "y is 0" + ) + } +} + +import DomainError as RestrictedDomainError +import DomainError as SimpleDomainError diff --git a/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll index b81f113281..05290b3aaf 100644 --- a/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll +++ b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll @@ -2,56 +2,75 @@ import semmle.code.cpp.controlflow.Guards import semmle.code.cpp.valuenumbering.HashCons /** - * A fork of SimpleRangeAnalysis.qll, which is intended to only give - * results with a conservative basis. + * A fork of SimpleRangeAnalysis.qll, which is intended to only give results + * with a conservative basis. Forked from codeql/cpp-all@1.4.2. * - * For instance, since range analysis is local, a function call (e.g. - * `f()`) is given the widest possible range in the original library. In - * this fork, we do not provide any result. + * For instance, since range analysis is local, a function call (e.g. `f()`) is + * given the widest possible range in the original library. In this fork, we do + * not provide any result. * * Original library level doc comment from SimpleRangeAnalysis.qll: * - * Simple range analysis library. Range analysis is usually done as an - * abstract interpretation over the lattice of range values. (A range is a - * pair, containing a lower and upper bound for the value.) The problem - * with this approach is that the lattice is very tall, which means it can - * take an extremely large number of iterations to find the least fixed - * point. This example illustrates the problem: + * > Simple range analysis library. Range analysis is usually done as an + * > abstract interpretation over the lattice of range values. (A range is a + * > pair, containing a lower and upper bound for the value.) The problem + * > with this approach is that the lattice is very tall, which means it can + * > take an extremely large number of iterations to find the least fixed + * > point. This example illustrates the problem: * - * int count = 0; - * for (; p; p = p->next) { - * count = count+1; - * } + * > int count = 0; + * > for (; p; p = p->next) { + * > count = count+1; + * > } * - * The range of 'count' is initially (0,0), then (0,1) on the second - * iteration, (0,2) on the third iteration, and so on until we eventually - * reach maxInt. + * > The range of 'count' is initially (0,0), then (0,1) on the second + * > iteration, (0,2) on the third iteration, and so on until we eventually + * > reach maxInt. * - * This library uses a crude solution to the problem described above: if - * the upper (or lower) bound of an expression might depend recursively on - * itself then we round it up (down for lower bounds) to one of a fixed set - * of values, such as 0, 1, 2, 256, and +Inf. This limits the height of the - * lattice which ensures that the analysis will terminate in a reasonable - * amount of time. This solution is similar to the abstract interpretation - * technique known as 'widening', but it is less precise because we are - * unable to inspect the bounds from the previous iteration of the fixed - * point computation. For example, widening might be able to deduce that - * the lower bound is -11 but we would approximate it to -16. + * > This library uses a crude solution to the problem described above: if + * > the upper (or lower) bound of an expression might depend recursively on + * > itself then we round it up (down for lower bounds) to one of a fixed set + * > of values, such as 0, 1, 2, 256, and +Inf. This limits the height of the + * > lattice which ensures that the analysis will terminate in a reasonable + * > amount of time. This solution is similar to the abstract interpretation + * > technique known as 'widening', but it is less precise because we are + * > unable to inspect the bounds from the previous iteration of the fixed + * > point computation. For example, widening might be able to deduce that + * > the lower bound is -11 but we would approximate it to -16. * - * QL does not allow us to compute an aggregate over a recursive - * sub-expression, so we cannot compute the minimum lower bound and maximum - * upper bound during the recursive phase of the query. Instead, the - * recursive phase computes a set of lower bounds and a set of upper bounds - * for each expression. We compute the minimum lower bound and maximum - * upper bound after the recursion is finished. This is another reason why - * we need to limit the number of bounds per expression, because they will - * all be stored until the recursive phase is finished. + * > QL does not allow us to compute an aggregate over a recursive + * > sub-expression, so we cannot compute the minimum lower bound and maximum + * > upper bound during the recursive phase of the query. Instead, the + * > recursive phase computes a set of lower bounds and a set of upper bounds + * > for each expression. We compute the minimum lower bound and maximum + * > upper bound after the recursion is finished. This is another reason why + * > we need to limit the number of bounds per expression, because they will + * > all be stored until the recursive phase is finished. * - * The ranges are represented using a pair of floating point numbers. This - * is simpler than using integers because floating point numbers cannot - * overflow and wrap. It is also convenient because we can detect overflow - * and negative overflow by looking for bounds that are outside the range - * of the type. + * > The ranges are represented using a pair of floating point numbers. This + * > is simpler than using integers because floating point numbers cannot + * > overflow and wrap. It is also convenient because we can detect overflow + * > and negative overflow by looking for bounds that are outside the range + * > of the type. + * + * The differences between this library and the original are: + * - The `largeValue()` predicate, with a value of 1e15, used in place of + * `exprMaxVal()` and `exprMinVal()` in most places. + * - Support for range analysis extensions removed for simplicity. + * - Additional predicates have been added to check for non-zero values, and guards + * against values equalling zero. + * - Division by a constant value has been added as a supported operations. Division + * is always widened, as support for division introduces examples of significantly + * longer chains of dependent expressions than merely addition and multiplication. + * These long chains can introduce exponential growth in the number of candidate + * bounds, even without recursive binary operations, so widening is always applied. + * - Division operations where the range of the denominator includes zero (and its + * not guarded to be non-zero) and produce infinite upper and/or lower bounds. + * - Support for monotonically increasing and decreasing math functions has been + * added, including `log`, `exp`, `asin`, `atan`, `sinh`, and `sqrt`. If a math + * function increases or decreases monotonically, then the lower or upper bound of + * its input can be used to compute the lower or upper bound of the function call. + * Not all math functions increase or decrease monotonically. */ module RestrictedRangeAnalysis { import cpp diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/FloatingTypes2.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/FloatingTypes2.qll index 7cdc6430a3..0dbc6cc22d 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/FloatingTypes2.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/FloatingTypes2.qll @@ -22,7 +22,7 @@ predicate isFloatingTypes2QueryMetadata(Query query, string queryId, string rule FloatingTypes2Package::possibleMisuseOfUndetectedNaNQuery() and queryId = // `@id` for the `possibleMisuseOfUndetectedNaN` query - "c/misra/possible-misuse-of-undetected-na-n" and + "c/misra/possible-misuse-of-undetected-nan" and ruleId = "DIR-4-15" and category = "required" } diff --git a/cpp/common/src/codingstandards/cpp/rules/uncheckedrangedomainpoleerrors/UncheckedRangeDomainPoleErrors.qll b/cpp/common/src/codingstandards/cpp/rules/uncheckedrangedomainpoleerrors/UncheckedRangeDomainPoleErrors.qll index ad93f70bd4..acc7888d2c 100644 --- a/cpp/common/src/codingstandards/cpp/rules/uncheckedrangedomainpoleerrors/UncheckedRangeDomainPoleErrors.qll +++ b/cpp/common/src/codingstandards/cpp/rules/uncheckedrangedomainpoleerrors/UncheckedRangeDomainPoleErrors.qll @@ -4,63 +4,14 @@ import cpp import codingstandards.cpp.CodingStandards +import codingstandards.cpp.FloatingPoint +import codingstandards.cpp.FloatingPoint::SimpleDomainError import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis abstract class UncheckedRangeDomainPoleErrorsSharedQuery extends Query { } Query getQuery() { result instanceof UncheckedRangeDomainPoleErrorsSharedQuery } -bindingset[name] -Function getMathVariants(string name) { result.hasGlobalOrStdName([name, name + "f", name + "l"]) } - -predicate hasDomainError(FunctionCall fc, string description) { - exists(Function functionWithDomainError | fc.getTarget() = functionWithDomainError | - functionWithDomainError = [getMathVariants(["acos", "asin", "atanh"])] and - not ( - upperBound(fc.getArgument(0)) <= 1.0 and - lowerBound(fc.getArgument(0)) >= -1.0 - ) and - description = - "the argument has a range " + lowerBound(fc.getArgument(0)) + "..." + - upperBound(fc.getArgument(0)) + " which is outside the domain of this function (-1.0...1.0)" - or - functionWithDomainError = getMathVariants(["atan2", "pow"]) and - ( - fc.getArgument(0).getValue().toFloat() = 0 and - fc.getArgument(1).getValue().toFloat() = 0 and - description = "both arguments are equal to zero" - ) - or - functionWithDomainError = getMathVariants("pow") and - ( - upperBound(fc.getArgument(0)) < 0.0 and - upperBound(fc.getArgument(1)) < 0.0 and - description = "both arguments are less than zero" - ) - or - functionWithDomainError = getMathVariants("acosh") and - upperBound(fc.getArgument(0)) < 1.0 and - description = "argument is less than 1" - or - //pole error is the same as domain for logb and tgamma (but not ilogb - no pole error exists) - functionWithDomainError = getMathVariants(["ilogb", "logb", "tgamma"]) and - fc.getArgument(0).getValue().toFloat() = 0 and - description = "argument is equal to zero" - or - functionWithDomainError = getMathVariants(["log", "log10", "log2", "sqrt"]) and - upperBound(fc.getArgument(0)) < 0.0 and - description = "argument is negative" - or - functionWithDomainError = getMathVariants("log1p") and - upperBound(fc.getArgument(0)) < -1.0 and - description = "argument is less than 1" - or - functionWithDomainError = getMathVariants("fmod") and - fc.getArgument(1).getValue().toFloat() = 0 and - description = "y is 0" - ) -} - predicate hasRangeError(FunctionCall fc, string description) { exists(Function functionWithRangeError | fc.getTarget() = functionWithRangeError | functionWithRangeError.hasGlobalOrStdName(["abs", "labs", "llabs", "imaxabs"]) and diff --git a/scripts/generate_rules/coding_standards_utils.py b/scripts/generate_rules/coding_standards_utils.py index 6f96460ef7..b0bcd48443 100644 --- a/scripts/generate_rules/coding_standards_utils.py +++ b/scripts/generate_rules/coding_standards_utils.py @@ -19,8 +19,10 @@ def split_camel_case(short_name : str) -> List[str]: """Split a camel case string to a list.""" + # Edge case, turn FooNaNBar into foo-nan-bar instead of foo-na-n-bar by a preprocessing step. + nan_fixed = short_name.replace("NaN", "Nan") matches = re.finditer( - ".+?(?:(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|$)", short_name) + ".+?(?:(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|$)", nan_fixed) return [m.group(0) for m in matches] From d10783cccb68348dbb43910ed6647867aa9bfdaf Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 20 Mar 2025 17:24:44 -0700 Subject: [PATCH 267/370] Format FloatingPoint.qll --- cpp/common/src/codingstandards/cpp/FloatingPoint.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/FloatingPoint.qll b/cpp/common/src/codingstandards/cpp/FloatingPoint.qll index f141214c82..f5ff2fefca 100644 --- a/cpp/common/src/codingstandards/cpp/FloatingPoint.qll +++ b/cpp/common/src/codingstandards/cpp/FloatingPoint.qll @@ -348,9 +348,7 @@ signature float lowerBoundPredicate(Expr e); signature predicate exprMayEqualZeroPredicate(Expr e); -predicate exprMayEqualZeroNaive(Expr e) { - e.getValue().toFloat() = 0 -} +predicate exprMayEqualZeroNaive(Expr e) { e.getValue().toFloat() = 0 } /** * Get the math function name variants for the given name, e.g., "acos" has variants "acos", @@ -358,7 +356,9 @@ predicate exprMayEqualZeroNaive(Expr e) { */ Function getMathVariants(string name) { result.hasGlobalOrStdName([name, name + "f", name + "l"]) } -module DomainError { +module DomainError< + upperBoundPredicate/1 ub, lowerBoundPredicate/1 lb, exprMayEqualZeroPredicate/1 mayEqualZero> +{ predicate hasDomainError(FunctionCall fc, string description) { exists(Function functionWithDomainError | fc.getTarget() = functionWithDomainError | functionWithDomainError = [getMathVariants(["acos", "asin", "atanh"])] and From 2265ed48d7b8739a4061e12ac601c5d2277e7ef9 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 21 Mar 2025 00:50:52 -0700 Subject: [PATCH 268/370] Address feedback --- c/common/src/codingstandards/c/Generic.qll | 2 +- ...ricSelectionDoesntDependOnMacroArgument.ql | 9 ++-- .../GenericSelectionNotExpandedFromAMacro.ql | 4 +- ...ricSelectionNotFromMacroWithSideEffects.ql | 1 + .../GenericWithoutNonDefaultAssociation.ql | 2 +- ...ectionDoesntDependOnMacroArgument.expected | 6 +-- ...ricSelectionNotExpandedFromAMacro.expected | 2 +- .../codingstandards/cpp/types/Compatible.qll | 51 +------------------ .../cpp/types/SimpleAssignment.qll | 6 +++ 9 files changed, 21 insertions(+), 62 deletions(-) diff --git a/c/common/src/codingstandards/c/Generic.qll b/c/common/src/codingstandards/c/Generic.qll index 784c16778e..1281be5f71 100644 --- a/c/common/src/codingstandards/c/Generic.qll +++ b/c/common/src/codingstandards/c/Generic.qll @@ -115,7 +115,7 @@ class ParsedGenericMacro extends Macro { ) } - string getControllingExprString() { result = getSelectionString(1) } + string getControllingExprString() { result = getSelectionString(1).trim() } bindingset[str, word] private int countWordInString(string word, string str) { diff --git a/c/misra/src/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.ql b/c/misra/src/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.ql index 0dc0e5273a..1a76339f50 100644 --- a/c/misra/src/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.ql +++ b/c/misra/src/rules/RULE-23-1/GenericSelectionDoesntDependOnMacroArgument.ql @@ -19,8 +19,9 @@ import codingstandards.c.Generic from ParsedGenericMacro macro, string ctrlExpr where not isExcluded(macro, GenericsPackage::genericSelectionDoesntDependOnMacroArgumentQuery()) and - ctrlExpr = macro.getControllingExprString().trim() and - not macro.expansionsInsideControllingExpr(_) > 0 + ctrlExpr = macro.getControllingExprString() and + // No parameter exists that is expanded in the controlling expression one or more times + not exists(string parameter | macro.expansionsInsideControllingExpr(parameter) > 0) select macro, - "Generic macro " + macro.getName() + " uses controlling expr " + ctrlExpr + - ", which doesn't match any macro parameter." + "Generic macro " + macro.getName() + " doesn't refer to a macro parameter in controlling expr '" + + ctrlExpr + "'." diff --git a/c/misra/src/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.ql b/c/misra/src/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.ql index 540804ffc4..603c44e8e1 100644 --- a/c/misra/src/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.ql +++ b/c/misra/src/rules/RULE-23-1/GenericSelectionNotExpandedFromAMacro.ql @@ -19,5 +19,5 @@ where not isExcluded(generic, GenericsPackage::genericSelectionNotExpandedFromAMacroQuery()) and ctrlExpr = generic.getControllingExpr() and not exists(MacroInvocation mi | mi.getAGeneratedElement() = generic.getExpr()) -select generic, "Generic expression with controlling expression $@ is not expanded froma macro", - ctrlExpr, ctrlExpr.toString() +select generic, "$@ in generic expression does not expand a macro parameter.", ctrlExpr, + "Controlling expression" diff --git a/c/misra/src/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.ql b/c/misra/src/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.ql index 4b1a2d26c3..d7fcb13d76 100644 --- a/c/misra/src/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.ql +++ b/c/misra/src/rules/RULE-23-2/GenericSelectionNotFromMacroWithSideEffects.ql @@ -72,6 +72,7 @@ module GenericSideEffectReportConfig implements MacroReportConfigSig Date: Mon, 24 Mar 2025 18:30:08 +0000 Subject: [PATCH 269/370] Bump version to 2.44.0-dev --- c/cert/src/qlpack.yml | 2 +- c/cert/test/qlpack.yml | 2 +- c/common/src/qlpack.yml | 2 +- c/common/test/qlpack.yml | 2 +- c/misra/src/qlpack.yml | 2 +- c/misra/test/qlpack.yml | 2 +- cpp/autosar/src/qlpack.yml | 2 +- cpp/autosar/test/qlpack.yml | 2 +- cpp/cert/src/qlpack.yml | 2 +- cpp/cert/test/qlpack.yml | 2 +- cpp/common/src/qlpack.yml | 2 +- cpp/common/test/qlpack.yml | 2 +- cpp/misra/src/qlpack.yml | 2 +- cpp/misra/test/qlpack.yml | 2 +- cpp/report/src/qlpack.yml | 2 +- docs/user_manual.md | 12 ++++++------ 16 files changed, 21 insertions(+), 21 deletions(-) diff --git a/c/cert/src/qlpack.yml b/c/cert/src/qlpack.yml index 8498e9447d..631639301e 100644 --- a/c/cert/src/qlpack.yml +++ b/c/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards -version: 2.43.0-dev +version: 2.44.0-dev description: CERT C 2016 suites: codeql-suites license: MIT diff --git a/c/cert/test/qlpack.yml b/c/cert/test/qlpack.yml index 2b44a05fdf..6eaaba1e91 100644 --- a/c/cert/test/qlpack.yml +++ b/c/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards-tests -version: 2.43.0-dev +version: 2.44.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/common/src/qlpack.yml b/c/common/src/qlpack.yml index 685a3a0144..4c21dc9b18 100644 --- a/c/common/src/qlpack.yml +++ b/c/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards -version: 2.43.0-dev +version: 2.44.0-dev license: MIT dependencies: codeql/common-cpp-coding-standards: '*' diff --git a/c/common/test/qlpack.yml b/c/common/test/qlpack.yml index 8f8486949b..1dbb59b4fd 100644 --- a/c/common/test/qlpack.yml +++ b/c/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards-tests -version: 2.43.0-dev +version: 2.44.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/misra/src/qlpack.yml b/c/misra/src/qlpack.yml index 5b8b1fc0b2..54cda2c1cc 100644 --- a/c/misra/src/qlpack.yml +++ b/c/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards -version: 2.43.0-dev +version: 2.44.0-dev description: MISRA C 2012 suites: codeql-suites license: MIT diff --git a/c/misra/test/qlpack.yml b/c/misra/test/qlpack.yml index aa5c5d86ae..9148e26b59 100644 --- a/c/misra/test/qlpack.yml +++ b/c/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards-tests -version: 2.43.0-dev +version: 2.44.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/autosar/src/qlpack.yml b/cpp/autosar/src/qlpack.yml index 1116e9534d..6d31398b2c 100644 --- a/cpp/autosar/src/qlpack.yml +++ b/cpp/autosar/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards -version: 2.43.0-dev +version: 2.44.0-dev description: AUTOSAR C++14 Guidelines R22-11, R21-11, R20-11, R19-11 and R19-03 suites: codeql-suites license: MIT diff --git a/cpp/autosar/test/qlpack.yml b/cpp/autosar/test/qlpack.yml index d540b01a32..ff7621c9d1 100644 --- a/cpp/autosar/test/qlpack.yml +++ b/cpp/autosar/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards-tests -version: 2.43.0-dev +version: 2.44.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/cert/src/qlpack.yml b/cpp/cert/src/qlpack.yml index 89b5196f23..f44646cdbe 100644 --- a/cpp/cert/src/qlpack.yml +++ b/cpp/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards -version: 2.43.0-dev +version: 2.44.0-dev description: CERT C++ 2016 suites: codeql-suites license: MIT diff --git a/cpp/cert/test/qlpack.yml b/cpp/cert/test/qlpack.yml index ceedca4647..c6d57b0d33 100644 --- a/cpp/cert/test/qlpack.yml +++ b/cpp/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards-tests -version: 2.43.0-dev +version: 2.44.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/common/src/qlpack.yml b/cpp/common/src/qlpack.yml index ce7e896ced..302955fc78 100644 --- a/cpp/common/src/qlpack.yml +++ b/cpp/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards -version: 2.43.0-dev +version: 2.44.0-dev license: MIT dependencies: codeql/cpp-all: 2.1.1 diff --git a/cpp/common/test/qlpack.yml b/cpp/common/test/qlpack.yml index e2201b887e..1f0b830de8 100644 --- a/cpp/common/test/qlpack.yml +++ b/cpp/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards-tests -version: 2.43.0-dev +version: 2.44.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/misra/src/qlpack.yml b/cpp/misra/src/qlpack.yml index 7c104631d1..27e0893ed6 100644 --- a/cpp/misra/src/qlpack.yml +++ b/cpp/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards -version: 2.43.0-dev +version: 2.44.0-dev description: MISRA C++ 2023 default-suite: codeql-suites/misra-cpp-default.qls license: MIT diff --git a/cpp/misra/test/qlpack.yml b/cpp/misra/test/qlpack.yml index 08bdda24eb..cdf6cbcdea 100644 --- a/cpp/misra/test/qlpack.yml +++ b/cpp/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards-tests -version: 2.43.0-dev +version: 2.44.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/report/src/qlpack.yml b/cpp/report/src/qlpack.yml index 73a6e189a3..83188c2748 100644 --- a/cpp/report/src/qlpack.yml +++ b/cpp/report/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/report-cpp-coding-standards -version: 2.43.0-dev +version: 2.44.0-dev license: MIT dependencies: codeql/cpp-all: 2.1.1 diff --git a/docs/user_manual.md b/docs/user_manual.md index a771aa1cc6..1e14744f80 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -35,14 +35,14 @@ ## Release information -This user manual documents release `2.43.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). +This user manual documents release `2.44.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). The release page documents the release notes and contains the following artifacts part of the release: - `coding-standards-codeql-packs-2.37.0-dev.zip`: CodeQL packs that can be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `code-scanning-cpp-query-pack-2.43.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `supported_rules_list_2.43.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. -- `supported_rules_list_2.43.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. -- `user_manual_2.43.0-dev.md`: This user manual. +- `code-scanning-cpp-query-pack-2.44.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. +- `supported_rules_list_2.44.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. +- `supported_rules_list_2.44.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. +- `user_manual_2.44.0-dev.md`: This user manual. - `Source Code (zip)`: A zip archive containing the contents of https://github.com/github/codeql-coding-standards - `Source Code (tar.gz)`: A GZip compressed tar archive containing the contents of https://github.com/github/codeql-coding-standards - `checksums.txt`: A text file containing sha256 checksums for the aforementioned artifacts. @@ -667,7 +667,7 @@ This section describes known failure modes for "CodeQL Coding Standards" and des | | Out of space | Less output. Some files may be only be partially analyzed, or not analyzed at all. | Error reported on the command line. | Increase space. If it remains an issue report space consumption issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False positives | More output. Results are reported which are not violations of the guidelines. | All reported results must be reviewed. | Report false positive issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False negatives | Less output. Violations of the guidelines are not reported. | Other validation and verification processes during software development should be used to complement the analysis performed by CodeQL Coding Standards. | Report false negative issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.43.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | +| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.44.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | | | Incorrect deviation record specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation records with a reason. Ensure that all deviation records are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Incorrect deviation permit specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation permits with a reason. Ensure that all deviation permits are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Unapproved use of a deviation record | Less output. Results for guideline violations are not reported. | Validate that the deviation record use is approved by verifying the approved-by attribute of the deviation record specification. | Ensure that each raised deviation record is approved by an independent approver through an auditable process. | From 642c7373d271bcb46daec0b6baf16d7278df5857 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 25 Mar 2025 00:28:00 -0700 Subject: [PATCH 270/370] Handle bit fields --- ...gMathArgumentsWithDifferingStandardType.ql | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql index 5156d81cef..5267ff98f9 100644 --- a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql +++ b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql @@ -16,12 +16,6 @@ import cpp import codingstandards.c.misra import codingstandards.c.TgMath -Expr getFullyExplicitlyConverted(Expr e) { - if e.hasExplicitConversion() - then result = getFullyExplicitlyConverted(e.getExplicitlyConverted()) - else result = e -} - string argTypesString(TgMathInvocation call, int i) { exists(string typeStr | typeStr = getEffectiveStandardType(call.getOperandArgument(i)).toString() and @@ -33,12 +27,28 @@ string argTypesString(TgMathInvocation call, int i) { ) } -predicate promotes(Type type) { type.(IntegralType).getSize() < any(IntType t).getSize() } - -Type integerPromote(Type type) { - promotes(type) and result.(IntType).isSigned() - or - not promotes(type) and result = type +/** + * If the range of values can be represented as a signed int, it is promoted to signed int. + * + * A value may also promote to unsigned int but only if `int` cannot represent the range of + * values. Which basically means only an `unsigned int` promotes to `unsigned int`, so we don't + * need to do anything in this case. + * + * An unsigned int bitfield with fewer than 32 bits is promoted to `int`. + */ +predicate promotesToSignedInt(Expr e) { + exists(int intBits, int intBytes | + intBytes = any(IntType t).getSize() and + intBits = intBytes * 8 and + ( + e.(FieldAccess).getTarget().(BitField).getNumBits() < intBits + or + e.getUnderlyingType().(IntegralType).getSize() < intBytes + ) + ) +} +Type getPromotedType(Expr e) { + if promotesToSignedInt(e) then result.(IntType).isSigned() else result = e.getUnderlyingType() } Type canonicalize(Type type) { @@ -48,8 +58,7 @@ Type canonicalize(Type type) { } Type getEffectiveStandardType(Expr e) { - result = - canonicalize(integerPromote(getFullyExplicitlyConverted(e).getType().stripTopLevelSpecifiers())) + result = canonicalize(getPromotedType(e.getExplicitlyConverted())) } from TgMathInvocation call, Type firstType From 952253de73853bb7a291672a7909698d81f76817 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 25 Mar 2025 00:30:09 -0700 Subject: [PATCH 271/370] Format SimpleAssignment.qll --- cpp/common/src/codingstandards/cpp/types/SimpleAssignment.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/types/SimpleAssignment.qll b/cpp/common/src/codingstandards/cpp/types/SimpleAssignment.qll index a38939c9ea..4f7a85c80a 100644 --- a/cpp/common/src/codingstandards/cpp/types/SimpleAssignment.qll +++ b/cpp/common/src/codingstandards/cpp/types/SimpleAssignment.qll @@ -1,9 +1,10 @@ /** * Helper predicates related to C11/C17 constraints on simple assignment between two types. - * + * * Currently only a subset of the constraints are implemented, specifically those * related to pointer types. */ + import codingstandards.cpp.types.LvalueConversion import codingstandards.cpp.types.Compatible From f268604d7d3920dad7c3546c60d56e90152ef6f5 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 25 Mar 2025 00:31:41 -0700 Subject: [PATCH 272/370] Update regex --- c/common/src/codingstandards/c/Generic.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/common/src/codingstandards/c/Generic.qll b/c/common/src/codingstandards/c/Generic.qll index 1281be5f71..19d5aad443 100644 --- a/c/common/src/codingstandards/c/Generic.qll +++ b/c/common/src/codingstandards/c/Generic.qll @@ -2,7 +2,7 @@ import cpp import codingstandards.cpp.Macro import codingstandards.cpp.MatchingParenthesis -string genericRegexp() { result = ".*_Generic\\s*\\(\\s*(.+),.*" } +string genericRegexp() { result = "\\b_Generic\\s*\\(\\s*(.+),.*" } bindingset[input] string deparenthesize(string input) { From 94bad29caacbeb653fe3adc34ea62d2008a316b4 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 25 Mar 2025 00:32:46 -0700 Subject: [PATCH 273/370] Format --- .../RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql index 5267ff98f9..81209c8565 100644 --- a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql +++ b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql @@ -29,11 +29,11 @@ string argTypesString(TgMathInvocation call, int i) { /** * If the range of values can be represented as a signed int, it is promoted to signed int. - * + * * A value may also promote to unsigned int but only if `int` cannot represent the range of * values. Which basically means only an `unsigned int` promotes to `unsigned int`, so we don't * need to do anything in this case. - * + * * An unsigned int bitfield with fewer than 32 bits is promoted to `int`. */ predicate promotesToSignedInt(Expr e) { @@ -47,6 +47,7 @@ predicate promotesToSignedInt(Expr e) { ) ) } + Type getPromotedType(Expr e) { if promotesToSignedInt(e) then result.(IntType).isSigned() else result = e.getUnderlyingType() } From 6245f7210e709e205b21e092e2cd907689cdd638 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 25 Mar 2025 00:34:09 -0700 Subject: [PATCH 274/370] Format --- cpp/common/src/codingstandards/cpp/types/Compatible.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/types/Compatible.qll b/cpp/common/src/codingstandards/cpp/types/Compatible.qll index fb8bf46aad..d6f65126e8 100644 --- a/cpp/common/src/codingstandards/cpp/types/Compatible.qll +++ b/cpp/common/src/codingstandards/cpp/types/Compatible.qll @@ -369,4 +369,4 @@ private class FunctionType extends Type { result = this.(RoutineType).getParameterType(i) or result = this.(FunctionPointerIshType).getParameterType(i) } -} \ No newline at end of file +} From 2045a44bd4aef7968ddc589004ee3d3ccd6d2bc7 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Wed, 26 Mar 2025 11:43:00 +0000 Subject: [PATCH 275/370] Restore deleted deviations suppression query --- .../deviations/DeviationsSuppression.qhelp | 12 ++ .../cpp/deviations/DeviationsSuppression.ql | 120 ++++++++++++++++++ .../DeviationsSuppression.expected | 7 + .../DeviationsSuppression.qlref | 1 + 4 files changed, 140 insertions(+) create mode 100644 cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.qhelp create mode 100644 cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql create mode 100644 cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected create mode 100644 cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.qlref diff --git a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.qhelp b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.qhelp new file mode 100644 index 0000000000..0bf3a3a71b --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.qhelp @@ -0,0 +1,12 @@ + + + +

    This query generates suppression information for rules that have an associated deviation record.

    +
    + +
  • + MISRA Compliance 2020 document: + Chapter 4.2 (page 12) - Deviations. +
  • +
    +
    \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql new file mode 100644 index 0000000000..9035b7d288 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql @@ -0,0 +1,120 @@ +/** + * @name Deviation suppression + * @description Generates information about files and locations where certain alerts should be considered suppressed by deviations. + * @kind alert-suppression + * @id cpp/coding-standards/deviation-suppression + */ + +import cpp +import Deviations + +/** Holds if `lineNumber` is an indexed line number in file `f`. */ +private predicate isLineNumber(File f, int lineNumber) { + exists(Location l | l.getFile() = f | + l.getStartLine() = lineNumber + or + l.getEndLine() = lineNumber + ) +} + +/** Gets the last line number in `f`. */ +private int getLastLineNumber(File f) { result = max(int lineNumber | isLineNumber(f, lineNumber)) } + +/** Gets the last column number on the last line of `f`. */ +int getLastColumnNumber(File f) { + result = + max(Location l | + l.getFile() = f and + l.getEndLine() = getLastLineNumber(f) + | + l.getEndColumn() + ) +} + +newtype TDeviationScope = + TDeviationRecordFileScope(DeviationRecord dr, File file) { + exists(string deviationPath | + dr.isDeviated(_, deviationPath) and + file.getRelativePath().prefix(deviationPath.length()) = deviationPath + ) + } or + TDeviationRecordCommentScope(DeviationRecord dr, Comment c) { c = dr.getACodeIdentifierComment() } + +/** A deviation scope. */ +class DeviationScope extends TDeviationScope { + /** Gets the location at which this deviation was defined. */ + abstract Locatable getDeviationDefinitionLocation(); + + /** Gets the Query being deviated. */ + abstract Query getQuery(); + + abstract string toString(); + + abstract predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ); +} + +/** A deviation scope derived from a "path" entry in a `DeviationRecord`. */ +class DeviationRecordFileScope extends DeviationScope, TDeviationRecordFileScope { + private DeviationRecord getDeviationRecord() { this = TDeviationRecordFileScope(result, _) } + + override Locatable getDeviationDefinitionLocation() { result = getDeviationRecord() } + + private File getFile() { this = TDeviationRecordFileScope(_, result) } + + override Query getQuery() { result = getDeviationRecord().getQuery() } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + // In an ideal world, we would produce a URL here that informed the AlertSuppression code that + // the whole file was suppressed. However, experimentation suggestions the alert suppression + // code only works with locations with lines and columns, so we generate a location that covers + // the whole "indexed" file, by finding the location indexed in the database with the latest + // line and column number. + exists(File f | f = getFile() | + f.getLocation().hasLocationInfo(filepath, _, _, _, _) and + startline = 1 and + startcolumn = 1 and + endline = getLastLineNumber(f) and + endcolumn = getLastColumnNumber(f) + ) + } + + override string toString() { + result = "Deviation of " + getDeviationRecord().getQuery() + " for " + getFile() + "." + } +} + +/** + * A deviation scope derived from a comment corresponding to a "code-identifier" entry for a + * `DeviationRecord`. + */ +class DeviationRecordCommentScope extends DeviationScope, TDeviationRecordCommentScope { + private DeviationRecord getDeviationRecord() { this = TDeviationRecordCommentScope(result, _) } + + private Comment getComment() { this = TDeviationRecordCommentScope(_, result) } + + override Locatable getDeviationDefinitionLocation() { result = getDeviationRecord() } + + override Query getQuery() { result = getDeviationRecord().getQuery() } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + getComment().getLocation().hasLocationInfo(filepath, startline, _, endline, endcolumn) and + startcolumn = 1 + } + + override string toString() { + result = + "Deviation of " + getDeviationRecord().getQuery() + " for comment " + getComment() + "." + } +} + +from DeviationScope deviationScope +select deviationScope.getDeviationDefinitionLocation(), // suppression comment + "// lgtm[" + deviationScope.getQuery().getQueryId() + "]", // text of suppression comment (excluding delimiters) + "lgtm[" + deviationScope.getQuery().getQueryId() + "]", // text of suppression annotation + deviationScope // scope of suppression diff --git a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected new file mode 100644 index 0000000000..50ceb35b9d --- /dev/null +++ b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected @@ -0,0 +1,7 @@ +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:12:1:12:58 | Deviation of cpp/autosar/type-long-double-used for comment // a-0-4-2-deviation COMPLIANT[DEVIATED]. | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/unused-return-value] | lgtm[cpp/autosar/unused-return-value] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/unused-return-value for nested/nested2/test2.h. | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | coding-standards.xml:1:1:17:19 | Deviation of cpp/autosar/useless-assignment for coding-standards.xml. | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | main.cpp:1:1:14:1 | Deviation of cpp/autosar/useless-assignment for main.cpp. | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/coding-standards.xml:1:1:13:19 | Deviation of cpp/autosar/useless-assignment for nested/coding-standards.xml. | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/useless-assignment for nested/nested2/test2.h. | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/test.h:1:1:6:1 | Deviation of cpp/autosar/useless-assignment for nested/test.h. | diff --git a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.qlref b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.qlref new file mode 100644 index 0000000000..6268ee7342 --- /dev/null +++ b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.qlref @@ -0,0 +1 @@ +codingstandards/cpp/deviations/DeviationsSuppression.ql \ No newline at end of file From 1e4011f73443b8b080385dcea3a3abce7f2b7858 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Wed, 26 Mar 2025 11:46:30 +0000 Subject: [PATCH 276/370] Add change note. --- change_notes/2025-03-26-deviations-suppression.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 change_notes/2025-03-26-deviations-suppression.md diff --git a/change_notes/2025-03-26-deviations-suppression.md b/change_notes/2025-03-26-deviations-suppression.md new file mode 100644 index 0000000000..5dcb5e8dba --- /dev/null +++ b/change_notes/2025-03-26-deviations-suppression.md @@ -0,0 +1 @@ + - The `DeviationsSuppression.ql` query has been restored after being incorrectly deleted in a previous release. \ No newline at end of file From 6b9dc41a53e8840cd0c8aaa07dfe6b0cb9600d08 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 26 Mar 2025 23:40:27 -0700 Subject: [PATCH 277/370] Feedback --- change_notes/2025-03-11-various-misra-amendments.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/change_notes/2025-03-11-various-misra-amendments.md b/change_notes/2025-03-11-various-misra-amendments.md index 99acdcc63a..19783fe803 100644 --- a/change_notes/2025-03-11-various-misra-amendments.md +++ b/change_notes/2025-03-11-various-misra-amendments.md @@ -5,4 +5,5 @@ - `RULE-18-6` - `ThreadLocalObjectAddressCopiedToGlobalObject.ql`: - New query added to detect thread local objects assigned to static storage duration objects. - `RULE-21-12` - `ExceptionHandlingFeaturesOfFenvhUsed.ql`: - - Added reports for `#include`ing "fenv.h", and for using `fesetenv`, `feupdatenv`, and `fesetround`. \ No newline at end of file + - Added reports for `#include`ing "fenv.h", and for using `fesetenv`, `feupdatenv`, and `fesetround`. + - Report message altered to handle new cases. \ No newline at end of file From dae8162b31cc8914a8662513854b1370492e8a0c Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 27 Mar 2025 00:48:07 -0700 Subject: [PATCH 278/370] Address feedback --- c/common/src/codingstandards/c/SubObjects.qll | 35 ++++++++++++++ .../GlobalInitializationAnalysis.qll | 4 +- .../DIR-5-1/PossibleDataRaceBetweenThreads.ql | 40 +++++++++------- .../InvalidOperationOnUnlockedMutex.ql | 2 +- ...NonRecursiveMutexRecursivelyLockedAudit.ql | 4 +- ...onditionVariableUsedWithMultipleMutexes.ql | 2 +- .../ThreadStorageNotInitializedBeforeUse.ql | 2 +- .../PossibleDataRaceBetweenThreads.expected | 48 +++++++++---------- c/misra/test/rules/RULE-22-14/test.c | 12 +++++ .../InvalidOperationOnUnlockedMutex.expected | 32 ++++++------- ...ursiveMutexRecursivelyLockedAudit.expected | 12 ++--- ...onVariableUsedWithMultipleMutexes.expected | 4 +- ...eadStorageNotInitializedBeforeUse.expected | 10 ++-- .../cpp/concurrency/LockingOperation.qll | 23 ++++----- rule_packages/c/Concurrency9.json | 2 +- 15 files changed, 140 insertions(+), 92 deletions(-) diff --git a/c/common/src/codingstandards/c/SubObjects.qll b/c/common/src/codingstandards/c/SubObjects.qll index 282b0fb5eb..66f15cd18c 100644 --- a/c/common/src/codingstandards/c/SubObjects.qll +++ b/c/common/src/codingstandards/c/SubObjects.qll @@ -1,3 +1,31 @@ +/** + * A library that expands upon the `Objects.qll` library, to support nested "Objects" such as + * `x.y.z` or `x[i][j]` within an object `x`. + * + * Objects in C are values in memory, that have a type and a storage duration. In the case of + * array objects and struct objects, the object will contain other objects. The these subobjects + * will share properties of the root object such as storage duration. This library can be used to, + * for instance, find all usages of a struct member to ensure that member is initialized before it + * is used. + * + * To use this library, select `SubObject` and find its usages in the AST via `getAnAccess()` (to + * find usages of the subobject by value) or `getAnAddressOfExpr()` (to find usages of the object + * by address). + * + * Note that a struct or array object may contain a pointer. In this case, the pointer itself is + * a subobject of the struct or array object, but the object that the pointer points to is not. + * This is because the pointed-to object does not necessarily have the same storage duration, + * lifetime, or linkage as the pointer and the object containing the pointer. + * + * Note as well that `getAnAccess()` on an array subobject will return all accesses to the array, + * not just accesses to a particular index. For this reason, `SubObject` exposes the predicate + * `isPrecise()`. If a subobject is precise, that means all results of `getAnAccess()` will + * definitely refer to the same object in memory. If it is not precise, the different accesses + * may refer to the same or different objects in memory. For instance, `x[i].y` and `x[j].y` are + * the same object if `i` and `j` are the same, but they are different objects if `i` and `j` are + * different. + */ + import codingstandards.c.Objects newtype TSubObject = @@ -70,6 +98,8 @@ class SubObject extends TSubObject { exists(MemberVariable m | this = TObjectMember(_, m) and result = m.getAnAccess() and + // Only consider `DotFieldAccess`es, not `PointerFieldAccess`es, as the latter + // are not subobjects of the root object: result.(DotFieldAccess).getQualifier() = getParent().getAnAccess() ) or @@ -79,6 +109,11 @@ class SubObject extends TSubObject { AddressOfExpr getAnAddressOfExpr() { result.getOperand() = this.getAnAccess() } + /** + * Get the "root" object identity to which this subobject belongs. For instance, in the + * expression `x.y.z`, the root object is `x`. This subobject will share properties with the root + * object such as storage duration, lifetime, and linkage. + */ ObjectIdentity getRootIdentity() { exists(ObjectIdentity i | this = TObjectRoot(i) and diff --git a/c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll b/c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll index 90d0a4630a..2906883ae9 100644 --- a/c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll +++ b/c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll @@ -7,7 +7,9 @@ signature module GlobalInitializationAnalysisConfigSig { /** A function which is not called or started as a thread */ default predicate isRootFunction(Function f) { not exists(Function f2 | f2.calls(f)) and - not f instanceof ThreadedFunction + not f instanceof ThreadedFunction and + // Exclude functions which are used as function pointers. + not exists(FunctionAccess access | f = access.getTarget()) } ObjectIdentity getAnInitializedObject(Expr e); diff --git a/c/misra/src/rules/DIR-5-1/PossibleDataRaceBetweenThreads.ql b/c/misra/src/rules/DIR-5-1/PossibleDataRaceBetweenThreads.ql index 443dc284fd..edf3705a9b 100644 --- a/c/misra/src/rules/DIR-5-1/PossibleDataRaceBetweenThreads.ql +++ b/c/misra/src/rules/DIR-5-1/PossibleDataRaceBetweenThreads.ql @@ -47,7 +47,7 @@ class NonReentrantOperation extends TNonReentrantOperation { ) } - Expr getARead() { + Expr getAReadExpr() { exists(SubObject object | this = TReadWrite(object) and result = object.getAnAccess() @@ -56,7 +56,7 @@ class NonReentrantOperation extends TNonReentrantOperation { this = TStdFunctionCall(result) } - Expr getAWrite() { + Expr getAWriteExpr() { exists(SubObject object, Assignment assignment | this = TReadWrite(object) and result = assignment and @@ -94,16 +94,20 @@ class NonReentrantOperation extends TNonReentrantOperation { class WritingThread extends ThreadedFunction { NonReentrantOperation aWriteObject; - Expr aWrite; + Expr aWriteExpr; WritingThread() { - aWrite = aWriteObject.getAWrite() and - this.calls*(aWrite.getEnclosingFunction()) and - not aWrite instanceof LockProtectedControlFlowNode and - not aWrite.getEnclosingFunction().getName().matches(["%init%", "%boot%", "%start%"]) + aWriteExpr = aWriteObject.getAWriteExpr() and + // This function directly contains the write expression, or transitively calls the function + // that contains the write expression. + this.calls*(aWriteExpr.getEnclosingFunction()) and + // The write isn't synchronized with a mutex or condition object. + not aWriteExpr instanceof LockProtectedControlFlowNode and + // The write doesn't seem to be during a special initialization phase of the program. + not aWriteExpr.getEnclosingFunction().getName().matches(["%init%", "%boot%", "%start%"]) } - Expr getAWrite() { result = aWrite } + Expr getAWriteExpr() { result = aWriteExpr } } class ReadingThread extends ThreadedFunction { @@ -111,22 +115,22 @@ class ReadingThread extends ThreadedFunction { ReadingThread() { exists(NonReentrantOperation op | - aReadExpr = op.getARead() and + aReadExpr = op.getAReadExpr() and this.calls*(aReadExpr.getEnclosingFunction()) and not aReadExpr instanceof LockProtectedControlFlowNode ) } - Expr getARead() { result = aReadExpr } + Expr getAReadExpr() { result = aReadExpr } } predicate mayBeDataRace(Expr write, Expr read, NonReentrantOperation operation) { exists(WritingThread wt | - wt.getAWrite() = write and - write = operation.getAWrite() and + wt.getAWriteExpr() = write and + write = operation.getAWriteExpr() and exists(ReadingThread rt | - read = rt.getARead() and - read = operation.getARead() and + read = rt.getAReadExpr() and + read = operation.getAReadExpr() and ( wt.isMultiplySpawned() or not wt = rt @@ -141,18 +145,18 @@ from where not isExcluded(write, Concurrency9Package::possibleDataRaceBetweenThreadsQuery()) and mayBeDataRace(write, read, operation) and - wt = min(WritingThread f | f.getAWrite() = write | f order by f.getName()) and - rt = min(ReadingThread f | f.getARead() = read | f order by f.getName()) and + wt = min(WritingThread f | f.getAWriteExpr() = write | f order by f.getName()) and + rt = min(ReadingThread f | f.getAReadExpr() = read | f order by f.getName()) and writeString = operation.getWriteString() and readString = operation.getReadString() and if wt.isMultiplySpawned() then message = "Threaded " + writeString + - " $@ not synchronized, for example from thread function $@ spawned from a loop." + " $@ not synchronized from thread function $@ spawned from a loop." else message = "Threaded " + writeString + - " $@, for example from thread function $@, not synchronized with $@, for example from thread function $@." + " $@ from thread function $@ is not synchronized with $@ from thread function $@." select write, message, operation.getSourceElement(), operation.toString(), wt, wt.getName(), read, "concurrent " + readString, rt, rt.getName() diff --git a/c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql b/c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql index 7c0b86f145..252b4a7d9f 100644 --- a/c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql +++ b/c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql @@ -64,5 +64,5 @@ where not isExcluded(operation, Concurrency9Package::invalidOperationOnUnlockedMutexQuery()) and mutex = operation.getMutex() and not DominatingSet::isDominatedByBehavior(operation) -select operation, "Invalid operation on mutex '$@' not locked by the current thread", +select operation, "Invalid operation on mutex '$@' not locked by the current thread.", mutex.getRootIdentity(), mutex.toString() diff --git a/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql b/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql index 4b70a21527..d242f75f57 100644 --- a/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql +++ b/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql @@ -2,7 +2,7 @@ * @id c/misra/non-recursive-mutex-recursively-locked-audit * @name RULE-22-18: (Audit) Non-recursive mutexes shall not be recursively locked * @description Mutex that may be initialized without mtx_recursive shall not be locked by a thread - * that has previous may havec locked it. + * that may have previously locked it. * @kind problem * @precision high * @problem.severity error @@ -57,4 +57,4 @@ where isTrackableMutex(lockCall, true) or isTrackableMutex(coveredByLock, true) ) -select n, "Mutex locked after previous $@.", coveredByLock, "already locked" +select n, "Mutex locked after it was already $@.", coveredByLock, "previously locked" diff --git a/c/misra/src/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.ql b/c/misra/src/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.ql index afa2556646..0d5aa5399f 100644 --- a/c/misra/src/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.ql +++ b/c/misra/src/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.ql @@ -64,6 +64,6 @@ where useOne = firstCallForConditionMutex(cond, mutexOne) and useTwo = firstCallForConditionMutex(cond, mutexOne) select useOne, - "Condition variable $@ associated with multiple mutexes, operation uses mutex $@ while $@ uses other mutex $@", + "Condition variable $@ associated with multiple mutexes, operation uses mutex $@ while $@ uses other mutex $@.", cond.getRootIdentity(), cond.toString(), mutexOne.getRootIdentity(), mutexOne.toString(), useTwo, "another operation", mutexTwo.getRootIdentity(), mutexTwo.toString() diff --git a/c/misra/src/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.ql b/c/misra/src/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.ql index 652b5d1f8c..1edf4aa9c3 100644 --- a/c/misra/src/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.ql +++ b/c/misra/src/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.ql @@ -40,5 +40,5 @@ where not isExcluded(objUse, Concurrency9Package::threadStorageNotInitializedBeforeUseQuery()) and InitAnalysis::uninitializedFrom(objUse, obj, callRoot) select objUse, - "Thread specific storage pointer '$@' possibly used before initialization, from entry point function '$@'.", + "Thread specific storage pointer '$@' used before initialization from entry point function '$@'.", obj, obj.toString(), callRoot, callRoot.getName() diff --git a/c/misra/test/rules/DIR-5-1/PossibleDataRaceBetweenThreads.expected b/c/misra/test/rules/DIR-5-1/PossibleDataRaceBetweenThreads.expected index 3f32b09d5c..e1c0e9389d 100644 --- a/c/misra/test/rules/DIR-5-1/PossibleDataRaceBetweenThreads.expected +++ b/c/misra/test/rules/DIR-5-1/PossibleDataRaceBetweenThreads.expected @@ -1,24 +1,24 @@ -| test.c:31:3:31:8 | ... = ... | Threaded write to object $@, for example from thread function $@, not synchronized with $@, for example from thread function $@. | test.c:11:5:11:6 | g2 | g2 | test.c:30:6:30:29 | single_thread4_writes_g2 | single_thread4_writes_g2 | test.c:27:3:27:4 | g2 | concurrent read operation | test.c:26:6:26:28 | single_thread3_reads_g2 | single_thread3_reads_g2 | -| test.c:35:3:35:8 | ... = ... | Threaded write to object $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:12:5:12:6 | g3 | g3 | test.c:34:6:34:27 | many_thread5_writes_g3 | many_thread5_writes_g3 | test.c:35:3:35:4 | g3 | concurrent read operation | test.c:34:6:34:27 | many_thread5_writes_g3 | many_thread5_writes_g3 | -| test.c:71:3:71:11 | ... = ... | Threaded write to object $@, for example from thread function $@, not synchronized with $@, for example from thread function $@. | test.c:68:3:68:4 | g7 | g7.m1 | test.c:70:6:70:33 | single_thread11_writes_g7_m1 | single_thread11_writes_g7_m1 | test.c:75:6:75:7 | m1 | concurrent read operation | test.c:74:6:74:33 | single_thread12_writes_g7_m1 | single_thread12_writes_g7_m1 | -| test.c:75:3:75:11 | ... = ... | Threaded write to object $@, for example from thread function $@, not synchronized with $@, for example from thread function $@. | test.c:68:3:68:4 | g7 | g7.m1 | test.c:74:6:74:33 | single_thread12_writes_g7_m1 | single_thread12_writes_g7_m1 | test.c:71:6:71:7 | m1 | concurrent read operation | test.c:70:6:70:33 | single_thread11_writes_g7_m1 | single_thread11_writes_g7_m1 | -| test.c:79:3:79:11 | call to setlocale | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:79:3:79:11 | call to setlocale | setlocale | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:79:3:79:11 | call to setlocale | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:80:3:80:8 | call to tmpnam | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:80:3:80:8 | call to tmpnam | tmpnam | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:80:3:80:8 | call to tmpnam | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:81:3:81:6 | call to rand | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:81:3:81:6 | call to rand | rand | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:81:3:81:6 | call to rand | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:82:3:82:7 | call to srand | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:82:3:82:7 | call to srand | srand | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:82:3:82:7 | call to srand | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:83:3:83:8 | call to getenv | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:83:3:83:8 | call to getenv | getenv | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:83:3:83:8 | call to getenv | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:84:3:84:10 | call to getenv_s | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:84:3:84:10 | call to getenv_s | getenv_s | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:84:3:84:10 | call to getenv_s | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:86:3:86:10 | call to strerror | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:86:3:86:10 | call to strerror | strerror | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:86:3:86:10 | call to strerror | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:87:3:87:9 | call to asctime | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:87:3:87:9 | call to asctime | asctime | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:87:3:87:9 | call to asctime | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:88:3:88:7 | call to ctime | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:88:3:88:7 | call to ctime | ctime | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:88:3:88:7 | call to ctime | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:89:3:89:8 | call to gmtime | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:89:3:89:8 | call to gmtime | gmtime | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:89:3:89:8 | call to gmtime | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:90:3:90:11 | call to localtime | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:90:3:90:11 | call to localtime | localtime | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:90:3:90:11 | call to localtime | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:91:3:91:10 | call to mbrtoc16 | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:91:3:91:10 | call to mbrtoc16 | mbrtoc16 | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:91:3:91:10 | call to mbrtoc16 | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:92:3:92:10 | call to mbrtoc32 | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:92:3:92:10 | call to mbrtoc32 | mbrtoc32 | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:92:3:92:10 | call to mbrtoc32 | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:93:3:93:10 | call to c16rtomb | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:93:3:93:10 | call to c16rtomb | c16rtomb | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:93:3:93:10 | call to c16rtomb | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:94:3:94:10 | call to c32rtomb | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:94:3:94:10 | call to c32rtomb | c32rtomb | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:94:3:94:10 | call to c32rtomb | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:95:3:95:8 | call to mbrlen | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:95:3:95:8 | call to mbrlen | mbrlen | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:95:3:95:8 | call to mbrlen | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:96:3:96:9 | call to mbrtowc | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:96:3:96:9 | call to mbrtowc | mbrtowc | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:96:3:96:9 | call to mbrtowc | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:97:3:97:9 | call to wcrtomb | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:97:3:97:9 | call to wcrtomb | wcrtomb | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:97:3:97:9 | call to wcrtomb | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:98:3:98:11 | call to mbsrtowcs | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:98:3:98:11 | call to mbsrtowcs | mbsrtowcs | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:98:3:98:11 | call to mbsrtowcs | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | -| test.c:99:3:99:11 | call to wcsrtombs | Threaded call to non-reentrant function $@ not synchronized, for example from thread function $@ spawned from a loop. | test.c:99:3:99:11 | call to wcsrtombs | wcsrtombs | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:99:3:99:11 | call to wcsrtombs | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:31:3:31:8 | ... = ... | Threaded write to object $@ from thread function $@ is not synchronized with $@ from thread function $@. | test.c:11:5:11:6 | g2 | g2 | test.c:30:6:30:29 | single_thread4_writes_g2 | single_thread4_writes_g2 | test.c:27:3:27:4 | g2 | concurrent read operation | test.c:26:6:26:28 | single_thread3_reads_g2 | single_thread3_reads_g2 | +| test.c:35:3:35:8 | ... = ... | Threaded write to object $@ not synchronized from thread function $@ spawned from a loop. | test.c:12:5:12:6 | g3 | g3 | test.c:34:6:34:27 | many_thread5_writes_g3 | many_thread5_writes_g3 | test.c:35:3:35:4 | g3 | concurrent read operation | test.c:34:6:34:27 | many_thread5_writes_g3 | many_thread5_writes_g3 | +| test.c:71:3:71:11 | ... = ... | Threaded write to object $@ from thread function $@ is not synchronized with $@ from thread function $@. | test.c:68:3:68:4 | g7 | g7.m1 | test.c:70:6:70:33 | single_thread11_writes_g7_m1 | single_thread11_writes_g7_m1 | test.c:75:6:75:7 | m1 | concurrent read operation | test.c:74:6:74:33 | single_thread12_writes_g7_m1 | single_thread12_writes_g7_m1 | +| test.c:75:3:75:11 | ... = ... | Threaded write to object $@ from thread function $@ is not synchronized with $@ from thread function $@. | test.c:68:3:68:4 | g7 | g7.m1 | test.c:74:6:74:33 | single_thread12_writes_g7_m1 | single_thread12_writes_g7_m1 | test.c:71:6:71:7 | m1 | concurrent read operation | test.c:70:6:70:33 | single_thread11_writes_g7_m1 | single_thread11_writes_g7_m1 | +| test.c:79:3:79:11 | call to setlocale | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:79:3:79:11 | call to setlocale | setlocale | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:79:3:79:11 | call to setlocale | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:80:3:80:8 | call to tmpnam | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:80:3:80:8 | call to tmpnam | tmpnam | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:80:3:80:8 | call to tmpnam | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:81:3:81:6 | call to rand | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:81:3:81:6 | call to rand | rand | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:81:3:81:6 | call to rand | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:82:3:82:7 | call to srand | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:82:3:82:7 | call to srand | srand | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:82:3:82:7 | call to srand | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:83:3:83:8 | call to getenv | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:83:3:83:8 | call to getenv | getenv | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:83:3:83:8 | call to getenv | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:84:3:84:10 | call to getenv_s | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:84:3:84:10 | call to getenv_s | getenv_s | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:84:3:84:10 | call to getenv_s | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:86:3:86:10 | call to strerror | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:86:3:86:10 | call to strerror | strerror | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:86:3:86:10 | call to strerror | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:87:3:87:9 | call to asctime | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:87:3:87:9 | call to asctime | asctime | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:87:3:87:9 | call to asctime | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:88:3:88:7 | call to ctime | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:88:3:88:7 | call to ctime | ctime | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:88:3:88:7 | call to ctime | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:89:3:89:8 | call to gmtime | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:89:3:89:8 | call to gmtime | gmtime | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:89:3:89:8 | call to gmtime | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:90:3:90:11 | call to localtime | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:90:3:90:11 | call to localtime | localtime | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:90:3:90:11 | call to localtime | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:91:3:91:10 | call to mbrtoc16 | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:91:3:91:10 | call to mbrtoc16 | mbrtoc16 | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:91:3:91:10 | call to mbrtoc16 | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:92:3:92:10 | call to mbrtoc32 | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:92:3:92:10 | call to mbrtoc32 | mbrtoc32 | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:92:3:92:10 | call to mbrtoc32 | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:93:3:93:10 | call to c16rtomb | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:93:3:93:10 | call to c16rtomb | c16rtomb | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:93:3:93:10 | call to c16rtomb | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:94:3:94:10 | call to c32rtomb | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:94:3:94:10 | call to c32rtomb | c32rtomb | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:94:3:94:10 | call to c32rtomb | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:95:3:95:8 | call to mbrlen | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:95:3:95:8 | call to mbrlen | mbrlen | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:95:3:95:8 | call to mbrlen | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:96:3:96:9 | call to mbrtowc | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:96:3:96:9 | call to mbrtowc | mbrtowc | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:96:3:96:9 | call to mbrtowc | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:97:3:97:9 | call to wcrtomb | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:97:3:97:9 | call to wcrtomb | wcrtomb | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:97:3:97:9 | call to wcrtomb | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:98:3:98:11 | call to mbsrtowcs | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:98:3:98:11 | call to mbsrtowcs | mbsrtowcs | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:98:3:98:11 | call to mbsrtowcs | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | +| test.c:99:3:99:11 | call to wcsrtombs | Threaded call to non-reentrant function $@ not synchronized from thread function $@ spawned from a loop. | test.c:99:3:99:11 | call to wcsrtombs | wcsrtombs | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | test.c:99:3:99:11 | call to wcsrtombs | concurrent call to non-reentrant function | test.c:78:6:78:43 | many_thread13_calls_nonreentrant_funcs | many_thread13_calls_nonreentrant_funcs | diff --git a/c/misra/test/rules/RULE-22-14/test.c b/c/misra/test/rules/RULE-22-14/test.c index d8f1770ad8..c664a08dc3 100644 --- a/c/misra/test/rules/RULE-22-14/test.c +++ b/c/misra/test/rules/RULE-22-14/test.c @@ -143,4 +143,16 @@ void invalid_mtx_init_types() { mtx_init(&m, mtx_plain & mtx_recursive); // NON-COMPLIANT mtx_init(&m, mtx_plain * mtx_recursive); // NON-COMPLIANT mtx_init(&m, -1); // NON-COMPLIANT +} + +void function_pointer_uses_global_mutexes() { + // If the function has been used as a function pointer, we don't attempt to + // analyze this. + mtx_lock(&g1); // COMPLIANT + mtx_lock(&g2.m1); // COMPLIANT + mtx_lock(g3); // COMPLIANT +} + +void take_function_pointer() { + void (*f)(void) = function_pointer_uses_global_mutexes; } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.expected b/c/misra/test/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.expected index 76d3ac1ba1..254d55adc2 100644 --- a/c/misra/test/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.expected +++ b/c/misra/test/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.expected @@ -1,16 +1,16 @@ -| test.c:19:3:19:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:11:9:11:10 | l1 | l1 | -| test.c:20:3:20:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:11:9:11:10 | l1 | l1 | -| test.c:25:3:25:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:14:5:14:6 | l2 | l2.m1 | -| test.c:26:3:26:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:14:5:14:6 | l2 | l2.m1 | -| test.c:31:3:31:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:3:7:3:8 | g1 | g1 | -| test.c:32:3:32:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:3:7:3:8 | g1 | g1 | -| test.c:37:3:37:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:6:3:6:4 | g2 | g2.m1 | -| test.c:38:3:38:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:6:3:6:4 | g2 | g2.m1 | -| test.c:47:3:47:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:11:9:11:10 | l1 | l1 | -| test.c:48:3:48:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:14:5:14:6 | l2 | l2.m1 | -| test.c:49:3:49:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:3:7:3:8 | g1 | g1 | -| test.c:50:3:50:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread | test.c:6:3:6:4 | g2 | g2.m1 | -| test.c:51:3:51:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:11:9:11:10 | l1 | l1 | -| test.c:52:3:52:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:14:5:14:6 | l2 | l2.m1 | -| test.c:53:3:53:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:3:7:3:8 | g1 | g1 | -| test.c:54:3:54:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread | test.c:6:3:6:4 | g2 | g2.m1 | +| test.c:19:3:19:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread. | test.c:11:9:11:10 | l1 | l1 | +| test.c:20:3:20:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread. | test.c:11:9:11:10 | l1 | l1 | +| test.c:25:3:25:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread. | test.c:14:5:14:6 | l2 | l2.m1 | +| test.c:26:3:26:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread. | test.c:14:5:14:6 | l2 | l2.m1 | +| test.c:31:3:31:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread. | test.c:3:7:3:8 | g1 | g1 | +| test.c:32:3:32:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread. | test.c:3:7:3:8 | g1 | g1 | +| test.c:37:3:37:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread. | test.c:6:3:6:4 | g2 | g2.m1 | +| test.c:38:3:38:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread. | test.c:6:3:6:4 | g2 | g2.m1 | +| test.c:47:3:47:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread. | test.c:11:9:11:10 | l1 | l1 | +| test.c:48:3:48:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread. | test.c:14:5:14:6 | l2 | l2.m1 | +| test.c:49:3:49:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread. | test.c:3:7:3:8 | g1 | g1 | +| test.c:50:3:50:10 | call to cnd_wait | Invalid operation on mutex '$@' not locked by the current thread. | test.c:6:3:6:4 | g2 | g2.m1 | +| test.c:51:3:51:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread. | test.c:11:9:11:10 | l1 | l1 | +| test.c:52:3:52:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread. | test.c:14:5:14:6 | l2 | l2.m1 | +| test.c:53:3:53:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread. | test.c:3:7:3:8 | g1 | g1 | +| test.c:54:3:54:12 | call to mtx_unlock | Invalid operation on mutex '$@' not locked by the current thread. | test.c:6:3:6:4 | g2 | g2.m1 | diff --git a/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.expected b/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.expected index 8f359c90f8..e268f5367e 100644 --- a/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.expected +++ b/c/misra/test/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.expected @@ -1,6 +1,6 @@ -| test.c:44:3:44:10 | call to mtx_lock | Mutex locked after previous $@. | test.c:43:3:43:10 | call to mtx_lock | already locked | -| test.c:49:3:49:10 | call to mtx_lock | Mutex locked after previous $@. | test.c:48:3:48:10 | call to mtx_lock | already locked | -| test.c:54:3:54:10 | call to mtx_lock | Mutex locked after previous $@. | test.c:53:3:53:10 | call to mtx_lock | already locked | -| test.c:59:3:59:10 | call to mtx_lock | Mutex locked after previous $@. | test.c:58:3:58:10 | call to mtx_lock | already locked | -| test.c:76:3:76:10 | call to mtx_lock | Mutex locked after previous $@. | test.c:75:3:75:10 | call to mtx_lock | already locked | -| test.c:81:3:81:10 | call to mtx_lock | Mutex locked after previous $@. | test.c:80:3:80:10 | call to mtx_lock | already locked | +| test.c:44:3:44:10 | call to mtx_lock | Mutex locked after it was already $@. | test.c:43:3:43:10 | call to mtx_lock | previously locked | +| test.c:49:3:49:10 | call to mtx_lock | Mutex locked after it was already $@. | test.c:48:3:48:10 | call to mtx_lock | previously locked | +| test.c:54:3:54:10 | call to mtx_lock | Mutex locked after it was already $@. | test.c:53:3:53:10 | call to mtx_lock | previously locked | +| test.c:59:3:59:10 | call to mtx_lock | Mutex locked after it was already $@. | test.c:58:3:58:10 | call to mtx_lock | previously locked | +| test.c:76:3:76:10 | call to mtx_lock | Mutex locked after it was already $@. | test.c:75:3:75:10 | call to mtx_lock | previously locked | +| test.c:81:3:81:10 | call to mtx_lock | Mutex locked after it was already $@. | test.c:80:3:80:10 | call to mtx_lock | previously locked | diff --git a/c/misra/test/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.expected b/c/misra/test/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.expected index ee9dff0be2..c9785067c6 100644 --- a/c/misra/test/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.expected +++ b/c/misra/test/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.expected @@ -1,2 +1,2 @@ -| test.c:19:3:19:10 | call to cnd_wait | Condition variable $@ associated with multiple mutexes, operation uses mutex $@ while $@ uses other mutex $@ | test.c:16:9:16:12 | cnd1 | cnd1 | test.c:17:9:17:12 | mtx1 | mtx1 | test.c:19:3:19:10 | call to cnd_wait | another operation | test.c:18:9:18:12 | mtx2 | mtx2 | -| test.c:41:3:41:10 | call to cnd_wait | Condition variable $@ associated with multiple mutexes, operation uses mutex $@ while $@ uses other mutex $@ | test.c:37:7:37:11 | gcnd1 | gcnd1 | test.c:38:7:38:11 | gmtx1 | gmtx1 | test.c:41:3:41:10 | call to cnd_wait | another operation | test.c:39:7:39:11 | gmtx2 | gmtx2 | +| test.c:19:3:19:10 | call to cnd_wait | Condition variable $@ associated with multiple mutexes, operation uses mutex $@ while $@ uses other mutex $@. | test.c:16:9:16:12 | cnd1 | cnd1 | test.c:17:9:17:12 | mtx1 | mtx1 | test.c:19:3:19:10 | call to cnd_wait | another operation | test.c:18:9:18:12 | mtx2 | mtx2 | +| test.c:41:3:41:10 | call to cnd_wait | Condition variable $@ associated with multiple mutexes, operation uses mutex $@ while $@ uses other mutex $@. | test.c:37:7:37:11 | gcnd1 | gcnd1 | test.c:38:7:38:11 | gmtx1 | gmtx1 | test.c:41:3:41:10 | call to cnd_wait | another operation | test.c:39:7:39:11 | gmtx2 | gmtx2 | diff --git a/c/misra/test/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.expected b/c/misra/test/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.expected index 9a9b86dfa2..301debd7e8 100644 --- a/c/misra/test/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.expected +++ b/c/misra/test/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.expected @@ -1,5 +1,5 @@ -| test.c:6:11:6:13 | & ... | Thread specific storage pointer '$@' possibly used before initialization, from entry point function '$@'. | test.c:5:9:5:10 | l1 | l1 | test.c:4:6:4:19 | use_local_mtxs | use_local_mtxs | -| test.c:11:11:11:12 | l4 | Thread specific storage pointer '$@' possibly used before initialization, from entry point function '$@'. | test.c:10:15:10:20 | call to malloc | call to malloc | test.c:16:6:16:31 | root1_calls_use_local_mtxs | root1_calls_use_local_mtxs | -| test.c:25:11:25:13 | & ... | Thread specific storage pointer '$@' possibly used before initialization, from entry point function '$@'. | test.c:22:7:22:8 | g1 | g1 | test.c:24:6:24:28 | root2_uses_global_tss_t | root2_uses_global_tss_t | -| test.c:38:11:38:13 | & ... | Thread specific storage pointer '$@' possibly used before initialization, from entry point function '$@'. | test.c:22:7:22:8 | g1 | g1 | test.c:41:6:41:45 | root4_call_thread_without_initialization | root4_call_thread_without_initialization | -| test.c:58:11:58:13 | & ... | Thread specific storage pointer '$@' possibly used before initialization, from entry point function '$@'. | test.c:56:7:56:8 | g5 | g5 | test.c:67:6:67:50 | root6_spawn_thread_uninitialized_thread_local | root6_spawn_thread_uninitialized_thread_local | +| test.c:6:11:6:13 | & ... | Thread specific storage pointer '$@' used before initialization from entry point function '$@'. | test.c:5:9:5:10 | l1 | l1 | test.c:4:6:4:19 | use_local_mtxs | use_local_mtxs | +| test.c:11:11:11:12 | l4 | Thread specific storage pointer '$@' used before initialization from entry point function '$@'. | test.c:10:15:10:20 | call to malloc | call to malloc | test.c:16:6:16:31 | root1_calls_use_local_mtxs | root1_calls_use_local_mtxs | +| test.c:25:11:25:13 | & ... | Thread specific storage pointer '$@' used before initialization from entry point function '$@'. | test.c:22:7:22:8 | g1 | g1 | test.c:24:6:24:28 | root2_uses_global_tss_t | root2_uses_global_tss_t | +| test.c:38:11:38:13 | & ... | Thread specific storage pointer '$@' used before initialization from entry point function '$@'. | test.c:22:7:22:8 | g1 | g1 | test.c:41:6:41:45 | root4_call_thread_without_initialization | root4_call_thread_without_initialization | +| test.c:58:11:58:13 | & ... | Thread specific storage pointer '$@' used before initialization from entry point function '$@'. | test.c:56:7:56:8 | g5 | g5 | test.c:67:6:67:50 | root6_spawn_thread_uninitialized_thread_local | root6_spawn_thread_uninitialized_thread_local | diff --git a/cpp/common/src/codingstandards/cpp/concurrency/LockingOperation.qll b/cpp/common/src/codingstandards/cpp/concurrency/LockingOperation.qll index 1dd753d122..95404b114a 100644 --- a/cpp/common/src/codingstandards/cpp/concurrency/LockingOperation.qll +++ b/cpp/common/src/codingstandards/cpp/concurrency/LockingOperation.qll @@ -52,18 +52,11 @@ class CPPMutexFunctionCall extends MutexFunctionCall { VariableAccess var; CPPMutexFunctionCall() { - ( - // the non recursive kinds - getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "mutex") or - getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "timed_mutex") or - getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "shared_timed_mutex") or - // the recursive ones - getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "recursive_mutex") or - getTarget() - .(MemberFunction) - .getDeclaringType() - .hasQualifiedName("std", "recursive_timed_mutex") - ) and + getTarget() + .(MemberFunction) + .getDeclaringType() + .hasQualifiedName("std", + ["mutex", "timed_mutex", "shared_timed_mutex", "recursive_mutex", "recursive_timed_mutex"]) and var = getQualifier() } @@ -71,8 +64,10 @@ class CPPMutexFunctionCall extends MutexFunctionCall { * Holds if this mutex is a recursive mutex. */ override predicate isRecursive() { - getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "recursive_mutex") or - getTarget().(MemberFunction).getDeclaringType().hasQualifiedName("std", "recursive_timed_mutex") + getTarget() + .(MemberFunction) + .getDeclaringType() + .hasQualifiedName("std", ["recursive_mutex", "recursive_timed_mutex"]) } /** diff --git a/rule_packages/c/Concurrency9.json b/rule_packages/c/Concurrency9.json index 39c5cc58a8..7a88f4e2ab 100644 --- a/rule_packages/c/Concurrency9.json +++ b/rule_packages/c/Concurrency9.json @@ -82,7 +82,7 @@ ] }, { - "description": "Mutex that may be initialized without mtx_recursive shall not be locked by a thread that has previous may havec locked it.", + "description": "Mutex that may be initialized without mtx_recursive shall not be locked by a thread that may have previously locked it.", "kind": "problem", "name": "(Audit) Non-recursive mutexes shall not be recursively locked", "precision": "high", From 0a6460986a1994659f43927f2bbdcca0b306e020 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 27 Mar 2025 01:40:53 -0700 Subject: [PATCH 279/370] Implement missing amendment for directive 4-11 from misra C 2012 amendment 3 --- amendments.csv | 2 +- ...cisionPeriodicTrigonometricFunctionCall.ql | 43 +++++++++++++ ...PeriodicTrigonometricFunctionCall.expected | 18 ++++++ ...ionPeriodicTrigonometricFunctionCall.qlref | 1 + c/misra/test/rules/DIR-4-11/test.c | 62 +++++++++++++++++++ ...etect-precision-limit-in-trig-functions.md | 2 + .../cpp/exclusions/c/Contracts.qll | 17 +++++ rule_packages/c/Contracts.json | 13 ++++ 8 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 c/misra/src/rules/DIR-4-11/LowPrecisionPeriodicTrigonometricFunctionCall.ql create mode 100644 c/misra/test/rules/DIR-4-11/LowPrecisionPeriodicTrigonometricFunctionCall.expected create mode 100644 c/misra/test/rules/DIR-4-11/LowPrecisionPeriodicTrigonometricFunctionCall.qlref create mode 100644 c/misra/test/rules/DIR-4-11/test.c create mode 100644 change_notes/2025-03-27-detect-precision-limit-in-trig-functions.md diff --git a/amendments.csv b/amendments.csv index 64d2e2e858..9b10149027 100644 --- a/amendments.csv +++ b/amendments.csv @@ -1,7 +1,7 @@ language,standard,amendment,rule_id,supportable,implementation_category,implemented,difficulty c,MISRA-C-2012,Amendment3,DIR-4-6,Yes,Expand,Yes,Easy c,MISRA-C-2012,Amendment3,DIR-4-9,Yes,Refine,No,Easy -c,MISRA-C-2012,Amendment3,DIR-4-11,Yes,Refine,No,Import +c,MISRA-C-2012,Amendment3,DIR-4-11,Yes,Refine,Yes,Import c,MISRA-C-2012,Amendment3,RULE-1-4,Yes,Replace,No,Easy c,MISRA-C-2012,Amendment3,RULE-10-1,Yes,Replace,Yes,Easy c,MISRA-C-2012,Amendment3,RULE-10-3,Yes,Refine,Yes,Easy diff --git a/c/misra/src/rules/DIR-4-11/LowPrecisionPeriodicTrigonometricFunctionCall.ql b/c/misra/src/rules/DIR-4-11/LowPrecisionPeriodicTrigonometricFunctionCall.ql new file mode 100644 index 0000000000..6a910a1a71 --- /dev/null +++ b/c/misra/src/rules/DIR-4-11/LowPrecisionPeriodicTrigonometricFunctionCall.ql @@ -0,0 +1,43 @@ +/** + * @id c/misra/low-precision-periodic-trigonometric-function-call + * @name DIR-4-11: The validity of values passed to trigonometric functions shall be checked + * @description Trigonometric periodic functions have significantly less precision when called with + * large floating-point values. + * @kind problem + * @precision high + * @problem.severity warning + * @tags external/misra/id/dir-4-11 + * correctness + * external/misra/c/2012/third-edition-first-revision + * external/misra/c/2012/amendment3 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis + +float getMaxAllowedAbsoluteValue(FloatingPointType t, string description) { + if t.getSize() <= 4 + then ( + // Per MISRA, assume k=1 for float types. + result = 3.15 and description = "pi" + ) else ( + // Allow k=10 for doubles, as the standard allows for a larger range depending on the + // implementation, application, and precision goals. + result = 10 * 3.15 and description = "10 * pi" + ) +} + +from FunctionCall fc, Expr argument, float maxValue, float maxAllowedValue, string maxAllowedStr +where + not isExcluded(fc, ContractsPackage::lowPrecisionPeriodicTrigonometricFunctionCallQuery()) and + fc.getTarget().getName() = ["sin", "cos", "tan"] and + argument = fc.getArgument(0) and + maxValue = rank[1](float bound | bound = [lowerBound(argument), upperBound(argument)].abs()) and + maxAllowedValue = getMaxAllowedAbsoluteValue(argument.getType(), maxAllowedStr) and + maxValue > maxAllowedValue +select fc, + "Call to periodic trigonometric function " + fc.getTarget().getName() + + " with maximum argument absolute value of " + maxValue.toString() + + ", which exceeds the recommended " + "maximum of " + maxAllowedStr + "." diff --git a/c/misra/test/rules/DIR-4-11/LowPrecisionPeriodicTrigonometricFunctionCall.expected b/c/misra/test/rules/DIR-4-11/LowPrecisionPeriodicTrigonometricFunctionCall.expected new file mode 100644 index 0000000000..d5d5892975 --- /dev/null +++ b/c/misra/test/rules/DIR-4-11/LowPrecisionPeriodicTrigonometricFunctionCall.expected @@ -0,0 +1,18 @@ +| test.c:32:5:32:7 | call to sin | Call to periodic trigonometric function sin with maximum argument absolute value of 31.4, which exceeds the recommended maximum of pi. | +| test.c:33:5:33:7 | call to cos | Call to periodic trigonometric function cos with maximum argument absolute value of 31.4, which exceeds the recommended maximum of pi. | +| test.c:34:5:34:7 | call to tan | Call to periodic trigonometric function tan with maximum argument absolute value of 31.4, which exceeds the recommended maximum of pi. | +| test.c:38:5:38:7 | call to sin | Call to periodic trigonometric function sin with maximum argument absolute value of 31.4, which exceeds the recommended maximum of pi. | +| test.c:39:5:39:7 | call to cos | Call to periodic trigonometric function cos with maximum argument absolute value of 31.4, which exceeds the recommended maximum of pi. | +| test.c:40:5:40:7 | call to tan | Call to periodic trigonometric function tan with maximum argument absolute value of 31.4, which exceeds the recommended maximum of pi. | +| test.c:49:5:49:7 | call to sin | Call to periodic trigonometric function sin with maximum argument absolute value of 314, which exceeds the recommended maximum of pi. | +| test.c:50:5:50:7 | call to cos | Call to periodic trigonometric function cos with maximum argument absolute value of 314, which exceeds the recommended maximum of pi. | +| test.c:51:5:51:7 | call to tan | Call to periodic trigonometric function tan with maximum argument absolute value of 314, which exceeds the recommended maximum of pi. | +| test.c:52:5:52:7 | call to sin | Call to periodic trigonometric function sin with maximum argument absolute value of 314, which exceeds the recommended maximum of 10 * pi. | +| test.c:53:5:53:7 | call to cos | Call to periodic trigonometric function cos with maximum argument absolute value of 314, which exceeds the recommended maximum of 10 * pi. | +| test.c:54:5:54:7 | call to tan | Call to periodic trigonometric function tan with maximum argument absolute value of 314, which exceeds the recommended maximum of 10 * pi. | +| test.c:55:5:55:7 | call to sin | Call to periodic trigonometric function sin with maximum argument absolute value of 314, which exceeds the recommended maximum of pi. | +| test.c:56:5:56:7 | call to cos | Call to periodic trigonometric function cos with maximum argument absolute value of 314, which exceeds the recommended maximum of pi. | +| test.c:57:5:57:7 | call to tan | Call to periodic trigonometric function tan with maximum argument absolute value of 314, which exceeds the recommended maximum of pi. | +| test.c:58:5:58:7 | call to sin | Call to periodic trigonometric function sin with maximum argument absolute value of 314, which exceeds the recommended maximum of 10 * pi. | +| test.c:59:5:59:7 | call to cos | Call to periodic trigonometric function cos with maximum argument absolute value of 314, which exceeds the recommended maximum of 10 * pi. | +| test.c:60:5:60:7 | call to tan | Call to periodic trigonometric function tan with maximum argument absolute value of 314, which exceeds the recommended maximum of 10 * pi. | diff --git a/c/misra/test/rules/DIR-4-11/LowPrecisionPeriodicTrigonometricFunctionCall.qlref b/c/misra/test/rules/DIR-4-11/LowPrecisionPeriodicTrigonometricFunctionCall.qlref new file mode 100644 index 0000000000..f7bd11b44d --- /dev/null +++ b/c/misra/test/rules/DIR-4-11/LowPrecisionPeriodicTrigonometricFunctionCall.qlref @@ -0,0 +1 @@ +rules/DIR-4-11/LowPrecisionPeriodicTrigonometricFunctionCall.ql \ No newline at end of file diff --git a/c/misra/test/rules/DIR-4-11/test.c b/c/misra/test/rules/DIR-4-11/test.c new file mode 100644 index 0000000000..dac34860ff --- /dev/null +++ b/c/misra/test/rules/DIR-4-11/test.c @@ -0,0 +1,62 @@ +#include +void f(int x) { + float f1 = 0.0f; + double d1 = 0.0f; + sin(f1); // COMPLIANT + cos(f1); // COMPLIANT + tan(f1); // COMPLIANT + sin(d1); // COMPLIANT + cos(d1); // COMPLIANT + tan(d1); // COMPLIANT + + if (x < 10) { + f1 += 3.14; + d1 += 3.14; + sin(f1); // COMPLIANT + cos(f1); // COMPLIANT + tan(f1); // COMPLIANT + sin(d1); // COMPLIANT + cos(d1); // COMPLIANT + tan(d1); // COMPLIANT + sin(-f1); // COMPLIANT + cos(-f1); // COMPLIANT + tan(-f1); // COMPLIANT + sin(-d1); // COMPLIANT + cos(-d1); // COMPLIANT + tan(-d1); // COMPLIANT + } + + if (x < 20) { + f1 = 3.14 * 10; + d1 = 3.14 * 10; + sin(f1); // NON-COMPLIANT + cos(f1); // NON-COMPLIANT + tan(f1); // NON-COMPLIANT + sin(d1); // COMPLIANT + cos(d1); // COMPLIANT + tan(d1); // COMPLIANT + sin(-f1); // NON-COMPLIANT + cos(-f1); // NON-COMPLIANT + tan(-f1); // NON-COMPLIANT + sin(-d1); // COMPLIANT + cos(-d1); // COMPLIANT + tan(-d1); // COMPLIANT + } + + if (x < 30) { + f1 = 3.14 * 100; + d1 = 3.14 * 100; + sin(f1); // NON-COMPLIANT + cos(f1); // NON-COMPLIANT + tan(f1); // NON-COMPLIANT + sin(d1); // NON-COMPLIANT + cos(d1); // NON-COMPLIANT + tan(d1); // NON-COMPLIANT + sin(-f1); // NON-COMPLIANT + cos(-f1); // NON-COMPLIANT + tan(-f1); // NON-COMPLIANT + sin(-d1); // NON-COMPLIANT + cos(-d1); // NON-COMPLIANT + tan(-d1); // NON-COMPLIANT + } +} \ No newline at end of file diff --git a/change_notes/2025-03-27-detect-precision-limit-in-trig-functions.md b/change_notes/2025-03-27-detect-precision-limit-in-trig-functions.md new file mode 100644 index 0000000000..914b25a2a2 --- /dev/null +++ b/change_notes/2025-03-27-detect-precision-limit-in-trig-functions.md @@ -0,0 +1,2 @@ + - `DIR-4-11` - `LowPrecisionPeriodicTrigonometricFunctionCall.ql`: + - New query within rule added to detect calls to periodic trigonometric functions with values outside of pi*k for k that depends on implementation and application precision goals, assuming k=1 for 32 bit floating types and k=10 for 64 bit floating types. diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Contracts.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Contracts.qll index 32a44a4355..174e7769b7 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/Contracts.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Contracts.qll @@ -6,6 +6,7 @@ import codingstandards.cpp.exclusions.RuleMetadata newtype ContractsQuery = TDoNotViolateInLineLinkageConstraintsQuery() or TCheckMathLibraryFunctionParametersQuery() or + TLowPrecisionPeriodicTrigonometricFunctionCallQuery() or TFunctionErrorInformationUntestedQuery() predicate isContractsQueryMetadata(Query query, string queryId, string ruleId, string category) { @@ -27,6 +28,15 @@ predicate isContractsQueryMetadata(Query query, string queryId, string ruleId, s ruleId = "DIR-4-11" and category = "required" or + query = + // `Query` instance for the `lowPrecisionPeriodicTrigonometricFunctionCall` query + ContractsPackage::lowPrecisionPeriodicTrigonometricFunctionCallQuery() and + queryId = + // `@id` for the `lowPrecisionPeriodicTrigonometricFunctionCall` query + "c/misra/low-precision-periodic-trigonometric-function-call" and + ruleId = "DIR-4-11" and + category = "required" + or query = // `Query` instance for the `functionErrorInformationUntested` query ContractsPackage::functionErrorInformationUntestedQuery() and @@ -52,6 +62,13 @@ module ContractsPackage { TQueryC(TContractsPackageQuery(TCheckMathLibraryFunctionParametersQuery())) } + Query lowPrecisionPeriodicTrigonometricFunctionCallQuery() { + //autogenerate `Query` type + result = + // `Query` type for `lowPrecisionPeriodicTrigonometricFunctionCall` query + TQueryC(TContractsPackageQuery(TLowPrecisionPeriodicTrigonometricFunctionCallQuery())) + } + Query functionErrorInformationUntestedQuery() { //autogenerate `Query` type result = diff --git a/rule_packages/c/Contracts.json b/rule_packages/c/Contracts.json index 40bf3d8b0b..e7db6fff86 100644 --- a/rule_packages/c/Contracts.json +++ b/rule_packages/c/Contracts.json @@ -44,6 +44,19 @@ "implementation_scope": { "description": "This query identifies possible domain, pole and range errors on a selection of C standard library fuctions from math.h." } + }, + { + "description": "Trigonometric periodic functions have significantly less precision when called with large floating-point values.", + "kind": "problem", + "name": "The validity of values passed to trigonometric functions shall be checked", + "precision": "high", + "severity": "warning", + "short_name": "LowPrecisionPeriodicTrigonometricFunctionCall", + "tags": [ + "correctness", + "external/misra/c/2012/third-edition-first-revision", + "external/misra/c/2012/amendment3" + ] } ], "title": "The validity of values passed to library functions shall be checked" From 00defddfa6abde09164a9b7860026fe4f497b076 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 27 Mar 2025 10:05:09 -0700 Subject: [PATCH 280/370] Fix typo --- .../RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql | 4 ++-- rule_packages/c/Concurrency9.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql b/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql index d242f75f57..7e002585b6 100644 --- a/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql +++ b/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql @@ -1,8 +1,8 @@ /** * @id c/misra/non-recursive-mutex-recursively-locked-audit * @name RULE-22-18: (Audit) Non-recursive mutexes shall not be recursively locked - * @description Mutex that may be initialized without mtx_recursive shall not be locked by a thread - * that may have previously locked it. + * @description Mutexes that may be initialized without mtx_recursive shall not be locked by a + * thread that may have previously locked it. * @kind problem * @precision high * @problem.severity error diff --git a/rule_packages/c/Concurrency9.json b/rule_packages/c/Concurrency9.json index 7a88f4e2ab..6ae1df8173 100644 --- a/rule_packages/c/Concurrency9.json +++ b/rule_packages/c/Concurrency9.json @@ -82,7 +82,7 @@ ] }, { - "description": "Mutex that may be initialized without mtx_recursive shall not be locked by a thread that may have previously locked it.", + "description": "Mutexes that may be initialized without mtx_recursive shall not be locked by a thread that may have previously locked it.", "kind": "problem", "name": "(Audit) Non-recursive mutexes shall not be recursively locked", "precision": "high", From 35cfb0f1e1e57a71a3a1d9537903a7c16aab304e Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sat, 29 Mar 2025 15:54:57 -0700 Subject: [PATCH 281/370] Add additional CERT-C rules to rules.csv --- rules.csv | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rules.csv b/rules.csv index 3f7961b630..2db1d7a66d 100644 --- a/rules.csv +++ b/rules.csv @@ -515,6 +515,7 @@ c,CERT-C,ERR30-C,Yes,Rule,,,Take care when reading errno,M19-3-1,Contracts4,Hard c,CERT-C,ERR32-C,Yes,Rule,,,Do not rely on indeterminate values of errno,,Contracts5,Hard, c,CERT-C,ERR33-C,Yes,Rule,,,Detect and handle standard library errors,MEM52-CPP,Contracts5,Hard, c,CERT-C,ERR34-C,OutOfScope,Rule,,,Detect errors when converting a string to a number,,,, +c,CERT-C,EXP16-C,Yes,Rule,,,Do not compare function pointers to constant values,,Expressions2,Medium, c,CERT-C,EXP30-C,Yes,Rule,,,Do not depend on the order of evaluation for side effects,EXP50-CPP,SideEffects1,Easy, c,CERT-C,EXP32-C,Yes,Rule,,,Do not access a volatile object through a nonvolatile reference,,Pointers3,Easy, c,CERT-C,EXP33-C,Yes,Rule,,,Do not read uninitialized memory,EXP53-CPP,InvalidMemory1,Import, @@ -530,6 +531,8 @@ c,CERT-C,EXP44-C,Yes,Rule,,,"Do not rely on side effects in operands to sizeof, c,CERT-C,EXP45-C,Yes,Rule,,,Do not perform assignments in selection statements,M6-2-1,SideEffects1,Medium, c,CERT-C,EXP46-C,Yes,Rule,,,Do not use a bitwise operator with a Boolean-like operand,,Expressions,Easy, c,CERT-C,EXP47-C,OutOfScope,Rule,,,Do not call va_arg with an argument of the incorrect type,,,, +c,CERT-C,FIO03-C,Yes,Rule,,,Do not make assumptions about fopen() and file creation,,IO5,Hard, +c,CERT-C,FIO21-C,Yes,Rule,,,Do not create temporary files in shared directories,,IO5,Easy, c,CERT-C,FIO30-C,Yes,Rule,,,Exclude user input from format strings,A27-0-1,IO1,Import, c,CERT-C,FIO32-C,Yes,Rule,,,Do not perform operations on devices that are only appropriate for files,,IO3,Medium, c,CERT-C,FIO34-C,Yes,Rule,,,Distinguish between characters read from a file and EOF or WEOF,,IO1,Hard, @@ -569,7 +572,7 @@ c,CERT-C,MSC38-C,Yes,Rule,,,Do not treat a predefined identifier as an object if c,CERT-C,MSC39-C,Yes,Rule,,,Do not call va_arg() on a va_list that has an indeterminate value,,Contracts7,Hard, c,CERT-C,MSC40-C,Yes,Rule,,,Do not violate constraints,,Contracts,Very Hard, c,CERT-C,MSC41-C,OutOfScope,Rule,,,Never hard code sensitive information,,,, -c,CERT-C,POS30-C,OutOfScope,Rule,,,Use the readlink() function properly,,,, +c,CERT-C,POS30-C,Yes,Rule,,,Use the readlink() function properly,,IO5,Hard, c,CERT-C,POS34-C,OutOfScope,Rule,,,Do not call putenv() with a pointer to an automatic variable as the argument,,,, c,CERT-C,POS35-C,OutOfScope,Rule,,,Avoid race conditions while checking for the existence of a symbolic link,,,, c,CERT-C,POS36-C,OutOfScope,Rule,,,Observe correct revocation order while relinquishing privileges,,,, From c25018fce4f419e5e770b8804fbd483b9705ccd3 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 31 Mar 2025 20:42:42 +0100 Subject: [PATCH 282/370] Re-add DeviationsSuppression.ql This is required for our reporting scripts. Changes implemented to support reporting of locations and messages for new deviation formats. --- .../deviations/CodeIdentifierDeviation.qll | 49 +++++++++++++++++-- .../cpp/deviations/DeviationsSuppression.ql | 25 ++++++---- .../DeviationsSuppression.expected | 2 +- 3 files changed, 60 insertions(+), 16 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll index 310a2b678b..4b2f03cf98 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll @@ -226,8 +226,8 @@ class DeviationAttribute extends StdAttribute { DeviationRecord getADeviationRecord() { result = record } - pragma[nomagic] - Element getASuppressedElement() { + /** Gets the element to which this attribute was applied. */ + Element getPrimarySuppressedElement() { result.(Type).getAnAttribute() = this or result.(Stmt).getAnAttribute() = this @@ -235,6 +235,11 @@ class DeviationAttribute extends StdAttribute { result.(Variable).getAnAttribute() = this or result.(Function).getAnAttribute() = this + } + + pragma[nomagic] + Element getASuppressedElement() { + result = this.getPrimarySuppressedElement() or result.(Expr).getEnclosingStmt() = this.getASuppressedElement() or @@ -336,26 +341,60 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation { ) } + predicate hasLocationInfo( + string filepath, int suppressedLine, int suppressedColumn, int endline, int endcolumn + ) { + exists(Comment commentMarker | + this = TSingleLineDeviation(_, commentMarker, filepath, suppressedLine) and + suppressedColumn = 1 and + endline = suppressedLine + | + if commentMarker instanceof DeviationEndOfLineMarker + then endcolumn = commentMarker.(DeviationEndOfLineMarker).getLocation().getEndColumn() + else + // Find the last column for a location on the next line + endcolumn = + max(Location l | + l.hasLocationInfo(filepath, _, _, _, _) and + l.getEndLine() = suppressedLine + | + l.getEndColumn() + ) + ) + or + this = TMultiLineDeviation(_, _, _, filepath, suppressedLine, endline) and + suppressedColumn = 1 and + endcolumn = 1 + or + exists(DeviationAttribute attribute | + this = TCodeIdentifierDeviation(_, attribute) and + attribute + .getPrimarySuppressedElement() + .getLocation() + .hasLocationInfo(filepath, suppressedLine, suppressedColumn, endline, endcolumn) + ) + } + string toString() { exists(string filepath | exists(int suppressedLine | this = TSingleLineDeviation(_, _, filepath, suppressedLine) and result = - "Deviation record " + getADeviationRecord() + " applied to " + filepath + " Line " + + "Deviation of " + getADeviationRecord().getQuery() + " applied to " + filepath + " Line " + suppressedLine ) or exists(int suppressedStartLine, int suppressedEndLine | this = TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine) and result = - "Deviation record " + getADeviationRecord() + " applied to " + filepath + " Line" + + "Deviation of " + getADeviationRecord().getQuery() + " applied to " + filepath + " Line " + suppressedStartLine + ":" + suppressedEndLine ) ) or exists(DeviationAttribute attribute | this = TCodeIdentifierDeviation(_, attribute) and - result = "Deviation record " + getADeviationRecord() + " applied to " + attribute + result = "Deviation of " + getADeviationRecord().getQuery() + " applied to " + attribute ) } } diff --git a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql index 9035b7d288..f29c068983 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql +++ b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql @@ -38,7 +38,9 @@ newtype TDeviationScope = file.getRelativePath().prefix(deviationPath.length()) = deviationPath ) } or - TDeviationRecordCommentScope(DeviationRecord dr, Comment c) { c = dr.getACodeIdentifierComment() } + TDeviationRecordCodeIdentiferDeviationScope(DeviationRecord dr, CodeIdentifierDeviation c) { + c = dr.getACodeIdentifierDeviation() + } /** A deviation scope. */ class DeviationScope extends TDeviationScope { @@ -91,10 +93,16 @@ class DeviationRecordFileScope extends DeviationScope, TDeviationRecordFileScope * A deviation scope derived from a comment corresponding to a "code-identifier" entry for a * `DeviationRecord`. */ -class DeviationRecordCommentScope extends DeviationScope, TDeviationRecordCommentScope { - private DeviationRecord getDeviationRecord() { this = TDeviationRecordCommentScope(result, _) } +class DeviationRecordCommentScope extends DeviationScope, + TDeviationRecordCodeIdentiferDeviationScope +{ + private DeviationRecord getDeviationRecord() { + this = TDeviationRecordCodeIdentiferDeviationScope(result, _) + } - private Comment getComment() { this = TDeviationRecordCommentScope(_, result) } + private CodeIdentifierDeviation getCodeIdentifierDeviation() { + this = TDeviationRecordCodeIdentiferDeviationScope(_, result) + } override Locatable getDeviationDefinitionLocation() { result = getDeviationRecord() } @@ -103,14 +111,11 @@ class DeviationRecordCommentScope extends DeviationScope, TDeviationRecordCommen override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - getComment().getLocation().hasLocationInfo(filepath, startline, _, endline, endcolumn) and - startcolumn = 1 + getCodeIdentifierDeviation() + .hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } - override string toString() { - result = - "Deviation of " + getDeviationRecord().getQuery() + " for comment " + getComment() + "." - } + override string toString() { result = getCodeIdentifierDeviation().toString() } } from DeviationScope deviationScope diff --git a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected index 50ceb35b9d..1d8a87d359 100644 --- a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected +++ b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected @@ -1,4 +1,4 @@ -| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:12:1:12:58 | Deviation of cpp/autosar/type-long-double-used for comment // a-0-4-2-deviation COMPLIANT[DEVIATED]. | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:12:1:12:58 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 12 | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/unused-return-value] | lgtm[cpp/autosar/unused-return-value] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/unused-return-value for nested/nested2/test2.h. | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | coding-standards.xml:1:1:17:19 | Deviation of cpp/autosar/useless-assignment for coding-standards.xml. | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | main.cpp:1:1:14:1 | Deviation of cpp/autosar/useless-assignment for main.cpp. | From ddd28e6dc4274c3c1ce1ee313ed3692c28ce7744 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 31 Mar 2025 20:47:06 +0100 Subject: [PATCH 283/370] Test new deviation formats for DeviationSuppressions.ql --- .../DeviationsSuppression.expected | 6 ++++- .../deviations_report_deviated/main.cpp | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected index 1d8a87d359..73f564c13c 100644 --- a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected +++ b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected @@ -1,7 +1,11 @@ | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:12:1:12:58 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 12 | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:14:1:14:65 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 14 | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:18:1:18:40 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 18 | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:21:1:27:1 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 21:27 | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:29:1:35:1 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 29:35 | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/unused-return-value] | lgtm[cpp/autosar/unused-return-value] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/unused-return-value for nested/nested2/test2.h. | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | coding-standards.xml:1:1:17:19 | Deviation of cpp/autosar/useless-assignment for coding-standards.xml. | -| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | main.cpp:1:1:14:1 | Deviation of cpp/autosar/useless-assignment for main.cpp. | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | main.cpp:1:1:39:1 | Deviation of cpp/autosar/useless-assignment for main.cpp. | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/coding-standards.xml:1:1:13:19 | Deviation of cpp/autosar/useless-assignment for nested/coding-standards.xml. | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/useless-assignment for nested/nested2/test2.h. | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/test.h:1:1:6:1 | Deviation of cpp/autosar/useless-assignment for nested/test.h. | diff --git a/cpp/common/test/deviations/deviations_report_deviated/main.cpp b/cpp/common/test/deviations/deviations_report_deviated/main.cpp index c59dea5609..7891faea18 100644 --- a/cpp/common/test/deviations/deviations_report_deviated/main.cpp +++ b/cpp/common/test/deviations/deviations_report_deviated/main.cpp @@ -10,5 +10,30 @@ int main(int argc, char **argv) { getX(); // NON_COMPLIANT long double d1; // NON_COMPLIANT (A0-4-2) long double d2; // a-0-4-2-deviation COMPLIANT[DEVIATED] + + long double d3; // codeql::autosar_deviation(a-0-4-2-deviation) + // COMPLIANT[DEVIATED] + long double d4; // NON_COMPLIANT (A0-4-2) + // codeql::autosar_deviation_next_line(a-0-4-2-deviation) + long double d5; // COMPLIANT[DEVIATED] + long double d6; // NON_COMPLIANT (A0-4-2) + + // codeql::autosar_deviation_begin(a-0-4-2-deviation) + long double d7; // COMPLIANT[DEVIATED] + getX(); // NON_COMPLIANT (A0-1-2) + long double d8; // COMPLIANT[DEVIATED] + getX(); // NON_COMPLIANT (A0-1-2) + long double d9; // COMPLIANT[DEVIATED] + // codeql::autosar_deviation_end(a-0-4-2-deviation) + long double d10; // NON_COMPLIANT (A0-4-2) + // codeql::autosar_deviation_begin(a-0-4-2-deviation) + long double d11; // COMPLIANT[DEVIATED] + getX(); // NON_COMPLIANT (A0-1-2) + long double d12; // COMPLIANT[DEVIATED] + getX(); // NON_COMPLIANT (A0-1-2) + long double d13; // COMPLIANT[DEVIATED] + // codeql::autosar_deviation_end(a-0-4-2-deviation) + long double d14; // NON_COMPLIANT (A0-4-2) + getX(); // NON_COMPLIANT (A0-1-2) return 0; } \ No newline at end of file From e7b53b27d540dac4213f6dfeef26f3a8174988ea Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 31 Mar 2025 20:39:32 -0700 Subject: [PATCH 284/370] Implement Rule-1-4's rule amendment from Amendment4 (also amended in Amdt3) --- amendments.csv | 2 +- .../EmergentLanguageFeaturesUsed.expected | 6 ------ c/misra/test/rules/RULE-1-4/test.c | 12 ++++++------ ...mics-threads-and-threadlocals-in-misra-c.md | 2 ++ .../src/codingstandards/cpp/Emergent.qll | 18 ------------------ 5 files changed, 9 insertions(+), 31 deletions(-) create mode 100644 change_notes/2025-03-31-allow-atomics-threads-and-threadlocals-in-misra-c.md diff --git a/amendments.csv b/amendments.csv index 1e774bc0c3..7bcc65327c 100644 --- a/amendments.csv +++ b/amendments.csv @@ -24,7 +24,7 @@ c,MISRA-C-2012,Amendment4,RULE-8-9,Yes,Clarification,Yes,Import c,MISRA-C-2012,Amendment4,RULE-9-4,Yes,Clarification,Yes,Import c,MISRA-C-2012,Amendment4,RULE-10-1,Yes,Clarification,Yes,Import c,MISRA-C-2012,Amendment4,RULE-18-3,Yes,Clarification,Yes,Import -c,MISRA-C-2012,Amendment4,RULE-1-4,Yes,Replace,No,Easy +c,MISRA-C-2012,Amendment4,RULE-1-4,Yes,Replace,Yes,Easy c,MISRA-C-2012,Amendment4,RULE-9-1,Yes,Refine,Yes,Easy c,MISRA-C-2012,Corrigendum2,DIR-4-10,Yes,Clarification,Yes,Import c,MISRA-C-2012,Corrigendum2,RULE-7-4,Yes,Refine,Yes,Easy diff --git a/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected b/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected index b0bbc467aa..3f63a6c26c 100644 --- a/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected +++ b/c/misra/test/rules/RULE-1-4/EmergentLanguageFeaturesUsed.expected @@ -1,7 +1 @@ -| test.c:2:1:2:22 | #include | Usage of emergent language feature. | -| test.c:4:1:4:20 | #include | Usage of emergent language feature. | | test.c:7:1:7:32 | #define __STDC_WANT_LIB_EXT1__ 1 | Usage of emergent language feature. | -| test.c:12:26:12:40 | atomic_new_type | Usage of emergent language feature. | -| test.c:17:15:17:15 | i | Usage of emergent language feature. | -| test.c:24:27:24:28 | i3 | Usage of emergent language feature. | -| test.c:25:28:25:29 | i4 | Usage of emergent language feature. | diff --git a/c/misra/test/rules/RULE-1-4/test.c b/c/misra/test/rules/RULE-1-4/test.c index 81d609f052..5bea219b54 100644 --- a/c/misra/test/rules/RULE-1-4/test.c +++ b/c/misra/test/rules/RULE-1-4/test.c @@ -1,15 +1,15 @@ #include //COMPLIANT -#include //NON_COMPLIANT +#include //COMPLIANT #include //COMPLIANT -#include //NON_COMPLIANT +#include //COMPLIANT -#define MACRO(x) _Generic((x), int : 0, long : 1) // NON_COMPLIANT +#define MACRO(x) _Generic((x), int : 0, long : 1) // COMPLIANT #define __STDC_WANT_LIB_EXT1__ 1 // NON_COMPLIANT _Noreturn void f0(); // COMPLIANT typedef int new_type; // COMPLIANT -typedef _Atomic new_type atomic_new_type; // NON_COMPLIANT +typedef _Atomic new_type atomic_new_type; // COMPLIANT void f(int p) { int i0 = _Generic(p, int : 0, long : 1); // COMPLIANT @@ -21,6 +21,6 @@ void f(int p) { int a = _Alignof(int); // COMPLIANT int a1 = alignof(int); // COMPLIANT - static thread_local int i3; // NON_COMPLIANT - static _Thread_local int i4; // NON_COMPLIANT + static thread_local int i3; // COMPLIANT + static _Thread_local int i4; // COMPLIANT } \ No newline at end of file diff --git a/change_notes/2025-03-31-allow-atomics-threads-and-threadlocals-in-misra-c.md b/change_notes/2025-03-31-allow-atomics-threads-and-threadlocals-in-misra-c.md new file mode 100644 index 0000000000..b59e04610f --- /dev/null +++ b/change_notes/2025-03-31-allow-atomics-threads-and-threadlocals-in-misra-c.md @@ -0,0 +1,2 @@ + - `RULE-1-4` - `EmergentLanguageFeaturesUsed.ql`: + - Allow usage of atomics, `thread.h`, and `_Thread_local` as per Misra C 2012 Amendment 4. \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/Emergent.qll b/cpp/common/src/codingstandards/cpp/Emergent.qll index 3b3fbbaebd..30f1df58e4 100644 --- a/cpp/common/src/codingstandards/cpp/Emergent.qll +++ b/cpp/common/src/codingstandards/cpp/Emergent.qll @@ -6,24 +6,6 @@ import cpp module C11 { abstract class EmergentLanguageFeature extends Element { } - class AtomicVariableSpecifier extends EmergentLanguageFeature, Variable { - AtomicVariableSpecifier() { - getType().(DerivedType).getBaseType*().getASpecifier().getName() = "atomic" - } - } - - class AtomicDeclaration extends EmergentLanguageFeature, Declaration { - AtomicDeclaration() { getASpecifier().getName() = "atomic" } - } - - class ThreadLocalDeclaration extends EmergentLanguageFeature, Declaration { - ThreadLocalDeclaration() { getASpecifier().getName() = "is_thread_local" } - } - - class EmergentHeader extends EmergentLanguageFeature, Include { - EmergentHeader() { getIncludedFile().getBaseName() = ["stdatomic.h", "threads.h"] } - } - class LibExt1Macro extends EmergentLanguageFeature, Macro { LibExt1Macro() { getName() = "__STDC_WANT_LIB_EXT1__" and From 24d743593ee429a50b81dd8f526f0d1ee603529a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 04:34:06 +0000 Subject: [PATCH 285/370] Bump actions/create-github-app-token from 1 to 2 Bumps [actions/create-github-app-token](https://github.com/actions/create-github-app-token) from 1 to 2. - [Release notes](https://github.com/actions/create-github-app-token/releases) - [Commits](https://github.com/actions/create-github-app-token/compare/v1...v2) --- updated-dependencies: - dependency-name: actions/create-github-app-token dependency-version: '2' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/dispatch-matrix-test-on-comment.yml | 2 +- .github/workflows/dispatch-release-performance-check.yml | 2 +- .github/workflows/finalize-release.yml | 2 +- .github/workflows/prepare-release.yml | 2 +- .github/workflows/update-release.yml | 2 +- .github/workflows/validate-release.yml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/dispatch-matrix-test-on-comment.yml b/.github/workflows/dispatch-matrix-test-on-comment.yml index 964fb7e9f3..972cabdb89 100644 --- a/.github/workflows/dispatch-matrix-test-on-comment.yml +++ b/.github/workflows/dispatch-matrix-test-on-comment.yml @@ -19,7 +19,7 @@ jobs: - name: Generate token id: generate-token - uses: actions/create-github-app-token@v1 + uses: actions/create-github-app-token@v2 with: app-id: ${{ vars.AUTOMATION_APP_ID }} private-key: ${{ secrets.AUTOMATION_PRIVATE_KEY }} diff --git a/.github/workflows/dispatch-release-performance-check.yml b/.github/workflows/dispatch-release-performance-check.yml index a8df297f7d..5886bb2ea8 100644 --- a/.github/workflows/dispatch-release-performance-check.yml +++ b/.github/workflows/dispatch-release-performance-check.yml @@ -19,7 +19,7 @@ jobs: - name: Generate token id: generate-token - uses: actions/create-github-app-token@v1 + uses: actions/create-github-app-token@v2 with: app-id: ${{ vars.AUTOMATION_APP_ID }} private-key: ${{ secrets.AUTOMATION_PRIVATE_KEY }} diff --git a/.github/workflows/finalize-release.yml b/.github/workflows/finalize-release.yml index a7ccc0375e..b3a96f32d3 100644 --- a/.github/workflows/finalize-release.yml +++ b/.github/workflows/finalize-release.yml @@ -103,7 +103,7 @@ jobs: - name: Generate token if: env.HOTFIX_RELEASE == 'false' id: generate-token - uses: actions/create-github-app-token@v1 + uses: actions/create-github-app-token@v2 with: app-id: ${{ vars.AUTOMATION_APP_ID }} private-key: ${{ secrets.AUTOMATION_PRIVATE_KEY }} diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 19dbe1adbd..75e297d42e 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -143,7 +143,7 @@ jobs: - name: Generate token id: generate-token - uses: actions/create-github-app-token@v1 + uses: actions/create-github-app-token@v2 with: app-id: ${{ vars.AUTOMATION_APP_ID }} private-key: ${{ secrets.AUTOMATION_PRIVATE_KEY }} diff --git a/.github/workflows/update-release.yml b/.github/workflows/update-release.yml index 4f779d0841..e3b8045514 100644 --- a/.github/workflows/update-release.yml +++ b/.github/workflows/update-release.yml @@ -43,7 +43,7 @@ jobs: - name: Generate token id: generate-token - uses: actions/create-github-app-token@v1 + uses: actions/create-github-app-token@v2 with: app-id: ${{ vars.AUTOMATION_APP_ID }} private-key: ${{ secrets.AUTOMATION_PRIVATE_KEY }} diff --git a/.github/workflows/validate-release.yml b/.github/workflows/validate-release.yml index 63aa9e90e3..cd7d27f6fa 100644 --- a/.github/workflows/validate-release.yml +++ b/.github/workflows/validate-release.yml @@ -40,7 +40,7 @@ jobs: steps: - name: Generate token id: generate-token - uses: actions/create-github-app-token@v1 + uses: actions/create-github-app-token@v2 with: app-id: ${{ vars.AUTOMATION_APP_ID }} private-key: ${{ secrets.AUTOMATION_PRIVATE_KEY }} @@ -108,7 +108,7 @@ jobs: steps: - name: Generate token id: generate-token - uses: actions/create-github-app-token@v1 + uses: actions/create-github-app-token@v2 with: app-id: ${{ vars.AUTOMATION_APP_ID }} private-key: ${{ secrets.AUTOMATION_PRIVATE_KEY }} From 4623f33542c09fbc1d2fa38833a2d0a337489602 Mon Sep 17 00:00:00 2001 From: Michael R Fairhurst Date: Tue, 8 Apr 2025 22:15:40 +0000 Subject: [PATCH 286/370] First pass at addressing cross-compiler compatibility in MISRA 2023. Handles clang findings and gcc findings. Many issues were merely updates to the test cases, however, additional work has been done to properly handle tgmath.h and stdatomic.h macros across gcc and clang results. --- c/common/src/codingstandards/c/TgMath.qll | 59 +++- .../functionnoreturnattributecondition/test.c | 2 +- .../rules/RULE-13-2/UnsequencedAtomicReads.ql | 50 ++- .../TgMathArgumentWithInvalidEssentialType.ql | 11 +- ...gMathArgumentsWithDifferingStandardType.ql | 6 +- .../RULE-21-25/InvalidMemoryOrderArgument.ql | 76 +--- .../RULE-9-7/UninitializedAtomicObject.ql | 6 +- c/misra/test/rules/DIR-5-1/test.c | 2 +- c/misra/test/rules/DIR-5-3/test.c | 2 +- ...eOfObsoleteMacroAtomicVarInit.expected.gcc | 1 + ...tomicQualifierAppliedToVoid.expected.clang | 0 c/misra/test/rules/RULE-11-10/test.c.clang | 28 ++ ...egateObjectDirectlyAccessed.expected.clang | 0 c/misra/test/rules/RULE-12-6/test.c | 6 +- c/misra/test/rules/RULE-12-6/test.c.clang | 89 +++++ .../RULE-13-2/UnsequencedAtomicReads.expected | 6 +- .../UnsequencedAtomicReads.expected.gcc | 5 + c/misra/test/rules/RULE-17-11/test.c | 2 +- c/misra/test/rules/RULE-18-10/test.c | 6 +- c/misra/test/rules/RULE-18-8/test.c | 2 +- ...ointerConversionOfTemporaryObject.expected | 6 +- ...eSubscriptedWithTemporaryLifetime.expected | 14 +- c/misra/test/rules/RULE-18-9/test.c | 5 +- ...hArgumentWithInvalidEssentialType.expected | 2 + ...entWithInvalidEssentialType.expected.clang | 76 ++++ ...umentWithInvalidEssentialType.expected.gcc | 79 +++++ c/misra/test/rules/RULE-21-22/test.c | 6 + c/misra/test/rules/RULE-21-22/test.c.clang | 329 ++++++++++++++++++ c/misra/test/rules/RULE-21-22/test.c.gcc | 329 ++++++++++++++++++ ...tsWithDifferingStandardType.expected.clang | 139 ++++++++ ...entsWithDifferingStandardType.expected.gcc | 139 ++++++++ .../InvalidMemoryOrderArgument.expected | 142 ++++---- .../InvalidMemoryOrderArgument.expected.gcc | 106 ++++++ c/misra/test/rules/RULE-21-25/test.c | 19 +- c/misra/test/rules/RULE-21-26/test.c | 2 +- c/misra/test/rules/RULE-22-16/test.c | 2 +- ...fObjectWithUnmatchedAlignment.expected.gcc | 20 +- c/misra/test/rules/RULE-9-7/test.c | 4 +- ...ss-compiler-compatibility-in-misra-2023.md | 12 + .../src/codingstandards/cpp/FloatingPoint.qll | 3 +- .../cpp/StdFunctionOrMacro.qll | 138 ++++++-- 41 files changed, 1698 insertions(+), 233 deletions(-) create mode 100644 c/misra/test/rules/RULE-1-5/UseOfObsoleteMacroAtomicVarInit.expected.gcc create mode 100644 c/misra/test/rules/RULE-11-10/AtomicQualifierAppliedToVoid.expected.clang create mode 100644 c/misra/test/rules/RULE-11-10/test.c.clang create mode 100644 c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.expected.clang create mode 100644 c/misra/test/rules/RULE-12-6/test.c.clang create mode 100644 c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected.gcc create mode 100644 c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected.clang create mode 100644 c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected.gcc create mode 100644 c/misra/test/rules/RULE-21-22/test.c.clang create mode 100644 c/misra/test/rules/RULE-21-22/test.c.gcc create mode 100644 c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected.clang create mode 100644 c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected.gcc create mode 100644 c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected.gcc create mode 100644 change_notes/2025-04-08-address-cross-compiler-compatibility-in-misra-2023.md diff --git a/c/common/src/codingstandards/c/TgMath.qll b/c/common/src/codingstandards/c/TgMath.qll index 36c47fb5a2..8d68cd2574 100644 --- a/c/common/src/codingstandards/c/TgMath.qll +++ b/c/common/src/codingstandards/c/TgMath.qll @@ -1,21 +1,38 @@ import cpp -private string getATgMathMacroName(boolean allowComplex) { +private string getATgMathMacroName(boolean allowComplex, int numberOfParameters) { allowComplex = true and + numberOfParameters = 1 and result = [ "acos", "acosh", "asin", "asinh", "atan", "atanh", "carg", "cimag", "conj", "cos", "cosh", - "cproj", "creal", "exp", "fabs", "log", "pow", "sin", "sinh", "sqrt", "tan", "tanh" + "cproj", "creal", "exp", "fabs", "log", "sin", "sinh", "sqrt", "tan", "tanh" + ] + or + allowComplex = true and + numberOfParameters = 2 and + result = "pow" + or + allowComplex = false and + numberOfParameters = 1 and + result = + [ + "cbrt", "ceil", "erf", "erfc", "exp2", "expm1", "floor", "ilogb", "lgamma", "llrint", + "llround", "log10", "log1p", "log2", "logb", "lrint", "lround", "nearbyint", "rint", "round", + "tgamma", "trunc", ] or allowComplex = false and + numberOfParameters = 2 and result = [ - "atan2", "cbrt", "ceil", "copysign", "erf", "erfc", "exp2", "expm1", "fdim", "floor", "fma", - "fmax", "fmin", "fmod", "frexp", "hypot", "ilogb", "ldexp", "lgamma", "llrint", "llround", - "log10", "log1p", "log2", "logb", "lrint", "lround", "nearbyint", "nextafter", "nexttoward", - "remainder", "remquo", "rint", "round", "scalbn", "scalbln", "tgamma", "trunc", + "atan2", "copysign", "fdim", "fmax", "fmin", "fmod", "frexp", "hypot", "ldexp", "nextafter", + "nexttoward", "remainder", "scalbn", "scalbln" ] + or + allowComplex = false and + numberOfParameters = 3 and + result = ["fma", "remquo"] } private predicate hasOutputArgument(string macroName, int index) { @@ -27,19 +44,41 @@ private predicate hasOutputArgument(string macroName, int index) { class TgMathInvocation extends MacroInvocation { Call call; boolean allowComplex; + int numberOfParameters; TgMathInvocation() { - this.getMacro().getName() = getATgMathMacroName(allowComplex) and + this.getMacro().getName() = getATgMathMacroName(allowComplex, numberOfParameters) and call = getBestCallInExpansion(this) } + /** Account for extra parameters added by gcc */ + private int getParameterOffset() { + // Gcc calls look something like: `__builtin_tgmath(cosf, cosd, cosl, arg)`, in this example + // there is a parameter offset of 3, so `getOperandArgument(0)` is equivalent to + // `call.getArgument(3)`. + result = call.getNumberOfArguments() - numberOfParameters + } + Expr getOperandArgument(int i) { - result = call.getArgument(i) and - not hasOutputArgument(call.getTarget().getName(), i) + i >= 0 and + result = call.getArgument(i + getParameterOffset()) and + //i in [0..numberOfParameters - 1] and + not hasOutputArgument(getMacro().getName(), i) + } + + /** Get all explicit conversions, except those added by clang in the macro body */ + Expr getExplicitlyConvertedOperandArgument(int i) { + exists(Expr explicitConv | + explicitConv = getOperandArgument(i).getExplicitlyConverted() and + // clang explicitly casts most arguments, but not some integer arguments such as in `scalbn`. + if call.getTarget().getName().matches("__tg_%") and explicitConv instanceof Conversion + then result = explicitConv.(Conversion).getExpr() + else result = explicitConv + ) } int getNumberOfOperandArguments() { - result = call.getNumberOfArguments() - count(int i | hasOutputArgument(getMacroName(), i)) + result = numberOfParameters - count(int i | hasOutputArgument(getMacroName(), i)) } Expr getAnOperandArgument() { result = getOperandArgument(_) } diff --git a/c/common/test/rules/functionnoreturnattributecondition/test.c b/c/common/test/rules/functionnoreturnattributecondition/test.c index 1b0ba759e1..c13654a8e0 100644 --- a/c/common/test/rules/functionnoreturnattributecondition/test.c +++ b/c/common/test/rules/functionnoreturnattributecondition/test.c @@ -77,7 +77,7 @@ _Noreturn void test_noreturn_f10(int i) { // COMPLIANT case 4: thrd_exit(0); break; - default: + default:; jmp_buf jb; longjmp(jb, 0); } diff --git a/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql b/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql index b5e17fc934..86756668a8 100644 --- a/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql +++ b/c/misra/src/rules/RULE-13-2/UnsequencedAtomicReads.ql @@ -17,6 +17,7 @@ import semmle.code.cpp.dataflow.TaintTracking import codingstandards.c.misra import codingstandards.c.Ordering import codingstandards.c.orderofevaluation.VariableAccessOrdering +import codingstandards.cpp.StdFunctionOrMacro class AtomicAccessInFullExpressionOrdering extends Ordering::Configuration { AtomicAccessInFullExpressionOrdering() { this = "AtomicAccessInFullExpressionOrdering" } @@ -24,8 +25,8 @@ class AtomicAccessInFullExpressionOrdering extends Ordering::Configuration { override predicate isCandidate(Expr e1, Expr e2) { exists(AtomicVariableAccess a, AtomicVariableAccess b, FullExpr e | a = e1 and b = e2 | a.getTarget() = b.getTarget() and - a.(ConstituentExpr).getFullExpr() = e and - b.(ConstituentExpr).getFullExpr() = e and + a.getARead().(ConstituentExpr).getFullExpr() = e and + b.getARead().(ConstituentExpr).getFullExpr() = e and not a = b ) } @@ -39,13 +40,32 @@ class AtomicAccessInFullExpressionOrdering extends Ordering::Configuration { class AtomicVariableAccess extends VariableAccess { AtomicVariableAccess() { getTarget().getType().hasSpecifier("atomic") } - /* Get the `atomic_()` call this VarAccess occurs in. */ - FunctionCall getAtomicFunctionCall() { - exists(AddressOfExpr addrParent, FunctionCall fc | - fc.getTarget().getName().matches("__c11_atomic%") and + /* Get the `atomic_load()` call this VarAccess occurs in. */ + Expr getAtomicFunctionRead() { + exists(AddressOfExpr addrParent, AtomicReadOrWriteCall fc | + fc.getName().matches("atomic_load%") and + // StdFunctionOrMacro arguments are not necessarily reliable, so we look for any AddressOfExpr + // that is an argument to a call to `atomic_load`. addrParent = fc.getArgument(0) and addrParent.getAnOperand() = this and - result = fc + result = fc.getExpr() + ) + } + + /* Get the `atomic_store()` call this VarAccess occurs in. */ + Expr getAtomicFunctionWrite(Expr storedValue) { + exists(AddressOfExpr addrParent, AtomicReadOrWriteCall fc | + addrParent = fc.getArgument(0) and + addrParent.getAnOperand() = this and + result = fc.getExpr() and + ( + fc.getName().matches(["%store%", "%exchange%", "%fetch_%"]) and + not fc.getName().matches("%compare%") and + storedValue = fc.getArgument(1) + or + fc.getName().matches(["%compare%"]) and + storedValue = fc.getArgument(2) + ) ) } @@ -53,7 +73,7 @@ class AtomicVariableAccess extends VariableAccess { * Gets an assigned expr, either in the form `x = ` or `atomic_store(&x, )`. */ Expr getAnAssignedExpr() { - result = getAtomicFunctionCall().getArgument(1) + exists(getAtomicFunctionWrite(result)) or exists(AssignExpr assign | assign.getLValue() = this and @@ -65,7 +85,7 @@ class AtomicVariableAccess extends VariableAccess { * Gets the expression holding this variable access, either in the form `x` or `atomic_read(&x)`. */ Expr getARead() { - result = getAtomicFunctionCall() + result = getAtomicFunctionRead() or result = this } @@ -73,11 +93,17 @@ class AtomicVariableAccess extends VariableAccess { from AtomicAccessInFullExpressionOrdering config, FullExpr e, Variable v, AtomicVariableAccess va1, - AtomicVariableAccess va2 + AtomicVariableAccess va2, Expr va1Read, Expr va2Read where not isExcluded(e, SideEffects3Package::unsequencedAtomicReadsQuery()) and - e = va1.(ConstituentExpr).getFullExpr() and - config.isUnsequenced(va1, va2) and + va1Read = va1.getARead() and + va2Read = va2.getARead() and + e = va1Read.(ConstituentExpr).getFullExpr() and + // Careful here. The `VariableAccess` in a pair of atomic function calls may not be unsequenced, + // for instance in gcc where atomic functions expand to StmtExprs, which have clear sequences. + // In this case, the result of `getARead()` for a pair of atomic function calls may be + // unsequenced even though the `VariableAccess`es within those calls are not. + config.isUnsequenced(va1Read, va2Read) and v = va1.getTarget() and v = va2.getTarget() and // Exclude cases where the variable is assigned a value tainted by the other variable access. diff --git a/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql b/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql index 2105567d04..3c918c10d3 100644 --- a/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql +++ b/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql @@ -34,14 +34,17 @@ string getAllowedTypesString(TgMathInvocation call) { else result = "essentially signed, unsigned, or real floating type" } -from TgMathInvocation call, Expr arg, int argIndex, Type type, EssentialTypeCategory category +from TgMathInvocation call, Expr convertedArg, Expr unconverted, int argIndex, Type type, EssentialTypeCategory category where not isExcluded(call, EssentialTypes2Package::tgMathArgumentWithInvalidEssentialTypeQuery()) and - arg = call.getOperandArgument(argIndex) and - type = getEssentialType(arg) and + // We must handle conversions specially, as clang inserts casts in the macro body we want to ignore. + convertedArg = call.getExplicitlyConvertedOperandArgument(argIndex) and + unconverted = convertedArg.getUnconverted() and + // Do not use `convertedArg.getEssentialType()`, as that is affected by clang's casts in the macro body. + type = getEssentialTypeBeforeConversions(convertedArg) and category = getEssentialTypeCategory(type) and not category = getAnAllowedEssentialTypeCategory(call) -select arg, +select unconverted, "Argument " + (argIndex + 1) + " provided to type-generic macro '" + call.getMacroName() + "' has " + category.toString().toLowerCase() + ", which is not " + getAllowedTypesString(call) + "." diff --git a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql index 81209c8565..1a19249982 100644 --- a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql +++ b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql @@ -59,14 +59,14 @@ Type canonicalize(Type type) { } Type getEffectiveStandardType(Expr e) { - result = canonicalize(getPromotedType(e.getExplicitlyConverted())) + result = canonicalize(getPromotedType(e)) } from TgMathInvocation call, Type firstType where not isExcluded(call, EssentialTypes2Package::tgMathArgumentsWithDifferingStandardTypeQuery()) and - firstType = getEffectiveStandardType(call.getAnOperandArgument()) and - not forall(Expr arg | arg = call.getAnOperandArgument() | + firstType = getEffectiveStandardType(call.getExplicitlyConvertedOperandArgument(0)) and + not forall(Expr arg | arg = call.getExplicitlyConvertedOperandArgument(_) | firstType = getEffectiveStandardType(arg) ) select call, diff --git a/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql b/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql index 92ec2694b3..a7b599316a 100644 --- a/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql +++ b/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql @@ -14,11 +14,23 @@ import cpp import codingstandards.c.misra +import codingstandards.cpp.StdFunctionOrMacro import semmle.code.cpp.dataflow.new.DataFlow +class MemoryOrderEnum extends Enum { + MemoryOrderEnum() { + this.hasGlobalOrStdName("memory_order") + or + exists(TypedefType t | + t.getName() = "memory_order" and + t.getBaseType() = this + ) + } +} + /* A member of the set of memory orders defined in the `memory_order` enum */ class MemoryOrder extends EnumConstant { - MemoryOrder() { getDeclaringEnum().getName() = "memory_order" } + MemoryOrder() { getDeclaringEnum() instanceof MemoryOrderEnum } int getIntValue() { result = getValue().toInt() } } @@ -49,59 +61,6 @@ class MemoryOrderConstantExpr extends Expr { string getMemoryOrderString() { result = ord.getName() } } -/** - * A `stdatomic.h` function which accepts a `memory_order` value as a parameter. - */ -class MemoryOrderedStdAtomicFunction extends Function { - int orderParamIdx; - - MemoryOrderedStdAtomicFunction() { - exists(int baseParamIdx, int baseParams, string prefix, string regex, string basename | - regex = "__(c11_)?atomic_([a-z_]+)" and - prefix = getName().regexpCapture(regex, 1) and - basename = "atomic_" + getName().regexpCapture(regex, 2) + ["", "_explicit"] and - ( - basename in ["atomic_thread_fence", "atomic_signal_fence"] and - baseParamIdx = 0 and - baseParams = 1 - or - basename in ["atomic_load", "atomic_flag_clear", "atomic_flag_test_and_set"] and - baseParamIdx = 1 and - baseParams = 2 - or - basename in [ - "atomic_store", "atomic_fetch_" + ["add", "sub", "or", "xor", "and"], "atomic_exchange" - ] and - baseParamIdx = 2 and - baseParams = 3 - or - basename in ["atomic_compare_exchange_" + ["strong", "weak"]] and - baseParamIdx = [3, 4] and - baseParams = 5 - ) and - ( - // GCC case, may have one or two inserted parameters, e.g.: - // __atomic_load(8, &repr->a, &desired, order) - // or - // __atomic_load_8(&repr->a, &desired, order) - prefix = "" and - exists(int extraParams | - extraParams = getNumberOfParameters() - baseParams and - extraParams >= 0 and - orderParamIdx = baseParamIdx + extraParams - ) - or - // Clang case, no inserted parameters: - // __c11_atomic_load(object, order) - prefix = "c11_" and - orderParamIdx = baseParamIdx - ) - ) - } - - int getOrderParameterIdx() { result = orderParamIdx } -} - module MemoryOrderFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node node) { // Direct usage of memory order constant @@ -118,9 +77,8 @@ module MemoryOrderFlowConfig implements DataFlow::ConfigSig { } predicate isSink(DataFlow::Node node) { - exists(FunctionCall fc | - node.asExpr() = - fc.getArgument(fc.getTarget().(MemoryOrderedStdAtomicFunction).getOrderParameterIdx()) + exists(AtomicallySequencedCall call | + call.getAMemoryOrderArgument() = node.asExpr() ) } } @@ -140,7 +98,7 @@ string describeMemoryOrderNode(DataFlow::Node node) { } from - Expr argument, Function function, string value, MemoryOrderFlow::PathNode source, + Expr argument, AtomicallySequencedCall function, string value, MemoryOrderFlow::PathNode source, MemoryOrderFlow::PathNode sink where not isExcluded(argument, Concurrency6Package::invalidMemoryOrderArgumentQuery()) and @@ -149,6 +107,6 @@ where value = describeMemoryOrderNode(source.getNode()) and // Double check that we didn't find flow from something equivalent to the allowed value. not value = any(AllowedMemoryOrder e).getName() and - function.getACallToThisFunction().getAnArgument() = argument + function.getAMemoryOrderArgument() = argument select argument, source, sink, "Invalid memory order '$@' in call to function '$@'.", value, value, function, function.getName() diff --git a/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql b/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql index dfb096189f..5f7fb803d6 100644 --- a/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql +++ b/c/misra/src/rules/RULE-9-7/UninitializedAtomicObject.ql @@ -31,7 +31,11 @@ class ThreadSpawningFunction extends Function { } class AtomicInitAddressOfExpr extends AddressOfExpr { - AtomicInitAddressOfExpr() { exists(AtomicInitCall c | this = c.getArgument(0)) } + AtomicInitAddressOfExpr() { + // StdFunctionOrMacro arguments are not necessarily reliable, so we look for any AddressOfExpr + // that is an argument to a call to `atomic_init`. + exists(AtomicInitCall c | this = c.getAnArgument()) + } } ControlFlowNode getARequiredInitializationPoint(LocalScopeVariable v) { diff --git a/c/misra/test/rules/DIR-5-1/test.c b/c/misra/test/rules/DIR-5-1/test.c index 5e568cc95c..5f392105e6 100644 --- a/c/misra/test/rules/DIR-5-1/test.c +++ b/c/misra/test/rules/DIR-5-1/test.c @@ -99,7 +99,7 @@ void many_thread13_calls_nonreentrant_funcs(void *p) { wcsrtombs(NULL, NULL, 0, NULL); // NON-COMPLIANT } -void main() { +int main(int argc, char *argv[]) { thrd_t single_thread1; thrd_t many_thread2; thrd_t single_thread3; diff --git a/c/misra/test/rules/DIR-5-3/test.c b/c/misra/test/rules/DIR-5-3/test.c index ebdf53cfb4..16eb580276 100644 --- a/c/misra/test/rules/DIR-5-3/test.c +++ b/c/misra/test/rules/DIR-5-3/test.c @@ -14,7 +14,7 @@ void func_called_from_main(void); void make_threads_called_from_func_called_from_main(void); void make_threads_called_from_main_pthread_thrd(void); -void main() { +int main(int argc, char *argv[]) { thrd_create(&g1, &thrd_func, NULL); // COMPLIANT pthread_create(&g2, NULL, &pthread_func, NULL); // COMPLIANT diff --git a/c/misra/test/rules/RULE-1-5/UseOfObsoleteMacroAtomicVarInit.expected.gcc b/c/misra/test/rules/RULE-1-5/UseOfObsoleteMacroAtomicVarInit.expected.gcc new file mode 100644 index 0000000000..cb8e72ff0f --- /dev/null +++ b/c/misra/test/rules/RULE-1-5/UseOfObsoleteMacroAtomicVarInit.expected.gcc @@ -0,0 +1 @@ +| test.c:29:18:29:36 | ATOMIC_VAR_INIT(VALUE) | Usage of macro ATOMIC_VAR_INIT() is declared obscelescent in C18, and discouraged in earlier C versions. | diff --git a/c/misra/test/rules/RULE-11-10/AtomicQualifierAppliedToVoid.expected.clang b/c/misra/test/rules/RULE-11-10/AtomicQualifierAppliedToVoid.expected.clang new file mode 100644 index 0000000000..e69de29bb2 diff --git a/c/misra/test/rules/RULE-11-10/test.c.clang b/c/misra/test/rules/RULE-11-10/test.c.clang new file mode 100644 index 0000000000..c30368a48d --- /dev/null +++ b/c/misra/test/rules/RULE-11-10/test.c.clang @@ -0,0 +1,28 @@ +// _Atomic void g1; // doesn't compile +_Atomic int g2; // COMPLIANT +// _Atomic void *g3; // NON_COMPLIANT +// _Atomic void g4[]; // doesn't compile +void *_Atomic g5; // COMPLIANT + +struct { + _Atomic int m1; // COMPLIANT + // _Atomic void m2; // doesn't compile + // _Atomic void *m3; // NON_COMPLIANT + void *_Atomic m4; // COMPLIANT +} s1; + +void f(_Atomic int p1 // COMPLIANT + // _Atomic void *p2 // NON_COMPLIANT + // _Atomic void p3[] // doesn't compile, even though it perhaps should as + // it is adjusted to void*. +) {} + +// typedef _Atomic void *f2(void); // NON_COMPLIANT +// typedef _Atomic void *(*f3)(void); // NON_COMPLIANT +// typedef void f4(_Atomic void *); // NON_COMPLIANT +// typedef void (*f5)(_Atomic void *); // NON_COMPLIANT + +void f6() { + (void *)0; // COMPLIANT + // (_Atomic void *)0; // NON_COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.expected.clang b/c/misra/test/rules/RULE-12-6/AtomicAggregateObjectDirectlyAccessed.expected.clang new file mode 100644 index 0000000000..e69de29bb2 diff --git a/c/misra/test/rules/RULE-12-6/test.c b/c/misra/test/rules/RULE-12-6/test.c index 0281e6b0d8..74d9de2fca 100644 --- a/c/misra/test/rules/RULE-12-6/test.c +++ b/c/misra/test/rules/RULE-12-6/test.c @@ -28,8 +28,8 @@ void f1() { atomic_store(&s1_atomic_ptr, l2); // COMPLIANT // Undefined behavior, but not banned by this rule. - memset(&atomic_s1, sizeof(atomic_s1), 0); // COMPLIANT - memset(ptr_atomic_s1, sizeof(*ptr_atomic_s1), 0); // COMPLIANT + memset(&atomic_s1, 0, sizeof(atomic_s1)); // COMPLIANT + memset(ptr_atomic_s1, 0, sizeof(*ptr_atomic_s1)); // COMPLIANT // OK: whole loads and stores are protected from data-races. takeCopy(atomic_s1); // COMPLIANT @@ -53,7 +53,7 @@ void f1() { // All OK: not an atomic struct, but rather an atomic pointer to non-atomic // struct. - memset(s1_atomic_ptr, sizeof(*s1_atomic_ptr), 0); // COMPLIANT + memset(s1_atomic_ptr, 0, sizeof(*s1_atomic_ptr)); // COMPLIANT takeCopy(*s1_atomic_ptr); // COMPLIANT *s1_atomic_ptr = (s1){0}; // COMPLIANT s1_atomic_ptr = l2; // COMPLIANT diff --git a/c/misra/test/rules/RULE-12-6/test.c.clang b/c/misra/test/rules/RULE-12-6/test.c.clang new file mode 100644 index 0000000000..83ad24cdb5 --- /dev/null +++ b/c/misra/test/rules/RULE-12-6/test.c.clang @@ -0,0 +1,89 @@ +#include "stdatomic.h" +#include "string.h" + +typedef struct s1 { + int x; +} s1; + +_Atomic s1 atomic_s1; +// A non-atomic pointer to an atomic s1 +_Atomic s1 *ptr_atomic_s1; +// An atomic pointer to a non-atomic s1 +s1 *_Atomic s1_atomic_ptr; + +_Atomic int g3; + +void takeCopy(s1 p1); + +void f1() { + s1 l1; + s1 *l2; + l1 = atomic_load(&atomic_s1); // COMPLIANT + l1 = atomic_load(ptr_atomic_s1); // COMPLIANT + l2 = atomic_load(&s1_atomic_ptr); // COMPLIANT + l1.x = 4; // COMPLIANT + l2->x = 4; // COMPLIANT + atomic_store(&atomic_s1, l1); // COMPLIANT + atomic_store(ptr_atomic_s1, l1); // COMPLIANT + atomic_store(&s1_atomic_ptr, l2); // COMPLIANT + + // Undefined behavior, but not banned by this rule. + memset(&atomic_s1, 0, sizeof(atomic_s1)); // COMPLIANT + memset(ptr_atomic_s1, 0, sizeof(*ptr_atomic_s1)); // COMPLIANT + + // OK: whole loads and stores are protected from data-races. + takeCopy(atomic_s1); // COMPLIANT + takeCopy(*ptr_atomic_s1); // COMPLIANT + atomic_s1 = (s1){0}; // COMPLIANT + *ptr_atomic_s1 = (s1){0}; // COMPLIANT + atomic_s1 = *l2; // COMPLIANT + ptr_atomic_s1 = l2; // COMPLIANT + + // Banned: circumvents data-race protection, results in UB. + // atomic_s1.x; // NON-COMPLIANT + // ptr_atomic_s1->x; // NON-COMPLIANT + // atomic_s1.x = 0; // NON-COMPLIANT + // ptr_atomic_s1->x = 0; // NON-COMPLIANT + + // OK: not evaluated. + sizeof(atomic_s1); // COMPLIANT + sizeof(ptr_atomic_s1); // COMPLIANT + // sizeof(atomic_s1.x); // COMPLIANT + // sizeof(ptr_atomic_s1->x); // COMPLIANT + + // All OK: not an atomic struct, but rather an atomic pointer to non-atomic + // struct. + memset(s1_atomic_ptr, 0, sizeof(*s1_atomic_ptr)); // COMPLIANT + takeCopy(*s1_atomic_ptr); // COMPLIANT + *s1_atomic_ptr = (s1){0}; // COMPLIANT + s1_atomic_ptr = l2; // COMPLIANT + s1_atomic_ptr->x; // COMPLIANT + + // Atomic specifier hidden behind a typedef, still atomic: + typedef _Atomic s1 atomic_s1; + atomic_s1 l3; + // l3.x; // NON_COMPLIANT + + // Worst case scenario: a typedef of a volatile const pointer to an atomic + // typedef type. + typedef atomic_s1 *volatile const atomic_s1_specified_ptr; + atomic_s1_specified_ptr l4; + // (l4)->x; // NON_COMPLIANT +} + +#define NOOP(x) (x) +#define DOT_FIELD_ACCESS_X(v) (v).x +#define POINTER_FIELD_ACCESS_X(v) (v)->x +#define GET_X_ATOMIC_S1() atomic_s1.x +#define GET_X_PTR_ATOMIC_S1() atomic_s1.x + +void f2() { + // Banned UB with user macros: + // NOOP(atomic_s1.x); // NON-COMPLIANT + // DOT_FIELD_ACCESS_X(atomic_s1); // NON-COMPLIANT + // POINTER_FIELD_ACCESS_X(ptr_atomic_s1); // NON-COMPLIANT + // GET_X_ATOMIC_S1(); // NON-COMPLIANT + // GET_X_PTR_ATOMIC_S1(); // NON-COMPLIANT + // GET_X_ATOMIC_S1() = 0; // NON-COMPLIANT + // GET_X_PTR_ATOMIC_S1() = 0; // NON-COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected b/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected index 897dd68f30..4fa06eb069 100644 --- a/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected +++ b/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected @@ -1,5 +1,5 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:86,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:86,67-75) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:86,5-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:112,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:112,67-75) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:112,5-18) | test.c:44:12:44:18 | ... + ... | Atomic variable $@ has a $@ that is unsequenced with $@. | test.c:42:15:42:16 | a1 | a1 | test.c:44:12:44:13 | a1 | previous read | test.c:44:17:44:18 | a1 | another read | | test.c:46:3:46:37 | ... + ... | Atomic variable $@ has a $@ that is unsequenced with $@. | test.c:42:15:42:16 | a1 | a1 | test.c:46:16:46:17 | a1 | previous read | test.c:46:35:46:36 | a1 | another read | diff --git a/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected.gcc b/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected.gcc new file mode 100644 index 0000000000..ccfb4e6a7b --- /dev/null +++ b/c/misra/test/rules/RULE-13-2/UnsequencedAtomicReads.expected.gcc @@ -0,0 +1,5 @@ +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:112,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:112,67-75) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (UnsequencedAtomicReads.ql:112,5-18) +| test.c:44:12:44:18 | ... + ... | Atomic variable $@ has a $@ that is unsequenced with $@. | test.c:42:15:42:16 | a1 | a1 | test.c:44:12:44:13 | a1 | previous read | test.c:44:17:44:18 | a1 | another read | +| test.c:46:15:46:17 | & ... | Atomic variable $@ has a $@ that is unsequenced with $@. | test.c:42:15:42:16 | a1 | a1 | test.c:46:16:46:17 | a1 | previous read | test.c:46:35:46:36 | a1 | another read | diff --git a/c/misra/test/rules/RULE-17-11/test.c b/c/misra/test/rules/RULE-17-11/test.c index 7baaea5821..73227accb9 100644 --- a/c/misra/test/rules/RULE-17-11/test.c +++ b/c/misra/test/rules/RULE-17-11/test.c @@ -86,7 +86,7 @@ __attribute__((noreturn)) void test_noreturn_f13(int i) { // COMPLIANT // Allowed by exception. It is undefined behavior for main() to be declared with // noreturn. -int main(char **argv, int argc) { // COMPLIANT +int main(int argc, char *argv[]) { // COMPLIANT abort(); } diff --git a/c/misra/test/rules/RULE-18-10/test.c b/c/misra/test/rules/RULE-18-10/test.c index 645943733d..b5906a3039 100644 --- a/c/misra/test/rules/RULE-18-10/test.c +++ b/c/misra/test/rules/RULE-18-10/test.c @@ -58,9 +58,9 @@ void f1( // Unknown array length types: int p21[], // COMPLIANT - int p22[][], // COMPLIANT + int p22[][2], // COMPLIANT int (*p23)[], // COMPLIANT - int (*p24)[2][], // COMPLIANT + // int (*p24)[2][], // doesn't compile int (*p25)[][2], // COMPLIANT // VLA types that are rewritten as pointers: @@ -73,7 +73,7 @@ void f1( int(*l2)[3]; // COMPLIANT int(*l3)[p0]; // NON-COMPLIANT - int l6[10] = p23; + int l6[10]; // A pointer to a VMT may be declared `static`. static int(*l4)[p0]; // NON-COMPLIANT diff --git a/c/misra/test/rules/RULE-18-8/test.c b/c/misra/test/rules/RULE-18-8/test.c index e6e038049c..7d6a1400d6 100644 --- a/c/misra/test/rules/RULE-18-8/test.c +++ b/c/misra/test/rules/RULE-18-8/test.c @@ -29,7 +29,7 @@ void f1(int n, // Pointers to variably-modified types are not VLAs. int p2[n][n], int p3[], // array of unknown length is converted to pointer - int p4[][] // array of unknown length are not VLAs. + int p4[][n] // array of unknown length are not VLAs. ) {} struct s { diff --git a/c/misra/test/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.expected b/c/misra/test/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.expected index 34bec03490..cf741ed16c 100644 --- a/c/misra/test/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.expected +++ b/c/misra/test/rules/RULE-18-9/ArrayToPointerConversionOfTemporaryObject.expected @@ -25,6 +25,6 @@ | test.c:90:3:90:36 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:90:3:90:8 | call to get_s2 | call to get_s2 | | test.c:91:15:91:42 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:91:15:91:20 | call to get_s2 | call to get_s2 | | test.c:92:15:92:48 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:92:15:92:20 | call to get_s2 | call to get_s2 | -| test.c:111:15:111:33 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:111:16:111:22 | ... = ... | ... = ... | -| test.c:113:15:113:37 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:113:16:113:26 | ... ? ... : ... | ... ? ... : ... | -| test.c:114:15:114:31 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:114:16:114:20 | ... , ... | ... , ... | +| test.c:114:15:114:27 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:112:9:112:11 | arr | arr | test.c:114:16:114:22 | ... = ... | ... = ... | +| test.c:116:15:116:37 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:116:16:116:26 | ... ? ... : ... | ... ? ... : ... | +| test.c:117:15:117:31 | array to pointer conversion | Array to pointer conversion of array $@ from temporary object $@. | test.c:3:13:3:21 | const_arr | const_arr | test.c:117:16:117:20 | ... , ... | ... , ... | diff --git a/c/misra/test/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.expected b/c/misra/test/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.expected index 19604e2092..4c961ee994 100644 --- a/c/misra/test/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.expected +++ b/c/misra/test/rules/RULE-18-9/ModifiableLValueSubscriptedWithTemporaryLifetime.expected @@ -5,11 +5,11 @@ | test.c:84:5:84:19 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:84:14:84:16 | arr | arr | test.c:84:5:84:10 | call to get_s1 | call to get_s1 | | test.c:93:3:93:27 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:93:22:93:24 | arr | arr | test.c:93:3:93:8 | call to get_s2 | call to get_s2 | | test.c:94:3:94:27 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:94:22:94:24 | arr | arr | test.c:94:3:94:8 | call to get_s2 | call to get_s2 | -| test.c:137:3:137:23 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:137:12:137:20 | arr_union | arr_union | test.c:137:3:137:8 | call to get_s3 | call to get_s3 | -| test.c:138:3:138:24 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:138:12:138:21 | arr_struct | arr_struct | test.c:138:3:138:8 | call to get_s3 | call to get_s3 | -| test.c:139:3:139:24 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:139:12:139:21 | arr_struct | arr_struct | test.c:139:3:139:8 | call to get_s3 | call to get_s3 | -| test.c:140:3:140:24 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:140:12:140:21 | arr_struct | arr_struct | test.c:140:3:140:8 | call to get_s3 | call to get_s3 | +| test.c:140:3:140:23 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:140:12:140:20 | arr_union | arr_union | test.c:140:3:140:8 | call to get_s3 | call to get_s3 | | test.c:141:3:141:24 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:141:12:141:21 | arr_struct | arr_struct | test.c:141:3:141:8 | call to get_s3 | call to get_s3 | -| test.c:142:4:142:25 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:142:13:142:22 | arr_struct | arr_struct | test.c:142:4:142:9 | call to get_s3 | call to get_s3 | -| test.c:146:3:146:19 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:146:12:146:16 | arr2d | arr2d | test.c:146:3:146:8 | call to get_s3 | call to get_s3 | -| test.c:147:4:147:20 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:147:13:147:17 | arr2d | arr2d | test.c:147:4:147:9 | call to get_s3 | call to get_s3 | +| test.c:142:3:142:24 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:142:12:142:21 | arr_struct | arr_struct | test.c:142:3:142:8 | call to get_s3 | call to get_s3 | +| test.c:143:3:143:24 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:143:12:143:21 | arr_struct | arr_struct | test.c:143:3:143:8 | call to get_s3 | call to get_s3 | +| test.c:144:3:144:24 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:144:12:144:21 | arr_struct | arr_struct | test.c:144:3:144:8 | call to get_s3 | call to get_s3 | +| test.c:145:4:145:25 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:145:13:145:22 | arr_struct | arr_struct | test.c:145:4:145:9 | call to get_s3 | call to get_s3 | +| test.c:149:3:149:19 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:149:12:149:16 | arr2d | arr2d | test.c:149:3:149:8 | call to get_s3 | call to get_s3 | +| test.c:150:4:150:20 | access to array | Modifiable lvalue produced by subscripting array member $@ of temporary lifetime object $@ | test.c:150:13:150:17 | arr2d | arr2d | test.c:150:4:150:9 | call to get_s3 | call to get_s3 | diff --git a/c/misra/test/rules/RULE-18-9/test.c b/c/misra/test/rules/RULE-18-9/test.c index f2fb44fdc9..d5eb5ec35e 100644 --- a/c/misra/test/rules/RULE-18-9/test.c +++ b/c/misra/test/rules/RULE-18-9/test.c @@ -108,7 +108,10 @@ void f(void) { get_s2_ptr()->member_s1.arr[0] = 1; // COMPLIANT // Other types of non-lvalue types - use_int_ptr((l1 = l1).const_arr); // NON-COMPLIANT + struct { + int arr[10]; + } l3; + use_int_ptr((l3 = l3).arr); // NON-COMPLIANT use_int_ptr(((struct s1)l1).const_arr); // NON-COMPLIANT[FALSE_NEGATIVE] use_int_ptr((1 ? l1 : l1).const_arr); // NON-COMPLIANT use_int_ptr((0, l1).const_arr); // NON-COMPLIANT diff --git a/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected index 7c30f68204..46e4e8f5c8 100644 --- a/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected +++ b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected @@ -130,3 +130,5 @@ | test.c:303:14:303:15 | cf | Argument 2 provided to type-generic macro 'scalbln' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | | test.c:309:10:309:11 | cf | Argument 1 provided to type-generic macro 'tgamma' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | | test.c:310:9:310:10 | cf | Argument 1 provided to type-generic macro 'trunc' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:325:14:325:14 | i | Argument 1 provided to type-generic macro 'cos' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:328:20:328:20 | c | Argument 1 provided to type-generic macro 'cos' has essentially character type, which is not essentially signed, unsigned, or floating type. | diff --git a/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected.clang b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected.clang new file mode 100644 index 0000000000..313438ea6c --- /dev/null +++ b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected.clang @@ -0,0 +1,76 @@ +| test.c:29:7:29:7 | c | Argument 1 provided to type-generic macro 'cos' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:40:7:40:7 | e | Argument 1 provided to type-generic macro 'cos' has essentially enum type, which is not essentially signed, unsigned, or floating type. | +| test.c:41:7:41:7 | b | Argument 1 provided to type-generic macro 'cos' has essentially boolean type, which is not essentially signed, unsigned, or floating type. | +| test.c:156:8:156:8 | c | Argument 1 provided to type-generic macro 'acos' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:157:9:157:9 | c | Argument 1 provided to type-generic macro 'acosh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:158:8:158:8 | c | Argument 1 provided to type-generic macro 'asin' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:159:9:159:9 | c | Argument 1 provided to type-generic macro 'asinh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:160:9:160:9 | c | Argument 1 provided to type-generic macro 'atan2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:161:12:161:12 | c | Argument 2 provided to type-generic macro 'atan2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:162:9:162:9 | c | Argument 1 provided to type-generic macro 'atanh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:163:8:163:8 | c | Argument 1 provided to type-generic macro 'carg' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:164:8:164:8 | c | Argument 1 provided to type-generic macro 'ceil' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:165:9:165:9 | c | Argument 1 provided to type-generic macro 'cimag' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:166:8:166:8 | c | Argument 1 provided to type-generic macro 'conj' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:167:15:167:15 | c | Argument 2 provided to type-generic macro 'copysign' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:168:12:168:12 | c | Argument 1 provided to type-generic macro 'copysign' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:169:8:169:8 | c | Argument 1 provided to type-generic macro 'cosh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:170:9:170:9 | c | Argument 1 provided to type-generic macro 'cproj' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:171:9:171:9 | c | Argument 1 provided to type-generic macro 'creal' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:172:7:172:7 | c | Argument 1 provided to type-generic macro 'erf' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:173:8:173:8 | c | Argument 1 provided to type-generic macro 'erfc' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:174:7:174:7 | c | Argument 1 provided to type-generic macro 'exp' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:175:8:175:8 | c | Argument 1 provided to type-generic macro 'exp2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:176:9:176:9 | c | Argument 1 provided to type-generic macro 'expm1' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:177:8:177:8 | c | Argument 1 provided to type-generic macro 'fabs' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:178:8:178:8 | c | Argument 1 provided to type-generic macro 'fdim' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:179:11:179:11 | c | Argument 2 provided to type-generic macro 'fdim' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:180:9:180:9 | c | Argument 1 provided to type-generic macro 'floor' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:181:7:181:7 | c | Argument 1 provided to type-generic macro 'fma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:182:10:182:10 | c | Argument 2 provided to type-generic macro 'fma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:183:13:183:13 | c | Argument 3 provided to type-generic macro 'fma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:184:8:184:8 | c | Argument 1 provided to type-generic macro 'fmax' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:185:11:185:11 | c | Argument 2 provided to type-generic macro 'fmax' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:186:8:186:8 | c | Argument 1 provided to type-generic macro 'fmin' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:187:11:187:11 | c | Argument 2 provided to type-generic macro 'fmin' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:188:8:188:8 | c | Argument 1 provided to type-generic macro 'fmod' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:189:11:189:11 | c | Argument 2 provided to type-generic macro 'fmod' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:191:9:191:9 | c | Argument 1 provided to type-generic macro 'hypot' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:192:12:192:12 | c | Argument 2 provided to type-generic macro 'hypot' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:193:9:193:9 | c | Argument 1 provided to type-generic macro 'ilogb' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:194:9:194:9 | c | Argument 1 provided to type-generic macro 'ldexp' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:195:12:195:12 | c | Argument 2 provided to type-generic macro 'ldexp' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:196:10:196:10 | c | Argument 1 provided to type-generic macro 'lgamma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:197:10:197:10 | c | Argument 1 provided to type-generic macro 'llrint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:198:11:198:11 | c | Argument 1 provided to type-generic macro 'llround' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:199:7:199:7 | c | Argument 1 provided to type-generic macro 'log' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:200:9:200:9 | c | Argument 1 provided to type-generic macro 'log10' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:201:9:201:9 | c | Argument 1 provided to type-generic macro 'log1p' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:202:8:202:8 | c | Argument 1 provided to type-generic macro 'log2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:203:8:203:8 | c | Argument 1 provided to type-generic macro 'logb' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:204:9:204:9 | c | Argument 1 provided to type-generic macro 'lrint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:205:10:205:10 | c | Argument 1 provided to type-generic macro 'lround' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:206:13:206:13 | c | Argument 1 provided to type-generic macro 'nearbyint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:207:13:207:13 | c | Argument 1 provided to type-generic macro 'nextafter' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:208:16:208:16 | c | Argument 2 provided to type-generic macro 'nextafter' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:209:14:209:14 | c | Argument 1 provided to type-generic macro 'nexttoward' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:210:17:210:17 | c | Argument 2 provided to type-generic macro 'nexttoward' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:211:7:211:7 | c | Argument 1 provided to type-generic macro 'pow' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:212:10:212:10 | c | Argument 2 provided to type-generic macro 'pow' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:213:13:213:13 | c | Argument 1 provided to type-generic macro 'remainder' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:214:16:214:16 | c | Argument 2 provided to type-generic macro 'remainder' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:217:8:217:8 | c | Argument 1 provided to type-generic macro 'rint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:218:9:218:9 | c | Argument 1 provided to type-generic macro 'round' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:219:10:219:10 | c | Argument 1 provided to type-generic macro 'scalbn' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:220:13:220:13 | c | Argument 2 provided to type-generic macro 'scalbn' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:221:11:221:11 | c | Argument 1 provided to type-generic macro 'scalbln' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:222:14:222:14 | c | Argument 2 provided to type-generic macro 'scalbln' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:223:7:223:7 | c | Argument 1 provided to type-generic macro 'sin' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:224:8:224:8 | c | Argument 1 provided to type-generic macro 'sinh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:225:8:225:8 | c | Argument 1 provided to type-generic macro 'sqrt' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:226:7:226:7 | c | Argument 1 provided to type-generic macro 'tan' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:227:8:227:8 | c | Argument 1 provided to type-generic macro 'tanh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:228:10:228:10 | c | Argument 1 provided to type-generic macro 'tgamma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:229:9:229:9 | c | Argument 1 provided to type-generic macro 'trunc' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:325:14:325:14 | i | Argument 1 provided to type-generic macro 'cos' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:328:20:328:20 | c | Argument 1 provided to type-generic macro 'cos' has essentially character type, which is not essentially signed, unsigned, or floating type. | diff --git a/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected.gcc b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected.gcc new file mode 100644 index 0000000000..79b070ae84 --- /dev/null +++ b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected.gcc @@ -0,0 +1,79 @@ +| test.c:29:7:29:7 | c | Argument 1 provided to type-generic macro 'cos' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:40:7:40:7 | e | Argument 1 provided to type-generic macro 'cos' has essentially enum type, which is not essentially signed, unsigned, or floating type. | +| test.c:41:7:41:7 | b | Argument 1 provided to type-generic macro 'cos' has essentially boolean type, which is not essentially signed, unsigned, or floating type. | +| test.c:156:8:156:8 | c | Argument 1 provided to type-generic macro 'acos' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:157:9:157:9 | c | Argument 1 provided to type-generic macro 'acosh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:158:8:158:8 | c | Argument 1 provided to type-generic macro 'asin' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:159:9:159:9 | c | Argument 1 provided to type-generic macro 'asinh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:160:9:160:9 | c | Argument 1 provided to type-generic macro 'atan2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:161:12:161:12 | c | Argument 2 provided to type-generic macro 'atan2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:162:9:162:9 | c | Argument 1 provided to type-generic macro 'atanh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:163:8:163:8 | c | Argument 1 provided to type-generic macro 'carg' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:164:8:164:8 | c | Argument 1 provided to type-generic macro 'ceil' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:165:9:165:9 | c | Argument 1 provided to type-generic macro 'cimag' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:166:8:166:8 | c | Argument 1 provided to type-generic macro 'conj' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:167:15:167:15 | c | Argument 2 provided to type-generic macro 'copysign' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:168:12:168:12 | c | Argument 1 provided to type-generic macro 'copysign' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:169:8:169:8 | c | Argument 1 provided to type-generic macro 'cosh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:170:9:170:9 | c | Argument 1 provided to type-generic macro 'cproj' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:171:9:171:9 | c | Argument 1 provided to type-generic macro 'creal' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:172:7:172:7 | c | Argument 1 provided to type-generic macro 'erf' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:173:8:173:8 | c | Argument 1 provided to type-generic macro 'erfc' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:174:7:174:7 | c | Argument 1 provided to type-generic macro 'exp' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:175:8:175:8 | c | Argument 1 provided to type-generic macro 'exp2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:176:9:176:9 | c | Argument 1 provided to type-generic macro 'expm1' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:177:8:177:8 | c | Argument 1 provided to type-generic macro 'fabs' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:178:8:178:8 | c | Argument 1 provided to type-generic macro 'fdim' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:179:11:179:11 | c | Argument 2 provided to type-generic macro 'fdim' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:180:9:180:9 | c | Argument 1 provided to type-generic macro 'floor' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:181:7:181:7 | c | Argument 1 provided to type-generic macro 'fma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:182:10:182:10 | c | Argument 2 provided to type-generic macro 'fma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:183:13:183:13 | c | Argument 3 provided to type-generic macro 'fma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:184:8:184:8 | c | Argument 1 provided to type-generic macro 'fmax' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:185:11:185:11 | c | Argument 2 provided to type-generic macro 'fmax' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:186:8:186:8 | c | Argument 1 provided to type-generic macro 'fmin' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:187:11:187:11 | c | Argument 2 provided to type-generic macro 'fmin' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:188:8:188:8 | c | Argument 1 provided to type-generic macro 'fmod' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:189:11:189:11 | c | Argument 2 provided to type-generic macro 'fmod' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:190:9:190:9 | c | Argument 1 provided to type-generic macro 'frexp' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:191:9:191:9 | c | Argument 1 provided to type-generic macro 'hypot' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:192:12:192:12 | c | Argument 2 provided to type-generic macro 'hypot' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:193:9:193:9 | c | Argument 1 provided to type-generic macro 'ilogb' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:194:9:194:9 | c | Argument 1 provided to type-generic macro 'ldexp' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:195:12:195:12 | c | Argument 2 provided to type-generic macro 'ldexp' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:196:10:196:10 | c | Argument 1 provided to type-generic macro 'lgamma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:197:10:197:10 | c | Argument 1 provided to type-generic macro 'llrint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:198:11:198:11 | c | Argument 1 provided to type-generic macro 'llround' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:199:7:199:7 | c | Argument 1 provided to type-generic macro 'log' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:200:9:200:9 | c | Argument 1 provided to type-generic macro 'log10' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:201:9:201:9 | c | Argument 1 provided to type-generic macro 'log1p' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:202:8:202:8 | c | Argument 1 provided to type-generic macro 'log2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:203:8:203:8 | c | Argument 1 provided to type-generic macro 'logb' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:204:9:204:9 | c | Argument 1 provided to type-generic macro 'lrint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:205:10:205:10 | c | Argument 1 provided to type-generic macro 'lround' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:206:13:206:13 | c | Argument 1 provided to type-generic macro 'nearbyint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:207:13:207:13 | c | Argument 1 provided to type-generic macro 'nextafter' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:208:16:208:16 | c | Argument 2 provided to type-generic macro 'nextafter' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:209:14:209:14 | c | Argument 1 provided to type-generic macro 'nexttoward' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:210:17:210:17 | c | Argument 2 provided to type-generic macro 'nexttoward' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:211:7:211:7 | c | Argument 1 provided to type-generic macro 'pow' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:212:10:212:10 | c | Argument 2 provided to type-generic macro 'pow' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:213:13:213:13 | c | Argument 1 provided to type-generic macro 'remainder' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:214:16:214:16 | c | Argument 2 provided to type-generic macro 'remainder' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:215:10:215:10 | c | Argument 1 provided to type-generic macro 'remquo' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:216:13:216:13 | c | Argument 2 provided to type-generic macro 'remquo' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:217:8:217:8 | c | Argument 1 provided to type-generic macro 'rint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:218:9:218:9 | c | Argument 1 provided to type-generic macro 'round' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:219:10:219:10 | c | Argument 1 provided to type-generic macro 'scalbn' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:220:13:220:13 | c | Argument 2 provided to type-generic macro 'scalbn' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:221:11:221:11 | c | Argument 1 provided to type-generic macro 'scalbln' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:222:14:222:14 | c | Argument 2 provided to type-generic macro 'scalbln' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:223:7:223:7 | c | Argument 1 provided to type-generic macro 'sin' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:224:8:224:8 | c | Argument 1 provided to type-generic macro 'sinh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:225:8:225:8 | c | Argument 1 provided to type-generic macro 'sqrt' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:226:7:226:7 | c | Argument 1 provided to type-generic macro 'tan' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:227:8:227:8 | c | Argument 1 provided to type-generic macro 'tanh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:228:10:228:10 | c | Argument 1 provided to type-generic macro 'tgamma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:229:9:229:9 | c | Argument 1 provided to type-generic macro 'trunc' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:325:14:325:14 | i | Argument 1 provided to type-generic macro 'cos' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:328:20:328:20 | c | Argument 1 provided to type-generic macro 'cos' has essentially character type, which is not essentially signed, unsigned, or floating type. | diff --git a/c/misra/test/rules/RULE-21-22/test.c b/c/misra/test/rules/RULE-21-22/test.c index cc456c17fb..66c889d168 100644 --- a/c/misra/test/rules/RULE-21-22/test.c +++ b/c/misra/test/rules/RULE-21-22/test.c @@ -320,4 +320,10 @@ void f1() { remquo(i, i, 0); // COMPLIANT remquo(i, i, 'c' - 'c'); // COMPLIANT remquo(i, i, c); // COMPLIANT + + /* Test casts */ + cos((char) i); // NON-COMPLIANT + cos((int) c); // COMPLIANT + cos((int) (char) i); // COMPLIANT + cos((char) (int) c); // NON-COMPLIANT } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-22/test.c.clang b/c/misra/test/rules/RULE-21-22/test.c.clang new file mode 100644 index 0000000000..d28576e058 --- /dev/null +++ b/c/misra/test/rules/RULE-21-22/test.c.clang @@ -0,0 +1,329 @@ +#include +#include +#include +#include + +void f1() { + int i = 0; + unsigned int ui = 0; + short s = 0; + unsigned short us = 0; + char c = 0; + unsigned char uc = 0; + signed char sc = 0; + long l = 0; + unsigned long ul = 0; + float f = 0.0f; + float _Complex cf = 0.0f + 0.0f * I; + double d = 0.0; + char *p = 0; + void *vp = 0; + uintptr_t uip = p; + enum { e1 } e = e1; + bool b = true; + + cos(i); // COMPLIANT + cos(ui); // COMPLIANT + cos(s); // COMPLIANT + cos(us); // COMPLIANT + cos(c); // NON-COMPLIANT + cos(uc); // COMPLIANT + cos(sc); // COMPLIANT + cos(l); // COMPLIANT + cos(ul); // COMPLIANT + cos(f); // COMPLIANT + cos(cf); // COMPLIANT + cos(d); // COMPLIANT + // cos(p); // Doesn't compile + // cos(vp); // Doesn't compile + cos(uip); // COMPLIANT + cos(e); // NON-COMPLIANT + cos(b); // NON-COMPLIANT + cos(1); // COMPLIANT + cos(1.1f); // COMPLIANT + cos('a'); // NON-COMPLIANT[false negative] + + /** + * Int, float, and complex allowed: + */ + acos(i); // COMPLIANT + acos(f); // COMPLIANT + acosh(i); // COMPLIANT + acosh(f); // COMPLIANT + asin(i); // COMPLIANT + asin(f); // COMPLIANT + asinh(i); // COMPLIANT + asinh(f); // COMPLIANT + atan(i); // COMPLIANT + atan(f); // COMPLIANT + atan2(i, i); // COMPLIANT + atan2(f, f); // COMPLIANT + atanh(i); // COMPLIANT + atanh(f); // COMPLIANT + carg(i); // COMPLIANT + carg(f); // COMPLIANT + cbrt(i); // COMPLIANT + cbrt(f); // COMPLIANT + ceil(i); // COMPLIANT + ceil(f); // COMPLIANT + cimag(i); // COMPLIANT + cimag(f); // COMPLIANT + conj(i); // COMPLIANT + conj(f); // COMPLIANT + copysign(i, i); // COMPLIANT + copysign(f, f); // COMPLIANT + cos(i); // COMPLIANT + cos(f); // COMPLIANT + cosh(i); // COMPLIANT + cosh(f); // COMPLIANT + cproj(i); // COMPLIANT + cproj(f); // COMPLIANT + creal(i); // COMPLIANT + creal(f); // COMPLIANT + erf(i); // COMPLIANT + erf(f); // COMPLIANT + erfc(i); // COMPLIANT + erfc(f); // COMPLIANT + exp(i); // COMPLIANT + exp(f); // COMPLIANT + exp2(i); // COMPLIANT + exp2(f); // COMPLIANT + expm1(i); // COMPLIANT + expm1(f); // COMPLIANT + fabs(i); // COMPLIANT + fabs(f); // COMPLIANT + fdim(i, i); // COMPLIANT + fdim(f, f); // COMPLIANT + floor(i); // COMPLIANT + floor(f); // COMPLIANT + fma(i, i, i); // COMPLIANT + fma(f, f, f); // COMPLIANT + fmax(i, i); // COMPLIANT + fmax(f, f); // COMPLIANT + fmin(i, i); // COMPLIANT + fmin(f, f); // COMPLIANT + fmod(i, i); // COMPLIANT + fmod(f, f); // COMPLIANT + frexp(i, &i); // COMPLIANT + frexp(f, &p); // COMPLIANT + hypot(i, i); // COMPLIANT + hypot(f, f); // COMPLIANT + ilogb(i); // COMPLIANT + ilogb(f); // COMPLIANT + llrint(i); // COMPLIANT + llrint(f); // COMPLIANT + ldexp(i, i); // COMPLIANT + ldexp(f, f); // COMPLIANT + lgamma(i); // COMPLIANT + lgamma(f); // COMPLIANT + llround(i); // COMPLIANT + llround(f); // COMPLIANT + log(i); // COMPLIANT + log(f); // COMPLIANT + pow(i, i); // COMPLIANT + pow(f, f); // COMPLIANT + remainder(i, i); // COMPLIANT + remainder(f, f); // COMPLIANT + remquo(i, i, &i); // COMPLIANT + remquo(f, f, &f); // COMPLIANT + rint(i); // COMPLIANT + rint(f); // COMPLIANT + round(i); // COMPLIANT + round(f); // COMPLIANT + scalbn(i, i); // COMPLIANT + scalbn(f, f); // COMPLIANT + scalbln(i, i); // COMPLIANT + scalbln(f, f); // COMPLIANT + sin(i); // COMPLIANT + sin(f); // COMPLIANT + sin(cf); // COMPLIANT + sinh(i); // COMPLIANT + sinh(f); // COMPLIANT + sqrt(i); // COMPLIANT + sqrt(f); // COMPLIANT + tan(i); // COMPLIANT + tan(f); // COMPLIANT + tanh(i); // COMPLIANT + tanh(f); // COMPLIANT + tgamma(i); // COMPLIANT + tgamma(f); // COMPLIANT + trunc(i); // COMPLIANT + trunc(f); // COMPLIANT + + /** + * Char not allowed: + */ + acos(c); // NON-COMPLIANT + acosh(c); // NON-COMPLIANT + asin(c); // NON-COMPLIANT + asinh(c); // NON-COMPLIANT + atan2(c, i); // NON-COMPLIANT + atan2(i, c); // NON-COMPLIANT + atanh(c); // NON-COMPLIANT + carg(c); // NON-COMPLIANT + ceil(c); // NON-COMPLIANT + cimag(c); // NON-COMPLIANT + conj(c); // NON-COMPLIANT + copysign(i, c); // NON-COMPLIANT + copysign(c, i); // NON-COMPLIANT + cosh(c); // NON-COMPLIANT + cproj(c); // NON-COMPLIANT + creal(c); // NON-COMPLIANT + erf(c); // NON-COMPLIANT + erfc(c); // NON-COMPLIANT + exp(c); // NON-COMPLIANT + exp2(c); // NON-COMPLIANT + expm1(c); // NON-COMPLIANT + fabs(c); // NON-COMPLIANT + fdim(c, i); // NON-COMPLIANT + fdim(i, c); // NON-COMPLIANT + floor(c); // NON-COMPLIANT + fma(c, i, i); // NON-COMPLIANT + fma(i, c, i); // NON-COMPLIANT + fma(i, i, c); // NON-COMPLIANT + fmax(c, i); // NON-COMPLIANT + fmax(i, c); // NON-COMPLIANT + fmin(c, i); // NON-COMPLIANT + fmin(i, c); // NON-COMPLIANT + fmod(c, i); // NON-COMPLIANT + fmod(i, c); // NON-COMPLIANT + //frexp(c, i); // NON-COMPLIANT + hypot(c, i); // NON-COMPLIANT + hypot(i, c); // NON-COMPLIANT + ilogb(c); // NON-COMPLIANT + ldexp(c, i); // NON-COMPLIANT + ldexp(i, c); // NON-COMPLIANT + lgamma(c); // NON-COMPLIANT + llrint(c); // NON-COMPLIANT + llround(c); // NON-COMPLIANT + log(c); // NON-COMPLIANT + log10(c); // NON-COMPLIANT + log1p(c); // NON-COMPLIANT + log2(c); // NON-COMPLIANT + logb(c); // NON-COMPLIANT + lrint(c); // NON-COMPLIANT + lround(c); // NON-COMPLIANT + nearbyint(c); // NON-COMPLIANT + nextafter(c, i); // NON-COMPLIANT + nextafter(i, c); // NON-COMPLIANT + nexttoward(c, i); // NON-COMPLIANT + nexttoward(i, c); // NON-COMPLIANT + pow(c, i); // NON-COMPLIANT + pow(i, c); // NON-COMPLIANT + remainder(c, i); // NON-COMPLIANT + remainder(i, c); // NON-COMPLIANT + //remquo(c, i, i); // NON-COMPLIANT + //remquo(i, c, i); // NON-COMPLIANT + rint(c); // NON-COMPLIANT + round(c); // NON-COMPLIANT + scalbn(c, i); // NON-COMPLIANT + scalbn(i, c); // NON-COMPLIANT + scalbln(c, i); // NON-COMPLIANT + scalbln(i, c); // NON-COMPLIANT + sin(c); // NON-COMPLIANT + sinh(c); // NON-COMPLIANT + sqrt(c); // NON-COMPLIANT + tan(c); // NON-COMPLIANT + tanh(c); // NON-COMPLIANT + tgamma(c); // NON-COMPLIANT + trunc(c); // NON-COMPLIANT + + /** + * Complex types allowed in some calls, not others: + */ + acos(cf); // COMPLIANT + acosh(cf); // COMPLIANT + asin(cf); // COMPLIANT + asinh(cf); // COMPLIANT + atan(cf); // COMPLIANT + //atan2(cf, i); // NON-COMPLIANT + //atan2(i, cf); // NON-COMPLIANT + atanh(cf); // COMPLIANT + carg(cf); // COMPLIANT + //cbrt(cf); // NON-COMPLIANT + //ceil(cf); // NON-COMPLIANT + cimag(cf); // COMPLIANT + conj(cf); // COMPLIANT + //copysign(i, cf); // NON-COMPLIANT + //copysign(cf, i); // NON-COMPLIANT + //copysign(i, cf); // NON-COMPLIANT + cos(cf); // COMPLIANT + cosh(cf); // COMPLIANT + cproj(cf); // COMPLIANT + creal(cf); // COMPLIANT + //erf(cf); // NON-COMPLIANT + //erfc(cf); // NON-COMPLIANT + exp(cf); // COMPLIANT + //exp2(cf); // NON-COMPLIANT + //expm1(cf); // NON-COMPLIANT + fabs(cf); // COMPLIANT + //fdim(cf, i); // NON-COMPLIANT + //fdim(i, cf); // NON-COMPLIANT + //floor(cf); // NON-COMPLIANT + //fma(cf, i, i); // NON-COMPLIANT + //fma(i, cf, i); // NON-COMPLIANT + //fma(i, i, cf); // NON-COMPLIANT + //fmax(cf, i); // NON-COMPLIANT + //fmax(i, cf); // NON-COMPLIANT + //fmin(cf, i); // NON-COMPLIANT + //fmin(i, cf); // NON-COMPLIANT + //fmod(cf, i); // NON-COMPLIANT + //fmod(i, cf); // NON-COMPLIANT + //frexp(cf, i); // NON-COMPLIANT + //hypot(cf, i); // NON-COMPLIANT + //hypot(i, cf); // NON-COMPLIANT + //ilogb(cf); // NON-COMPLIANT + //ldexp(cf, i); // NON-COMPLIANT + //ldexp(i, cf); // NON-COMPLIANT + //lgamma(cf); // NON-COMPLIANT + //llrint(cf); // NON-COMPLIANT + //llround(cf); // NON-COMPLIANT + log(cf); // COMPLIANT + //log10(cf); // NON-COMPLIANT + //log1p(cf); // NON-COMPLIANT + //log2(cf); // NON-COMPLIANT + //logb(cf); // NON-COMPLIANT + //lrint(cf); // NON-COMPLIANT + //lround(cf); // NON-COMPLIANT + //nearbyint(cf); // NON-COMPLIANT + //nextafter(cf, i); // NON-COMPLIANT + //nextafter(i, cf); // NON-COMPLIANT + //nexttoward(cf, i); // NON-COMPLIANT + //nexttoward(i, cf); // NON-COMPLIANT + pow(cf, cf); // COMPLIANT + //remainder(cf, i); // NON-COMPLIANT + //remainder(i, cf); // NON-COMPLIANT + //remquo(cf, i, i); // NON-COMPLIANT + //remquo(i, cf, i); // NON-COMPLIANT + //rint(cf); // NON-COMPLIANT + //round(cf); // NON-COMPLIANT + //scalbn(cf, i); // NON-COMPLIANT + //scalbn(i, cf); // NON-COMPLIANT + //scalbln(cf, i); // NON-COMPLIANT + //scalbln(i, cf); // NON-COMPLIANT + sin(cf); // COMPLIANT + sinh(cf); // COMPLIANT + sqrt(cf); // COMPLIANT + tan(cf); // COMPLIANT + tanh(cf); // COMPLIANT + //tgamma(cf); // NON-COMPLIANT + //trunc(cf); // NON-COMPLIANT + + /* Test output arguments thoroughly */ + frexp(i, &i); // COMPLIANT + frexp(i, vp); // COMPLIANT + frexp(i, 0); // COMPLIANT + frexp(i, 'c' - 'c'); // COMPLIANT + //frexp(i, c); // COMPLIANT + remquo(i, i, &i); // COMPLIANT + remquo(i, i, vp); // COMPLIANT + remquo(i, i, 0); // COMPLIANT + remquo(i, i, 'c' - 'c'); // COMPLIANT + //remquo(i, i, c); // COMPLIANT + + /* Test casts */ + cos((char) i); // NON-COMPLIANT + cos((int) c); // COMPLIANT + cos((int) (char) i); // COMPLIANT + cos((char) (int) c); // NON-COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-22/test.c.gcc b/c/misra/test/rules/RULE-21-22/test.c.gcc new file mode 100644 index 0000000000..4661a0b4f7 --- /dev/null +++ b/c/misra/test/rules/RULE-21-22/test.c.gcc @@ -0,0 +1,329 @@ +#include +#include +#include +#include + +void f1() { + int i = 0; + unsigned int ui = 0; + short s = 0; + unsigned short us = 0; + char c = 0; + unsigned char uc = 0; + signed char sc = 0; + long l = 0; + unsigned long ul = 0; + float f = 0.0f; + float _Complex cf = 0.0f + 0.0f * I; + double d = 0.0; + char *p = 0; + void *vp = 0; + uintptr_t uip = p; + enum { e1 } e = e1; + bool b = true; + + cos(i); // COMPLIANT + cos(ui); // COMPLIANT + cos(s); // COMPLIANT + cos(us); // COMPLIANT + cos(c); // NON-COMPLIANT + cos(uc); // COMPLIANT + cos(sc); // COMPLIANT + cos(l); // COMPLIANT + cos(ul); // COMPLIANT + cos(f); // COMPLIANT + cos(cf); // COMPLIANT + cos(d); // COMPLIANT + // cos(p); // Doesn't compile + // cos(vp); // Doesn't compile + cos(uip); // COMPLIANT + cos(e); // NON-COMPLIANT + cos(b); // NON-COMPLIANT + cos(1); // COMPLIANT + cos(1.1f); // COMPLIANT + cos('a'); // NON-COMPLIANT[false negative] + + /** + * Int, float, and complex allowed: + */ + acos(i); // COMPLIANT + acos(f); // COMPLIANT + acosh(i); // COMPLIANT + acosh(f); // COMPLIANT + asin(i); // COMPLIANT + asin(f); // COMPLIANT + asinh(i); // COMPLIANT + asinh(f); // COMPLIANT + atan(i); // COMPLIANT + atan(f); // COMPLIANT + atan2(i, i); // COMPLIANT + atan2(f, f); // COMPLIANT + atanh(i); // COMPLIANT + atanh(f); // COMPLIANT + carg(i); // COMPLIANT + carg(f); // COMPLIANT + cbrt(i); // COMPLIANT + cbrt(f); // COMPLIANT + ceil(i); // COMPLIANT + ceil(f); // COMPLIANT + cimag(i); // COMPLIANT + cimag(f); // COMPLIANT + conj(i); // COMPLIANT + conj(f); // COMPLIANT + copysign(i, i); // COMPLIANT + copysign(f, f); // COMPLIANT + cos(i); // COMPLIANT + cos(f); // COMPLIANT + cosh(i); // COMPLIANT + cosh(f); // COMPLIANT + cproj(i); // COMPLIANT + cproj(f); // COMPLIANT + creal(i); // COMPLIANT + creal(f); // COMPLIANT + erf(i); // COMPLIANT + erf(f); // COMPLIANT + erfc(i); // COMPLIANT + erfc(f); // COMPLIANT + exp(i); // COMPLIANT + exp(f); // COMPLIANT + exp2(i); // COMPLIANT + exp2(f); // COMPLIANT + expm1(i); // COMPLIANT + expm1(f); // COMPLIANT + fabs(i); // COMPLIANT + fabs(f); // COMPLIANT + fdim(i, i); // COMPLIANT + fdim(f, f); // COMPLIANT + floor(i); // COMPLIANT + floor(f); // COMPLIANT + fma(i, i, i); // COMPLIANT + fma(f, f, f); // COMPLIANT + fmax(i, i); // COMPLIANT + fmax(f, f); // COMPLIANT + fmin(i, i); // COMPLIANT + fmin(f, f); // COMPLIANT + fmod(i, i); // COMPLIANT + fmod(f, f); // COMPLIANT + frexp(i, &i); // COMPLIANT + frexp(f, &p); // COMPLIANT + hypot(i, i); // COMPLIANT + hypot(f, f); // COMPLIANT + ilogb(i); // COMPLIANT + ilogb(f); // COMPLIANT + llrint(i); // COMPLIANT + llrint(f); // COMPLIANT + ldexp(i, i); // COMPLIANT + ldexp(f, f); // COMPLIANT + lgamma(i); // COMPLIANT + lgamma(f); // COMPLIANT + llround(i); // COMPLIANT + llround(f); // COMPLIANT + log(i); // COMPLIANT + log(f); // COMPLIANT + pow(i, i); // COMPLIANT + pow(f, f); // COMPLIANT + remainder(i, i); // COMPLIANT + remainder(f, f); // COMPLIANT + remquo(i, i, &i); // COMPLIANT + remquo(f, f, &f); // COMPLIANT + rint(i); // COMPLIANT + rint(f); // COMPLIANT + round(i); // COMPLIANT + round(f); // COMPLIANT + scalbn(i, i); // COMPLIANT + scalbn(f, f); // COMPLIANT + scalbln(i, i); // COMPLIANT + scalbln(f, f); // COMPLIANT + sin(i); // COMPLIANT + sin(f); // COMPLIANT + sin(cf); // COMPLIANT + sinh(i); // COMPLIANT + sinh(f); // COMPLIANT + sqrt(i); // COMPLIANT + sqrt(f); // COMPLIANT + tan(i); // COMPLIANT + tan(f); // COMPLIANT + tanh(i); // COMPLIANT + tanh(f); // COMPLIANT + tgamma(i); // COMPLIANT + tgamma(f); // COMPLIANT + trunc(i); // COMPLIANT + trunc(f); // COMPLIANT + + /** + * Char not allowed: + */ + acos(c); // NON-COMPLIANT + acosh(c); // NON-COMPLIANT + asin(c); // NON-COMPLIANT + asinh(c); // NON-COMPLIANT + atan2(c, i); // NON-COMPLIANT + atan2(i, c); // NON-COMPLIANT + atanh(c); // NON-COMPLIANT + carg(c); // NON-COMPLIANT + ceil(c); // NON-COMPLIANT + cimag(c); // NON-COMPLIANT + conj(c); // NON-COMPLIANT + copysign(i, c); // NON-COMPLIANT + copysign(c, i); // NON-COMPLIANT + cosh(c); // NON-COMPLIANT + cproj(c); // NON-COMPLIANT + creal(c); // NON-COMPLIANT + erf(c); // NON-COMPLIANT + erfc(c); // NON-COMPLIANT + exp(c); // NON-COMPLIANT + exp2(c); // NON-COMPLIANT + expm1(c); // NON-COMPLIANT + fabs(c); // NON-COMPLIANT + fdim(c, i); // NON-COMPLIANT + fdim(i, c); // NON-COMPLIANT + floor(c); // NON-COMPLIANT + fma(c, i, i); // NON-COMPLIANT + fma(i, c, i); // NON-COMPLIANT + fma(i, i, c); // NON-COMPLIANT + fmax(c, i); // NON-COMPLIANT + fmax(i, c); // NON-COMPLIANT + fmin(c, i); // NON-COMPLIANT + fmin(i, c); // NON-COMPLIANT + fmod(c, i); // NON-COMPLIANT + fmod(i, c); // NON-COMPLIANT + frexp(c, i); // NON-COMPLIANT + hypot(c, i); // NON-COMPLIANT + hypot(i, c); // NON-COMPLIANT + ilogb(c); // NON-COMPLIANT + ldexp(c, i); // NON-COMPLIANT + ldexp(i, c); // NON-COMPLIANT + lgamma(c); // NON-COMPLIANT + llrint(c); // NON-COMPLIANT + llround(c); // NON-COMPLIANT + log(c); // NON-COMPLIANT + log10(c); // NON-COMPLIANT + log1p(c); // NON-COMPLIANT + log2(c); // NON-COMPLIANT + logb(c); // NON-COMPLIANT + lrint(c); // NON-COMPLIANT + lround(c); // NON-COMPLIANT + nearbyint(c); // NON-COMPLIANT + nextafter(c, i); // NON-COMPLIANT + nextafter(i, c); // NON-COMPLIANT + nexttoward(c, i); // NON-COMPLIANT + nexttoward(i, c); // NON-COMPLIANT + pow(c, i); // NON-COMPLIANT + pow(i, c); // NON-COMPLIANT + remainder(c, i); // NON-COMPLIANT + remainder(i, c); // NON-COMPLIANT + remquo(c, i, i); // NON-COMPLIANT + remquo(i, c, i); // NON-COMPLIANT + rint(c); // NON-COMPLIANT + round(c); // NON-COMPLIANT + scalbn(c, i); // NON-COMPLIANT + scalbn(i, c); // NON-COMPLIANT + scalbln(c, i); // NON-COMPLIANT + scalbln(i, c); // NON-COMPLIANT + sin(c); // NON-COMPLIANT + sinh(c); // NON-COMPLIANT + sqrt(c); // NON-COMPLIANT + tan(c); // NON-COMPLIANT + tanh(c); // NON-COMPLIANT + tgamma(c); // NON-COMPLIANT + trunc(c); // NON-COMPLIANT + + /** + * Complex types allowed in some calls, not others: + */ + acos(cf); // COMPLIANT + acosh(cf); // COMPLIANT + asin(cf); // COMPLIANT + asinh(cf); // COMPLIANT + atan(cf); // COMPLIANT + //atan2(cf, i); // NON-COMPLIANT + //atan2(i, cf); // NON-COMPLIANT + atanh(cf); // COMPLIANT + carg(cf); // COMPLIANT + //cbrt(cf); // NON-COMPLIANT + //ceil(cf); // NON-COMPLIANT + cimag(cf); // COMPLIANT + conj(cf); // COMPLIANT + //copysign(i, cf); // NON-COMPLIANT + //copysign(cf, i); // NON-COMPLIANT + //copysign(i, cf); // NON-COMPLIANT + cos(cf); // COMPLIANT + cosh(cf); // COMPLIANT + cproj(cf); // COMPLIANT + creal(cf); // COMPLIANT + //erf(cf); // NON-COMPLIANT + //erfc(cf); // NON-COMPLIANT + exp(cf); // COMPLIANT + //exp2(cf); // NON-COMPLIANT + //expm1(cf); // NON-COMPLIANT + fabs(cf); // COMPLIANT + //fdim(cf, i); // NON-COMPLIANT + //fdim(i, cf); // NON-COMPLIANT + //floor(cf); // NON-COMPLIANT + //fma(cf, i, i); // NON-COMPLIANT + //fma(i, cf, i); // NON-COMPLIANT + //fma(i, i, cf); // NON-COMPLIANT + //fmax(cf, i); // NON-COMPLIANT + //fmax(i, cf); // NON-COMPLIANT + //fmin(cf, i); // NON-COMPLIANT + //fmin(i, cf); // NON-COMPLIANT + //fmod(cf, i); // NON-COMPLIANT + //fmod(i, cf); // NON-COMPLIANT + //frexp(cf, i); // NON-COMPLIANT + //hypot(cf, i); // NON-COMPLIANT + //hypot(i, cf); // NON-COMPLIANT + //ilogb(cf); // NON-COMPLIANT + //ldexp(cf, i); // NON-COMPLIANT + //ldexp(i, cf); // NON-COMPLIANT + //lgamma(cf); // NON-COMPLIANT + //llrint(cf); // NON-COMPLIANT + //llround(cf); // NON-COMPLIANT + log(cf); // COMPLIANT + //log10(cf); // NON-COMPLIANT + //log1p(cf); // NON-COMPLIANT + //log2(cf); // NON-COMPLIANT + //logb(cf); // NON-COMPLIANT + //lrint(cf); // NON-COMPLIANT + //lround(cf); // NON-COMPLIANT + //nearbyint(cf); // NON-COMPLIANT + //nextafter(cf, i); // NON-COMPLIANT + //nextafter(i, cf); // NON-COMPLIANT + //nexttoward(cf, i); // NON-COMPLIANT + //nexttoward(i, cf); // NON-COMPLIANT + pow(cf, cf); // COMPLIANT + //remainder(cf, i); // NON-COMPLIANT + //remainder(i, cf); // NON-COMPLIANT + //remquo(cf, i, i); // NON-COMPLIANT + //remquo(i, cf, i); // NON-COMPLIANT + //rint(cf); // NON-COMPLIANT + //round(cf); // NON-COMPLIANT + //scalbn(cf, i); // NON-COMPLIANT + //scalbn(i, cf); // NON-COMPLIANT + //scalbln(cf, i); // NON-COMPLIANT + //scalbln(i, cf); // NON-COMPLIANT + sin(cf); // COMPLIANT + sinh(cf); // COMPLIANT + sqrt(cf); // COMPLIANT + tan(cf); // COMPLIANT + tanh(cf); // COMPLIANT + //tgamma(cf); // NON-COMPLIANT + //trunc(cf); // NON-COMPLIANT + + /* Test output arguments thoroughly */ + frexp(i, &i); // COMPLIANT + frexp(i, vp); // COMPLIANT + frexp(i, 0); // COMPLIANT + frexp(i, 'c' - 'c'); // COMPLIANT + frexp(i, c); // COMPLIANT + remquo(i, i, &i); // COMPLIANT + remquo(i, i, vp); // COMPLIANT + remquo(i, i, 0); // COMPLIANT + remquo(i, i, 'c' - 'c'); // COMPLIANT + remquo(i, i, c); // COMPLIANT + + /* Test casts */ + cos((char) i); // NON-COMPLIANT + cos((int) c); // COMPLIANT + cos((int) (char) i); // COMPLIANT + cos((char) (int) c); // NON-COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected.clang b/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected.clang new file mode 100644 index 0000000000..e6ad5c62e4 --- /dev/null +++ b/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected.clang @@ -0,0 +1,139 @@ +| test.c:95:3:95:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:96:3:96:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:97:3:97:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:98:3:98:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:99:3:99:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:100:3:100:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:101:3:101:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:102:3:102:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:103:3:103:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:104:3:104:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:105:3:105:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:106:3:106:17 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:107:3:107:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:108:3:108:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:109:3:109:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:110:3:110:17 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:111:3:111:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:112:3:112:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:113:3:113:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:114:3:114:17 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:121:3:121:13 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:122:3:122:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:123:3:123:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:124:3:124:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:125:3:125:13 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:126:3:126:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:127:3:127:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:128:3:128:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:131:3:131:13 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:132:3:132:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:133:3:133:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:134:3:134:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:135:3:135:13 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:136:3:136:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:137:3:137:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:138:3:138:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:139:3:139:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:140:3:140:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:141:3:141:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:142:3:142:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:143:3:143:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:144:3:144:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:145:3:145:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:146:3:146:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:147:3:147:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:148:3:148:17 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:149:3:149:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:150:3:150:17 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:151:3:151:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:152:3:152:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:153:3:153:17 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:154:3:154:17 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:155:3:155:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:156:3:156:17 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:157:3:157:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:158:3:158:17 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:159:3:159:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:160:3:160:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:161:3:161:17 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:162:3:162:17 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:165:3:165:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:166:3:166:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:167:3:167:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:168:3:168:17 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:169:3:169:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:170:3:170:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:171:3:171:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:172:3:172:17 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:175:3:175:13 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (float, double). | +| test.c:176:3:176:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (float, long double). | +| test.c:177:3:177:13 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (double, float). | +| test.c:178:3:178:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (double, long double). | +| test.c:179:3:179:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long double, float). | +| test.c:180:3:180:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long double, double). | +| test.c:183:3:183:13 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:184:3:184:13 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:185:3:185:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:186:3:186:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:187:3:187:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:188:3:188:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:189:3:189:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:190:3:190:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:191:3:191:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:192:3:192:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:193:3:193:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:194:3:194:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:195:3:195:13 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:196:3:196:13 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:197:3:197:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:198:3:198:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:199:3:199:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:200:3:200:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:201:3:201:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:202:3:202:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:203:3:203:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:204:3:204:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:205:3:205:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:206:3:206:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:207:3:207:13 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:208:3:208:13 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:209:3:209:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:210:3:210:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:211:3:211:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:212:3:212:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:213:3:213:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, float). | +| test.c:214:3:214:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, double). | +| test.c:215:3:215:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long double). | +| test.c:216:3:216:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, float). | +| test.c:217:3:217:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, double). | +| test.c:218:3:218:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long double). | +| test.c:219:3:219:13 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, float). | +| test.c:220:3:220:13 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, double). | +| test.c:221:3:221:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, long double). | +| test.c:222:3:222:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, float). | +| test.c:223:3:223:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, double). | +| test.c:224:3:224:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, long double). | +| test.c:225:3:225:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, float). | +| test.c:226:3:226:14 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, double). | +| test.c:227:3:227:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long double). | +| test.c:228:3:228:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, float). | +| test.c:229:3:229:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, double). | +| test.c:230:3:230:16 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long double). | +| test.c:235:3:235:15 | atan2(__x,__y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:242:3:242:16 | copysign(__x,__y) | Call to type-generic macro 'copysign' has arguments with differing standard types (int, float). | +| test.c:245:3:245:12 | fdim(__x,__y) | Call to type-generic macro 'fdim' has arguments with differing standard types (int, float). | +| test.c:248:3:248:14 | fma(__x,__y,__z) | Call to type-generic macro 'fma' has arguments with differing standard types (float, int, int). | +| test.c:249:3:249:14 | fma(__x,__y,__z) | Call to type-generic macro 'fma' has arguments with differing standard types (int, float, int). | +| test.c:250:3:250:14 | fma(__x,__y,__z) | Call to type-generic macro 'fma' has arguments with differing standard types (int, int, float). | +| test.c:253:3:253:12 | fmax(__x,__y) | Call to type-generic macro 'fmax' has arguments with differing standard types (int, float). | +| test.c:256:3:256:12 | fmin(__x,__y) | Call to type-generic macro 'fmin' has arguments with differing standard types (int, float). | +| test.c:259:3:259:12 | fmod(__x,__y) | Call to type-generic macro 'fmod' has arguments with differing standard types (int, float). | +| test.c:262:3:262:13 | hypot(__x,__y) | Call to type-generic macro 'hypot' has arguments with differing standard types (int, float). | +| test.c:265:3:265:13 | ldexp(__x,__y) | Call to type-generic macro 'ldexp' has arguments with differing standard types (int, float). | +| test.c:268:3:268:17 | nextafter(__x,__y) | Call to type-generic macro 'nextafter' has arguments with differing standard types (int, float). | +| test.c:271:3:271:18 | nexttoward(__x,__y) | Call to type-generic macro 'nexttoward' has arguments with differing standard types (int, float). | +| test.c:274:3:274:17 | remainder(__x,__y) | Call to type-generic macro 'remainder' has arguments with differing standard types (int, float). | +| test.c:277:3:277:17 | remquo(__x,__y,__z) | Call to type-generic macro 'remquo' has arguments with differing standard types (int, float). | +| test.c:280:3:280:15 | scalbln(__x,__y) | Call to type-generic macro 'scalbln' has arguments with differing standard types (int, float). | +| test.c:283:3:283:14 | scalbn(__x,__y) | Call to type-generic macro 'scalbn' has arguments with differing standard types (int, float). | diff --git a/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected.gcc b/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected.gcc new file mode 100644 index 0000000000..f8c610f8c2 --- /dev/null +++ b/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected.gcc @@ -0,0 +1,139 @@ +| test.c:95:3:95:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:96:3:96:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:97:3:97:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:98:3:98:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:99:3:99:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:100:3:100:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:101:3:101:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:102:3:102:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:103:3:103:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:104:3:104:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:105:3:105:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:106:3:106:17 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:107:3:107:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:108:3:108:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:109:3:109:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:110:3:110:17 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:111:3:111:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:112:3:112:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:113:3:113:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:114:3:114:17 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:121:3:121:13 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:122:3:122:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:123:3:123:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:124:3:124:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:125:3:125:13 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:126:3:126:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:127:3:127:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:128:3:128:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:131:3:131:13 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:132:3:132:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:133:3:133:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:134:3:134:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:135:3:135:13 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:136:3:136:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:137:3:137:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:138:3:138:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:139:3:139:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:140:3:140:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:141:3:141:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:142:3:142:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:143:3:143:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:144:3:144:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:145:3:145:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:146:3:146:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:147:3:147:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:148:3:148:17 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:149:3:149:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:150:3:150:17 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:151:3:151:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:152:3:152:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:153:3:153:17 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:154:3:154:17 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:155:3:155:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:156:3:156:17 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:157:3:157:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:158:3:158:17 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:159:3:159:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:160:3:160:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:161:3:161:17 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:162:3:162:17 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:165:3:165:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:166:3:166:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:167:3:167:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:168:3:168:17 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:169:3:169:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:170:3:170:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:171:3:171:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:172:3:172:17 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:175:3:175:13 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (float, double). | +| test.c:176:3:176:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (float, long double). | +| test.c:177:3:177:13 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (double, float). | +| test.c:178:3:178:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (double, long double). | +| test.c:179:3:179:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long double, float). | +| test.c:180:3:180:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long double, double). | +| test.c:183:3:183:13 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:184:3:184:13 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:185:3:185:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:186:3:186:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:187:3:187:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:188:3:188:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:189:3:189:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:190:3:190:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:191:3:191:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:192:3:192:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:193:3:193:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:194:3:194:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:195:3:195:13 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:196:3:196:13 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:197:3:197:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:198:3:198:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:199:3:199:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:200:3:200:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:201:3:201:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:202:3:202:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:203:3:203:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:204:3:204:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:205:3:205:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:206:3:206:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:207:3:207:13 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:208:3:208:13 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:209:3:209:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:210:3:210:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:211:3:211:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:212:3:212:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:213:3:213:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, float). | +| test.c:214:3:214:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, double). | +| test.c:215:3:215:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long double). | +| test.c:216:3:216:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, float). | +| test.c:217:3:217:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, double). | +| test.c:218:3:218:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long double). | +| test.c:219:3:219:13 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, float). | +| test.c:220:3:220:13 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, double). | +| test.c:221:3:221:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, long double). | +| test.c:222:3:222:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, float). | +| test.c:223:3:223:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, double). | +| test.c:224:3:224:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, long double). | +| test.c:225:3:225:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, float). | +| test.c:226:3:226:14 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, double). | +| test.c:227:3:227:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long double). | +| test.c:228:3:228:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, float). | +| test.c:229:3:229:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, double). | +| test.c:230:3:230:16 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long double). | +| test.c:235:3:235:15 | atan2(Val1,Val2) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:242:3:242:16 | copysign(Val1,Val2) | Call to type-generic macro 'copysign' has arguments with differing standard types (int, float). | +| test.c:245:3:245:12 | fdim(Val1,Val2) | Call to type-generic macro 'fdim' has arguments with differing standard types (int, float). | +| test.c:248:3:248:14 | fma(Val1,Val2,Val3) | Call to type-generic macro 'fma' has arguments with differing standard types (float, int, int). | +| test.c:249:3:249:14 | fma(Val1,Val2,Val3) | Call to type-generic macro 'fma' has arguments with differing standard types (int, float, int). | +| test.c:250:3:250:14 | fma(Val1,Val2,Val3) | Call to type-generic macro 'fma' has arguments with differing standard types (int, int, float). | +| test.c:253:3:253:12 | fmax(Val1,Val2) | Call to type-generic macro 'fmax' has arguments with differing standard types (int, float). | +| test.c:256:3:256:12 | fmin(Val1,Val2) | Call to type-generic macro 'fmin' has arguments with differing standard types (int, float). | +| test.c:259:3:259:12 | fmod(Val1,Val2) | Call to type-generic macro 'fmod' has arguments with differing standard types (int, float). | +| test.c:262:3:262:13 | hypot(Val1,Val2) | Call to type-generic macro 'hypot' has arguments with differing standard types (int, float). | +| test.c:265:3:265:13 | ldexp(Val1,Val2) | Call to type-generic macro 'ldexp' has arguments with differing standard types (int, float). | +| test.c:268:3:268:17 | nextafter(Val1,Val2) | Call to type-generic macro 'nextafter' has arguments with differing standard types (int, float). | +| test.c:271:3:271:18 | nexttoward(Val1,Val2) | Call to type-generic macro 'nexttoward' has arguments with differing standard types (int, float). | +| test.c:274:3:274:17 | remainder(Val1,Val2) | Call to type-generic macro 'remainder' has arguments with differing standard types (int, float). | +| test.c:277:3:277:17 | remquo(Val1,Val2,Val3) | Call to type-generic macro 'remquo' has arguments with differing standard types (int, float). | +| test.c:280:3:280:15 | scalbln(Val1,Val2) | Call to type-generic macro 'scalbln' has arguments with differing standard types (int, float). | +| test.c:283:3:283:14 | scalbn(Val1,Val2) | Call to type-generic macro 'scalbn' has arguments with differing standard types (int, float). | diff --git a/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected b/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected index 967621d71f..0b17405a0e 100644 --- a/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected +++ b/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected @@ -1,33 +1,33 @@ edges -| test.c:4:5:4:6 | *g2 | test.c:53:33:53:34 | g2 | provenance | | -| test.c:4:5:4:6 | *g2 | test.c:54:29:54:30 | g2 | provenance | | -| test.c:4:5:4:6 | *g2 | test.c:55:42:55:43 | g2 | provenance | | -| test.c:4:5:4:6 | *g2 | test.c:56:35:56:36 | g2 | provenance | | -| test.c:4:5:4:6 | *g2 | test.c:57:36:57:37 | g2 | provenance | | -| test.c:4:5:4:6 | *g2 | test.c:58:54:58:55 | g2 | provenance | | -| test.c:4:5:4:6 | *g2 | test.c:59:58:59:59 | g2 | provenance | | -| test.c:4:5:4:6 | *g2 | test.c:60:52:60:53 | g2 | provenance | | -| test.c:4:5:4:6 | *g2 | test.c:61:56:61:57 | g2 | provenance | | -| test.c:4:5:4:6 | *g2 | test.c:62:37:62:38 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:54:33:54:34 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:55:29:55:30 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:56:42:56:43 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:57:35:57:36 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:58:36:58:37 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:59:56:59:57 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:60:60:60:61 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:61:54:61:55 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:62:58:62:59 | g2 | provenance | | | test.c:4:5:4:6 | *g2 | test.c:63:37:63:38 | g2 | provenance | | -| test.c:4:5:4:6 | *g2 | test.c:64:36:64:37 | g2 | provenance | | -| test.c:4:5:4:6 | *g2 | test.c:65:37:65:38 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:64:37:64:38 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:65:36:65:37 | g2 | provenance | | | test.c:4:5:4:6 | *g2 | test.c:66:37:66:38 | g2 | provenance | | -| test.c:4:5:4:6 | *g2 | test.c:67:23:67:24 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:67:37:67:38 | g2 | provenance | | | test.c:4:5:4:6 | *g2 | test.c:68:23:68:24 | g2 | provenance | | -| test.c:4:5:4:6 | *g2 | test.c:71:23:71:24 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:69:23:69:24 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:72:23:72:24 | g2 | provenance | | | test.c:4:10:4:29 | memory_order_relaxed | test.c:4:5:4:6 | *g2 | provenance | | | test.c:4:10:4:29 | memory_order_relaxed | test.c:4:10:4:29 | memory_order_relaxed | provenance | | -| test.c:5:5:5:6 | *g3 | test.c:72:23:72:24 | g3 | provenance | | +| test.c:5:5:5:6 | *g3 | test.c:73:23:73:24 | g3 | provenance | | | test.c:5:10:5:29 | memory_order_acquire | test.c:5:5:5:6 | *g3 | provenance | | | test.c:5:10:5:29 | memory_order_acquire | test.c:5:10:5:29 | memory_order_acquire | provenance | | -| test.c:6:5:6:6 | *g4 | test.c:73:23:73:24 | g4 | provenance | | +| test.c:6:5:6:6 | *g4 | test.c:74:23:74:24 | g4 | provenance | | | test.c:6:10:6:29 | memory_order_consume | test.c:6:5:6:6 | *g4 | provenance | | | test.c:6:10:6:29 | memory_order_consume | test.c:6:10:6:29 | memory_order_consume | provenance | | -| test.c:7:5:7:6 | *g5 | test.c:74:23:74:24 | g5 | provenance | | +| test.c:7:5:7:6 | *g5 | test.c:75:23:75:24 | g5 | provenance | | | test.c:7:10:7:29 | memory_order_acq_rel | test.c:7:5:7:6 | *g5 | provenance | | | test.c:7:10:7:29 | memory_order_acq_rel | test.c:7:10:7:29 | memory_order_acq_rel | provenance | | -| test.c:8:5:8:6 | *g6 | test.c:75:23:75:24 | g6 | provenance | | +| test.c:8:5:8:6 | *g6 | test.c:76:23:76:24 | g6 | provenance | | | test.c:8:10:8:29 | memory_order_release | test.c:8:5:8:6 | *g6 | provenance | | | test.c:8:10:8:29 | memory_order_release | test.c:8:10:8:29 | memory_order_release | provenance | | nodes @@ -46,61 +46,61 @@ nodes | test.c:8:5:8:6 | *g6 | semmle.label | *g6 | | test.c:8:10:8:29 | memory_order_release | semmle.label | memory_order_release | | test.c:8:10:8:29 | memory_order_release | semmle.label | memory_order_release | -| test.c:16:29:16:48 | memory_order_relaxed | semmle.label | memory_order_relaxed | -| test.c:17:29:17:48 | memory_order_acquire | semmle.label | memory_order_acquire | -| test.c:18:29:18:48 | memory_order_consume | semmle.label | memory_order_consume | -| test.c:19:29:19:48 | memory_order_acq_rel | semmle.label | memory_order_acq_rel | -| test.c:20:29:20:48 | memory_order_release | semmle.label | memory_order_release | -| test.c:53:33:53:34 | g2 | semmle.label | g2 | -| test.c:54:29:54:30 | g2 | semmle.label | g2 | -| test.c:55:42:55:43 | g2 | semmle.label | g2 | -| test.c:56:35:56:36 | g2 | semmle.label | g2 | -| test.c:57:36:57:37 | g2 | semmle.label | g2 | -| test.c:58:54:58:55 | g2 | semmle.label | g2 | -| test.c:59:58:59:59 | g2 | semmle.label | g2 | -| test.c:60:52:60:53 | g2 | semmle.label | g2 | -| test.c:61:56:61:57 | g2 | semmle.label | g2 | -| test.c:62:37:62:38 | g2 | semmle.label | g2 | +| test.c:17:29:17:48 | memory_order_relaxed | semmle.label | memory_order_relaxed | +| test.c:18:29:18:48 | memory_order_acquire | semmle.label | memory_order_acquire | +| test.c:19:29:19:48 | memory_order_consume | semmle.label | memory_order_consume | +| test.c:20:29:20:48 | memory_order_acq_rel | semmle.label | memory_order_acq_rel | +| test.c:21:29:21:48 | memory_order_release | semmle.label | memory_order_release | +| test.c:54:33:54:34 | g2 | semmle.label | g2 | +| test.c:55:29:55:30 | g2 | semmle.label | g2 | +| test.c:56:42:56:43 | g2 | semmle.label | g2 | +| test.c:57:35:57:36 | g2 | semmle.label | g2 | +| test.c:58:36:58:37 | g2 | semmle.label | g2 | +| test.c:59:56:59:57 | g2 | semmle.label | g2 | +| test.c:60:60:60:61 | g2 | semmle.label | g2 | +| test.c:61:54:61:55 | g2 | semmle.label | g2 | +| test.c:62:58:62:59 | g2 | semmle.label | g2 | | test.c:63:37:63:38 | g2 | semmle.label | g2 | -| test.c:64:36:64:37 | g2 | semmle.label | g2 | -| test.c:65:37:65:38 | g2 | semmle.label | g2 | +| test.c:64:37:64:38 | g2 | semmle.label | g2 | +| test.c:65:36:65:37 | g2 | semmle.label | g2 | | test.c:66:37:66:38 | g2 | semmle.label | g2 | -| test.c:67:23:67:24 | g2 | semmle.label | g2 | +| test.c:67:37:67:38 | g2 | semmle.label | g2 | | test.c:68:23:68:24 | g2 | semmle.label | g2 | -| test.c:71:23:71:24 | g2 | semmle.label | g2 | -| test.c:72:23:72:24 | g3 | semmle.label | g3 | -| test.c:73:23:73:24 | g4 | semmle.label | g4 | -| test.c:74:23:74:24 | g5 | semmle.label | g5 | -| test.c:75:23:75:24 | g6 | semmle.label | g6 | -| test.c:79:23:79:23 | 1 | semmle.label | 1 | -| test.c:80:23:80:25 | 100 | semmle.label | 100 | +| test.c:69:23:69:24 | g2 | semmle.label | g2 | +| test.c:72:23:72:24 | g2 | semmle.label | g2 | +| test.c:73:23:73:24 | g3 | semmle.label | g3 | +| test.c:74:23:74:24 | g4 | semmle.label | g4 | +| test.c:75:23:75:24 | g5 | semmle.label | g5 | +| test.c:76:23:76:24 | g6 | semmle.label | g6 | +| test.c:80:23:80:23 | 1 | semmle.label | 1 | +| test.c:81:23:81:25 | 100 | semmle.label | 100 | subpaths #select -| test.c:16:29:16:48 | memory_order_relaxed | test.c:16:29:16:48 | memory_order_relaxed | test.c:16:29:16:48 | memory_order_relaxed | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_load | __c11_atomic_load | -| test.c:17:29:17:48 | memory_order_acquire | test.c:17:29:17:48 | memory_order_acquire | test.c:17:29:17:48 | memory_order_acquire | Invalid memory order '$@' in call to function '$@'. | memory_order_acquire | memory_order_acquire | file://:0:0:0:0 | __c11_atomic_load | __c11_atomic_load | -| test.c:18:29:18:48 | memory_order_consume | test.c:18:29:18:48 | memory_order_consume | test.c:18:29:18:48 | memory_order_consume | Invalid memory order '$@' in call to function '$@'. | memory_order_consume | memory_order_consume | file://:0:0:0:0 | __c11_atomic_load | __c11_atomic_load | -| test.c:19:29:19:48 | memory_order_acq_rel | test.c:19:29:19:48 | memory_order_acq_rel | test.c:19:29:19:48 | memory_order_acq_rel | Invalid memory order '$@' in call to function '$@'. | memory_order_acq_rel | memory_order_acq_rel | file://:0:0:0:0 | __c11_atomic_load | __c11_atomic_load | -| test.c:20:29:20:48 | memory_order_release | test.c:20:29:20:48 | memory_order_release | test.c:20:29:20:48 | memory_order_release | Invalid memory order '$@' in call to function '$@'. | memory_order_release | memory_order_release | file://:0:0:0:0 | __c11_atomic_load | __c11_atomic_load | -| test.c:53:33:53:34 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:53:33:53:34 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_store | __c11_atomic_store | -| test.c:54:29:54:30 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:54:29:54:30 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_load | __c11_atomic_load | -| test.c:55:42:55:43 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:55:42:55:43 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_exchange | __c11_atomic_exchange | -| test.c:56:35:56:36 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:56:35:56:36 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_store | __c11_atomic_store | -| test.c:57:36:57:37 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:57:36:57:37 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_exchange | __c11_atomic_exchange | -| test.c:58:54:58:55 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:58:54:58:55 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_compare_exchange_strong | __c11_atomic_compare_exchange_strong | -| test.c:59:58:59:59 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:59:58:59:59 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_compare_exchange_strong | __c11_atomic_compare_exchange_strong | -| test.c:60:52:60:53 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:60:52:60:53 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_compare_exchange_weak | __c11_atomic_compare_exchange_weak | -| test.c:61:56:61:57 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:61:56:61:57 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_compare_exchange_weak | __c11_atomic_compare_exchange_weak | -| test.c:62:37:62:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:62:37:62:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_fetch_add | __c11_atomic_fetch_add | -| test.c:63:37:63:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:63:37:63:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_fetch_sub | __c11_atomic_fetch_sub | -| test.c:64:36:64:37 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:64:36:64:37 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_fetch_or | __c11_atomic_fetch_or | -| test.c:65:37:65:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:65:37:65:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_fetch_xor | __c11_atomic_fetch_xor | -| test.c:66:37:66:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:66:37:66:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_fetch_and | __c11_atomic_fetch_and | -| test.c:67:23:67:24 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:67:23:67:24 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | -| test.c:68:23:68:24 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:68:23:68:24 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_signal_fence | __c11_atomic_signal_fence | -| test.c:71:23:71:24 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:71:23:71:24 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | -| test.c:72:23:72:24 | g3 | test.c:5:10:5:29 | memory_order_acquire | test.c:72:23:72:24 | g3 | Invalid memory order '$@' in call to function '$@'. | memory_order_acquire | memory_order_acquire | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | -| test.c:73:23:73:24 | g4 | test.c:6:10:6:29 | memory_order_consume | test.c:73:23:73:24 | g4 | Invalid memory order '$@' in call to function '$@'. | memory_order_consume | memory_order_consume | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | -| test.c:74:23:74:24 | g5 | test.c:7:10:7:29 | memory_order_acq_rel | test.c:74:23:74:24 | g5 | Invalid memory order '$@' in call to function '$@'. | memory_order_acq_rel | memory_order_acq_rel | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | -| test.c:75:23:75:24 | g6 | test.c:8:10:8:29 | memory_order_release | test.c:75:23:75:24 | g6 | Invalid memory order '$@' in call to function '$@'. | memory_order_release | memory_order_release | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | -| test.c:79:23:79:23 | 1 | test.c:79:23:79:23 | 1 | test.c:79:23:79:23 | 1 | Invalid memory order '$@' in call to function '$@'. | memory_order_consume | memory_order_consume | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | -| test.c:80:23:80:25 | 100 | test.c:80:23:80:25 | 100 | test.c:80:23:80:25 | 100 | Invalid memory order '$@' in call to function '$@'. | 100 | 100 | file://:0:0:0:0 | __c11_atomic_thread_fence | __c11_atomic_thread_fence | +| test.c:17:29:17:48 | memory_order_relaxed | test.c:17:29:17:48 | memory_order_relaxed | test.c:17:29:17:48 | memory_order_relaxed | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_load_explicit | +| test.c:18:29:18:48 | memory_order_acquire | test.c:18:29:18:48 | memory_order_acquire | test.c:18:29:18:48 | memory_order_acquire | Invalid memory order '$@' in call to function '$@'. | memory_order_acquire | memory_order_acquire | Invocation of a standard function implemented as a macro | atomic_load_explicit | +| test.c:19:29:19:48 | memory_order_consume | test.c:19:29:19:48 | memory_order_consume | test.c:19:29:19:48 | memory_order_consume | Invalid memory order '$@' in call to function '$@'. | memory_order_consume | memory_order_consume | Invocation of a standard function implemented as a macro | atomic_load_explicit | +| test.c:20:29:20:48 | memory_order_acq_rel | test.c:20:29:20:48 | memory_order_acq_rel | test.c:20:29:20:48 | memory_order_acq_rel | Invalid memory order '$@' in call to function '$@'. | memory_order_acq_rel | memory_order_acq_rel | Invocation of a standard function implemented as a macro | atomic_load_explicit | +| test.c:21:29:21:48 | memory_order_release | test.c:21:29:21:48 | memory_order_release | test.c:21:29:21:48 | memory_order_release | Invalid memory order '$@' in call to function '$@'. | memory_order_release | memory_order_release | Invocation of a standard function implemented as a macro | atomic_load_explicit | +| test.c:54:33:54:34 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:54:33:54:34 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_store_explicit | +| test.c:55:29:55:30 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:55:29:55:30 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_load_explicit | +| test.c:56:42:56:43 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:56:42:56:43 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_flag_test_and_set_explicit | +| test.c:57:35:57:36 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:57:35:57:36 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_flag_clear_explicit | +| test.c:58:36:58:37 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:58:36:58:37 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_exchange_explicit | +| test.c:59:56:59:57 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:59:56:59:57 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_compare_exchange_strong_explicit | +| test.c:60:60:60:61 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:60:60:60:61 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_compare_exchange_strong_explicit | +| test.c:61:54:61:55 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:61:54:61:55 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_compare_exchange_weak_explicit | +| test.c:62:58:62:59 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:62:58:62:59 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_compare_exchange_weak_explicit | +| test.c:63:37:63:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:63:37:63:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_fetch_add_explicit | +| test.c:64:37:64:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:64:37:64:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_fetch_sub_explicit | +| test.c:65:36:65:37 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:65:36:65:37 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_fetch_or_explicit | +| test.c:66:37:66:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:66:37:66:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_fetch_xor_explicit | +| test.c:67:37:67:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:67:37:67:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_fetch_and_explicit | +| test.c:68:23:68:24 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:68:23:68:24 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_thread_fence | +| test.c:69:23:69:24 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:69:23:69:24 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_signal_fence | +| test.c:72:23:72:24 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:72:23:72:24 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_thread_fence | +| test.c:73:23:73:24 | g3 | test.c:5:10:5:29 | memory_order_acquire | test.c:73:23:73:24 | g3 | Invalid memory order '$@' in call to function '$@'. | memory_order_acquire | memory_order_acquire | Invocation of a standard function implemented as a macro | atomic_thread_fence | +| test.c:74:23:74:24 | g4 | test.c:6:10:6:29 | memory_order_consume | test.c:74:23:74:24 | g4 | Invalid memory order '$@' in call to function '$@'. | memory_order_consume | memory_order_consume | Invocation of a standard function implemented as a macro | atomic_thread_fence | +| test.c:75:23:75:24 | g5 | test.c:7:10:7:29 | memory_order_acq_rel | test.c:75:23:75:24 | g5 | Invalid memory order '$@' in call to function '$@'. | memory_order_acq_rel | memory_order_acq_rel | Invocation of a standard function implemented as a macro | atomic_thread_fence | +| test.c:76:23:76:24 | g6 | test.c:8:10:8:29 | memory_order_release | test.c:76:23:76:24 | g6 | Invalid memory order '$@' in call to function '$@'. | memory_order_release | memory_order_release | Invocation of a standard function implemented as a macro | atomic_thread_fence | +| test.c:80:23:80:23 | 1 | test.c:80:23:80:23 | 1 | test.c:80:23:80:23 | 1 | Invalid memory order '$@' in call to function '$@'. | memory_order_consume | memory_order_consume | Invocation of a standard function implemented as a macro | atomic_thread_fence | +| test.c:81:23:81:25 | 100 | test.c:81:23:81:25 | 100 | test.c:81:23:81:25 | 100 | Invalid memory order '$@' in call to function '$@'. | 100 | 100 | Invocation of a standard function implemented as a macro | atomic_thread_fence | diff --git a/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected.gcc b/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected.gcc new file mode 100644 index 0000000000..db07e0aa33 --- /dev/null +++ b/c/misra/test/rules/RULE-21-25/InvalidMemoryOrderArgument.expected.gcc @@ -0,0 +1,106 @@ +edges +| test.c:4:5:4:6 | *g2 | test.c:54:33:54:34 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:55:29:55:30 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:56:42:56:43 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:57:35:57:36 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:58:36:58:37 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:59:56:59:57 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:60:60:60:61 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:61:54:61:55 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:62:58:62:59 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:63:37:63:38 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:64:37:64:38 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:65:36:65:37 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:66:37:66:38 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:67:37:67:38 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:68:23:68:24 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:69:23:69:24 | g2 | provenance | | +| test.c:4:5:4:6 | *g2 | test.c:72:23:72:24 | g2 | provenance | | +| test.c:4:10:4:29 | memory_order_relaxed | test.c:4:5:4:6 | *g2 | provenance | | +| test.c:4:10:4:29 | memory_order_relaxed | test.c:4:10:4:29 | memory_order_relaxed | provenance | | +| test.c:5:5:5:6 | *g3 | test.c:73:23:73:24 | g3 | provenance | | +| test.c:5:10:5:29 | memory_order_acquire | test.c:5:5:5:6 | *g3 | provenance | | +| test.c:5:10:5:29 | memory_order_acquire | test.c:5:10:5:29 | memory_order_acquire | provenance | | +| test.c:6:5:6:6 | *g4 | test.c:74:23:74:24 | g4 | provenance | | +| test.c:6:10:6:29 | memory_order_consume | test.c:6:5:6:6 | *g4 | provenance | | +| test.c:6:10:6:29 | memory_order_consume | test.c:6:10:6:29 | memory_order_consume | provenance | | +| test.c:7:5:7:6 | *g5 | test.c:75:23:75:24 | g5 | provenance | | +| test.c:7:10:7:29 | memory_order_acq_rel | test.c:7:5:7:6 | *g5 | provenance | | +| test.c:7:10:7:29 | memory_order_acq_rel | test.c:7:10:7:29 | memory_order_acq_rel | provenance | | +| test.c:8:5:8:6 | *g6 | test.c:76:23:76:24 | g6 | provenance | | +| test.c:8:10:8:29 | memory_order_release | test.c:8:5:8:6 | *g6 | provenance | | +| test.c:8:10:8:29 | memory_order_release | test.c:8:10:8:29 | memory_order_release | provenance | | +nodes +| test.c:4:5:4:6 | *g2 | semmle.label | *g2 | +| test.c:4:10:4:29 | memory_order_relaxed | semmle.label | memory_order_relaxed | +| test.c:4:10:4:29 | memory_order_relaxed | semmle.label | memory_order_relaxed | +| test.c:5:5:5:6 | *g3 | semmle.label | *g3 | +| test.c:5:10:5:29 | memory_order_acquire | semmle.label | memory_order_acquire | +| test.c:5:10:5:29 | memory_order_acquire | semmle.label | memory_order_acquire | +| test.c:6:5:6:6 | *g4 | semmle.label | *g4 | +| test.c:6:10:6:29 | memory_order_consume | semmle.label | memory_order_consume | +| test.c:6:10:6:29 | memory_order_consume | semmle.label | memory_order_consume | +| test.c:7:5:7:6 | *g5 | semmle.label | *g5 | +| test.c:7:10:7:29 | memory_order_acq_rel | semmle.label | memory_order_acq_rel | +| test.c:7:10:7:29 | memory_order_acq_rel | semmle.label | memory_order_acq_rel | +| test.c:8:5:8:6 | *g6 | semmle.label | *g6 | +| test.c:8:10:8:29 | memory_order_release | semmle.label | memory_order_release | +| test.c:8:10:8:29 | memory_order_release | semmle.label | memory_order_release | +| test.c:17:3:17:49 | memory_order_relaxed | semmle.label | memory_order_relaxed | +| test.c:18:3:18:49 | memory_order_acquire | semmle.label | memory_order_acquire | +| test.c:19:3:19:49 | memory_order_consume | semmle.label | memory_order_consume | +| test.c:20:3:20:49 | memory_order_acq_rel | semmle.label | memory_order_acq_rel | +| test.c:21:3:21:49 | memory_order_release | semmle.label | memory_order_release | +| test.c:54:33:54:34 | g2 | semmle.label | g2 | +| test.c:55:29:55:30 | g2 | semmle.label | g2 | +| test.c:56:42:56:43 | g2 | semmle.label | g2 | +| test.c:57:35:57:36 | g2 | semmle.label | g2 | +| test.c:58:36:58:37 | g2 | semmle.label | g2 | +| test.c:59:56:59:57 | g2 | semmle.label | g2 | +| test.c:60:60:60:61 | g2 | semmle.label | g2 | +| test.c:61:54:61:55 | g2 | semmle.label | g2 | +| test.c:62:58:62:59 | g2 | semmle.label | g2 | +| test.c:63:37:63:38 | g2 | semmle.label | g2 | +| test.c:64:37:64:38 | g2 | semmle.label | g2 | +| test.c:65:36:65:37 | g2 | semmle.label | g2 | +| test.c:66:37:66:38 | g2 | semmle.label | g2 | +| test.c:67:37:67:38 | g2 | semmle.label | g2 | +| test.c:68:23:68:24 | g2 | semmle.label | g2 | +| test.c:69:23:69:24 | g2 | semmle.label | g2 | +| test.c:72:23:72:24 | g2 | semmle.label | g2 | +| test.c:73:23:73:24 | g3 | semmle.label | g3 | +| test.c:74:23:74:24 | g4 | semmle.label | g4 | +| test.c:75:23:75:24 | g5 | semmle.label | g5 | +| test.c:76:23:76:24 | g6 | semmle.label | g6 | +| test.c:80:23:80:23 | 1 | semmle.label | 1 | +| test.c:81:23:81:25 | 100 | semmle.label | 100 | +subpaths +#select +| test.c:17:3:17:49 | memory_order_relaxed | test.c:17:3:17:49 | memory_order_relaxed | test.c:17:3:17:49 | memory_order_relaxed | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_load_explicit | +| test.c:18:3:18:49 | memory_order_acquire | test.c:18:3:18:49 | memory_order_acquire | test.c:18:3:18:49 | memory_order_acquire | Invalid memory order '$@' in call to function '$@'. | memory_order_acquire | memory_order_acquire | Invocation of a standard function implemented as a macro | atomic_load_explicit | +| test.c:19:3:19:49 | memory_order_consume | test.c:19:3:19:49 | memory_order_consume | test.c:19:3:19:49 | memory_order_consume | Invalid memory order '$@' in call to function '$@'. | memory_order_consume | memory_order_consume | Invocation of a standard function implemented as a macro | atomic_load_explicit | +| test.c:20:3:20:49 | memory_order_acq_rel | test.c:20:3:20:49 | memory_order_acq_rel | test.c:20:3:20:49 | memory_order_acq_rel | Invalid memory order '$@' in call to function '$@'. | memory_order_acq_rel | memory_order_acq_rel | Invocation of a standard function implemented as a macro | atomic_load_explicit | +| test.c:21:3:21:49 | memory_order_release | test.c:21:3:21:49 | memory_order_release | test.c:21:3:21:49 | memory_order_release | Invalid memory order '$@' in call to function '$@'. | memory_order_release | memory_order_release | Invocation of a standard function implemented as a macro | atomic_load_explicit | +| test.c:54:33:54:34 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:54:33:54:34 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_store_explicit | +| test.c:55:29:55:30 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:55:29:55:30 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_load_explicit | +| test.c:56:42:56:43 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:56:42:56:43 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_flag_test_and_set_explicit | +| test.c:57:35:57:36 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:57:35:57:36 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_flag_clear_explicit | +| test.c:58:36:58:37 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:58:36:58:37 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_exchange_explicit | +| test.c:59:56:59:57 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:59:56:59:57 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_compare_exchange_strong_explicit | +| test.c:60:60:60:61 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:60:60:60:61 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_compare_exchange_strong_explicit | +| test.c:61:54:61:55 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:61:54:61:55 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_compare_exchange_weak_explicit | +| test.c:62:58:62:59 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:62:58:62:59 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_compare_exchange_weak_explicit | +| test.c:63:37:63:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:63:37:63:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_fetch_add_explicit | +| test.c:64:37:64:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:64:37:64:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_fetch_sub_explicit | +| test.c:65:36:65:37 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:65:36:65:37 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_fetch_or_explicit | +| test.c:66:37:66:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:66:37:66:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_fetch_xor_explicit | +| test.c:67:37:67:38 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:67:37:67:38 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_fetch_and_explicit | +| test.c:68:23:68:24 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:68:23:68:24 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_thread_fence | +| test.c:69:23:69:24 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:69:23:69:24 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_signal_fence | +| test.c:72:23:72:24 | g2 | test.c:4:10:4:29 | memory_order_relaxed | test.c:72:23:72:24 | g2 | Invalid memory order '$@' in call to function '$@'. | memory_order_relaxed | memory_order_relaxed | Invocation of a standard function implemented as a macro | atomic_thread_fence | +| test.c:73:23:73:24 | g3 | test.c:5:10:5:29 | memory_order_acquire | test.c:73:23:73:24 | g3 | Invalid memory order '$@' in call to function '$@'. | memory_order_acquire | memory_order_acquire | Invocation of a standard function implemented as a macro | atomic_thread_fence | +| test.c:74:23:74:24 | g4 | test.c:6:10:6:29 | memory_order_consume | test.c:74:23:74:24 | g4 | Invalid memory order '$@' in call to function '$@'. | memory_order_consume | memory_order_consume | Invocation of a standard function implemented as a macro | atomic_thread_fence | +| test.c:75:23:75:24 | g5 | test.c:7:10:7:29 | memory_order_acq_rel | test.c:75:23:75:24 | g5 | Invalid memory order '$@' in call to function '$@'. | memory_order_acq_rel | memory_order_acq_rel | Invocation of a standard function implemented as a macro | atomic_thread_fence | +| test.c:76:23:76:24 | g6 | test.c:8:10:8:29 | memory_order_release | test.c:76:23:76:24 | g6 | Invalid memory order '$@' in call to function '$@'. | memory_order_release | memory_order_release | Invocation of a standard function implemented as a macro | atomic_thread_fence | +| test.c:80:23:80:23 | 1 | test.c:80:23:80:23 | 1 | test.c:80:23:80:23 | 1 | Invalid memory order '$@' in call to function '$@'. | memory_order_consume | memory_order_consume | Invocation of a standard function implemented as a macro | atomic_thread_fence | +| test.c:81:23:81:25 | 100 | test.c:81:23:81:25 | 100 | test.c:81:23:81:25 | 100 | Invalid memory order '$@' in call to function '$@'. | 100 | 100 | Invocation of a standard function implemented as a macro | atomic_thread_fence | diff --git a/c/misra/test/rules/RULE-21-25/test.c b/c/misra/test/rules/RULE-21-25/test.c index d1831785ba..fc9fc67e95 100644 --- a/c/misra/test/rules/RULE-21-25/test.c +++ b/c/misra/test/rules/RULE-21-25/test.c @@ -1,4 +1,4 @@ -#include "stdatomic.h" +#include int g1 = memory_order_seq_cst; int g2 = memory_order_relaxed; @@ -6,6 +6,7 @@ int g3 = memory_order_acquire; int g4 = memory_order_consume; int g5 = memory_order_acq_rel; int g6 = memory_order_release; +int *ptr; void f(int p) { _Atomic int l1; @@ -25,8 +26,8 @@ void f(int p) { atomic_flag_test_and_set(&l2); // COMPLIANT atomic_flag_clear(&l2); // COMPLIANT atomic_exchange(&l1, 0); // COMPLIANT - atomic_compare_exchange_strong(&l1, 0, 1); // COMPLIANT - atomic_compare_exchange_weak(&l1, 0, 1); // COMPLIANT + atomic_compare_exchange_strong(&l1, ptr, 1); // COMPLIANT + atomic_compare_exchange_weak(&l1, ptr, 1); // COMPLIANT atomic_fetch_add(&l1, 0); // COMPLIANT atomic_fetch_sub(&l1, 0); // COMPLIANT atomic_fetch_or(&l1, 0); // COMPLIANT @@ -39,8 +40,8 @@ void f(int p) { atomic_flag_test_and_set_explicit(&l2, g1); // COMPLIANT atomic_flag_clear_explicit(&l2, g1); // COMPLIANT atomic_exchange_explicit(&l1, 0, g1); // COMPLIANT - atomic_compare_exchange_strong_explicit(&l1, 0, 1, g1, g1); // COMPLIANT - atomic_compare_exchange_weak_explicit(&l1, 0, 1, g1, g1); // COMPLIANT + atomic_compare_exchange_strong_explicit(&l1, ptr, 1, g1, g1); // COMPLIANT + atomic_compare_exchange_weak_explicit(&l1, ptr, 1, g1, g1); // COMPLIANT atomic_fetch_add_explicit(&l1, 0, g1); // COMPLIANT atomic_fetch_sub_explicit(&l1, 0, g1); // COMPLIANT atomic_fetch_or_explicit(&l1, 0, g1); // COMPLIANT @@ -55,10 +56,10 @@ void f(int p) { atomic_flag_test_and_set_explicit(&l2, g2); // NON-COMPLIANT atomic_flag_clear_explicit(&l2, g2); // NON-COMPLIANT atomic_exchange_explicit(&l1, 0, g2); // NON-COMPLIANT - atomic_compare_exchange_strong_explicit(&l1, 0, 1, g2, g1); // NON-COMPLIANT - atomic_compare_exchange_strong_explicit(&l1, 0, 1, g1, g2); // NON-COMPLIANT - atomic_compare_exchange_weak_explicit(&l1, 0, 1, g2, g1); // NON-COMPLIANT - atomic_compare_exchange_weak_explicit(&l1, 0, 1, g1, g2); // NON-COMPLIANT + atomic_compare_exchange_strong_explicit(&l1, ptr, 1, g2, g1); // NON-COMPLIANT + atomic_compare_exchange_strong_explicit(&l1, ptr, 1, g1, g2); // NON-COMPLIANT + atomic_compare_exchange_weak_explicit(&l1, ptr, 1, g2, g1); // NON-COMPLIANT + atomic_compare_exchange_weak_explicit(&l1, ptr, 1, g1, g2); // NON-COMPLIANT atomic_fetch_add_explicit(&l1, 0, g2); // NON-COMPLIANT atomic_fetch_sub_explicit(&l1, 0, g2); // NON-COMPLIANT atomic_fetch_or_explicit(&l1, 0, g2); // NON-COMPLIANT diff --git a/c/misra/test/rules/RULE-21-26/test.c b/c/misra/test/rules/RULE-21-26/test.c index d26f9c1f2f..b08f7e54a1 100644 --- a/c/misra/test/rules/RULE-21-26/test.c +++ b/c/misra/test/rules/RULE-21-26/test.c @@ -9,7 +9,7 @@ struct timespec ts = {0, 0}; void doTimeLock(mtx_t *m) { mtx_timedlock(m, &ts); } -void main(void) { +int main(int argc, char *argv[]) { mtx_init(&g1, mtx_plain); mtx_timedlock(&g1, &ts); // NON-COMPLIANT doTimeLock(&g1); // NON-COMPLIANT diff --git a/c/misra/test/rules/RULE-22-16/test.c b/c/misra/test/rules/RULE-22-16/test.c index c97fb3d588..723516509f 100644 --- a/c/misra/test/rules/RULE-22-16/test.c +++ b/c/misra/test/rules/RULE-22-16/test.c @@ -41,7 +41,7 @@ void f6(int p) { goto skipped; } mtx_unlock(&m); -skipped: +skipped:; } void f7(int p) { diff --git a/c/misra/test/rules/RULE-8-15/RedeclarationOfObjectWithUnmatchedAlignment.expected.gcc b/c/misra/test/rules/RULE-8-15/RedeclarationOfObjectWithUnmatchedAlignment.expected.gcc index f1054946a7..6f3d414214 100644 --- a/c/misra/test/rules/RULE-8-15/RedeclarationOfObjectWithUnmatchedAlignment.expected.gcc +++ b/c/misra/test/rules/RULE-8-15/RedeclarationOfObjectWithUnmatchedAlignment.expected.gcc @@ -1,10 +1,10 @@ -| test.c:11:8:11:15 | alignas(...) | Variable g4 declared with lexically different _Alignof() values '$@' and '$@' | test.c:11:8:11:15 | alignas(...) | 16 | test.c:12:8:12:15 | alignas(...) | 32 | -| test.c:12:8:12:15 | alignas(...) | Variable g4 declared with lexically different _Alignof() values '$@' and '$@' | test.c:12:8:12:15 | alignas(...) | 32 | test.c:11:8:11:15 | alignas(...) | 16 | -| test.c:18:8:18:15 | alignas(...) | Variable g6 declared with lexically different _Alignof() values '$@' and '$@' | test.c:18:8:18:15 | alignas(...) | int | test.c:19:8:19:15 | alignas(...) | 4 | -| test.c:19:8:19:15 | alignas(...) | Variable g6 declared with lexically different _Alignof() values '$@' and '$@' | test.c:19:8:19:15 | alignas(...) | 4 | test.c:18:8:18:15 | alignas(...) | int | -| test.c:22:8:22:15 | alignas(...) | Variable g7 declared with lexically different _Alignof() values '$@' and '$@' | test.c:22:8:22:15 | alignas(...) | ... * ... | test.c:23:8:23:15 | alignas(...) | 32 | -| test.c:23:8:23:15 | alignas(...) | Variable g7 declared with lexically different _Alignof() values '$@' and '$@' | test.c:23:8:23:15 | alignas(...) | 32 | test.c:22:8:22:15 | alignas(...) | ... * ... | -| test.c:28:8:28:15 | alignas(...) | Variable g9 declared with lexically different _Alignof() values '$@' and '$@' | test.c:28:8:28:15 | alignas(...) | ... * ... | test.c:29:8:29:15 | alignas(...) | ... * ... | -| test.c:29:8:29:15 | alignas(...) | Variable g9 declared with lexically different _Alignof() values '$@' and '$@' | test.c:29:8:29:15 | alignas(...) | ... * ... | test.c:28:8:28:15 | alignas(...) | ... * ... | -| test.c:34:8:34:15 | alignas(...) | Variable g11 declared with lexically different _Alignof() values '$@' and '$@' | test.c:34:8:34:15 | alignas(...) | signed int | test.c:35:8:35:15 | alignas(...) | unsigned int | -| test.c:35:8:35:15 | alignas(...) | Variable g11 declared with lexically different _Alignof() values '$@' and '$@' | test.c:35:8:35:15 | alignas(...) | unsigned int | test.c:34:8:34:15 | alignas(...) | signed int | +| test.c:11:8:11:15 | alignas(...) | Variable g4 declared with lexically different _Alignof() values '$@' and '$@'. | test.c:11:8:11:15 | alignas(...) | 16 | test.c:12:8:12:15 | alignas(...) | 32 | +| test.c:12:8:12:15 | alignas(...) | Variable g4 declared with lexically different _Alignof() values '$@' and '$@'. | test.c:12:8:12:15 | alignas(...) | 32 | test.c:11:8:11:15 | alignas(...) | 16 | +| test.c:18:8:18:15 | alignas(...) | Variable g6 declared with lexically different _Alignof() values '$@' and '$@'. | test.c:18:8:18:15 | alignas(...) | int | test.c:19:8:19:15 | alignas(...) | 4 | +| test.c:19:8:19:15 | alignas(...) | Variable g6 declared with lexically different _Alignof() values '$@' and '$@'. | test.c:19:8:19:15 | alignas(...) | 4 | test.c:18:8:18:15 | alignas(...) | int | +| test.c:22:8:22:15 | alignas(...) | Variable g7 declared with lexically different _Alignof() values '$@' and '$@'. | test.c:22:8:22:15 | alignas(...) | ... * ... | test.c:23:8:23:15 | alignas(...) | 32 | +| test.c:23:8:23:15 | alignas(...) | Variable g7 declared with lexically different _Alignof() values '$@' and '$@'. | test.c:23:8:23:15 | alignas(...) | 32 | test.c:22:8:22:15 | alignas(...) | ... * ... | +| test.c:28:8:28:15 | alignas(...) | Variable g9 declared with lexically different _Alignof() values '$@' and '$@'. | test.c:28:8:28:15 | alignas(...) | ... * ... | test.c:29:8:29:15 | alignas(...) | ... * ... | +| test.c:29:8:29:15 | alignas(...) | Variable g9 declared with lexically different _Alignof() values '$@' and '$@'. | test.c:29:8:29:15 | alignas(...) | ... * ... | test.c:28:8:28:15 | alignas(...) | ... * ... | +| test.c:34:8:34:15 | alignas(...) | Variable g11 declared with lexically different _Alignof() values '$@' and '$@'. | test.c:34:8:34:15 | alignas(...) | signed int | test.c:35:8:35:15 | alignas(...) | unsigned int | +| test.c:35:8:35:15 | alignas(...) | Variable g11 declared with lexically different _Alignof() values '$@' and '$@'. | test.c:35:8:35:15 | alignas(...) | unsigned int | test.c:34:8:34:15 | alignas(...) | signed int | diff --git a/c/misra/test/rules/RULE-9-7/test.c b/c/misra/test/rules/RULE-9-7/test.c index da367c0bd1..90645f6372 100644 --- a/c/misra/test/rules/RULE-9-7/test.c +++ b/c/misra/test/rules/RULE-9-7/test.c @@ -4,7 +4,7 @@ _Atomic int g1; // COMPLIANT _Atomic int g2 = 0; // COMPLIANT -void f_thread(void *x); +int f_thread(void *x); void f_starts_thread() { thrd_t t; @@ -13,7 +13,7 @@ void f_starts_thread() { void f_may_initialize_argument(void *p1) {} -void main() { +int main(int argc, char *argv[]) { _Atomic int l1 = 1; // COMPLIANT f_starts_thread(); diff --git a/change_notes/2025-04-08-address-cross-compiler-compatibility-in-misra-2023.md b/change_notes/2025-04-08-address-cross-compiler-compatibility-in-misra-2023.md new file mode 100644 index 0000000000..abe4c2bba8 --- /dev/null +++ b/change_notes/2025-04-08-address-cross-compiler-compatibility-in-misra-2023.md @@ -0,0 +1,12 @@ + - `RULE-21-22`, `RULE-21-23` - `TgMathArgumentWithInvalidEssentialType.ql`, `TgMathArgumentsWithDifferingStandardType.ql` + - Change type-generic macro analysis for finding macro parameters to be compatible with gcc, by ignoring early arguments inserted by gcc. + - Change explicit conversion logic to ignore the explicit casts inserted in macro bodies by clang, which previously overruled the argument essential type. + - `RULE-13-2` - `UnsequencedAtomicReads.ql`: + - Handle statement expression implementation of atomic operations in gcc. + - `RULE-21-25` - `InvalidMemoryOrderArgument.ql`: + - Handle case of where the enum `memory_order` is declared via a typedef as an anonymous enum. + - Rewrite how atomically sequenced operations are found; no longer look for builtins or internal functions, instead look for macros with the exact expected name and analyze the macro bodies for the memory sequence parameter. + - `RULE-9-7` - `UninitializedAtomicArgument.ql`: + - Handle gcc case where `atomic_init` is defined is a call to `atomic_store`, and take a more flexible approach to finding the initialized atomic variable. + - `DIR-4-15` - `PossibleMisuseOfUndetectedInfinity.ql`, `PossibleMisuseOfUndetectedNaN.ql`: + - Fix issue when analyzing clang/gcc implementations of floating point classification macros, where analysis incorrectly determined that `x` in `isinf(x)` was guaranteed to be infinite at the call site itself, affecting later analysis involving `x`. \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/FloatingPoint.qll b/cpp/common/src/codingstandards/cpp/FloatingPoint.qll index f5ff2fefca..e2a13bd62e 100644 --- a/cpp/common/src/codingstandards/cpp/FloatingPoint.qll +++ b/cpp/common/src/codingstandards/cpp/FloatingPoint.qll @@ -325,7 +325,8 @@ predicate guardedNotFPClass(Expr e, FPClassification cls) { hashCons(checked) = hashCons(e) and guard.controls(e, cmpEq) and guard.constrainsFPClass(checked, constraint, cmpEq) and - constraint.mustNotBe(cls) + constraint.mustNotBe(cls) and + not checked = e ) } diff --git a/cpp/common/src/codingstandards/cpp/StdFunctionOrMacro.qll b/cpp/common/src/codingstandards/cpp/StdFunctionOrMacro.qll index 1067b7ad09..ec4873d20e 100644 --- a/cpp/common/src/codingstandards/cpp/StdFunctionOrMacro.qll +++ b/cpp/common/src/codingstandards/cpp/StdFunctionOrMacro.qll @@ -3,28 +3,21 @@ * implement a function as a macro: the class `StdFunctionOrMacro<...>::Call` matches both std * function calls as well as std function macro expansions. * - * For instance, `atomic_init` may be implemented as a function, but is also implemented as - * `#DEFINE atomic_init(x) __c11_atomic_init(x)` on some platforms. This module aids in finding - * calls to any standard function which may be a macro, and has predefined behavior for - * handling `__c11_*` macros. + * For instance, `atomic_init` may be implemented as a function, but is also implemented as a + * complicated macro on some platforms. This module aids in finding calls to any standard function + * which may be a macro. * * Since a macro can be defined to expand to any expression, we cannot know generally which - * expanded expressions in `f(x, y)` correspond to arguments `x` or `y`. To handle this, the - * following inference options are available: - * - `NoMacroExpansionInference`: Assume any expression in the macro expansion could correspond to - * any macro argument. - * - `C11FunctionWrapperMacro`: Check if the macro expands to a function call prefixed with - * `__c11_` and if so, return the corresponding argument. Otherwise, fall back to - * `NoMacroExpansionInference`. - * - `InferMacroExpansionArguments`: Implement your own logic for inferring the argument. + * expanded expressions in `f(x, y)` correspond to arguments `x` or `y`. To handle this, implement + * the module `InferMacroExpansionArguments`. * - * To use this module, pick one of the above inference strategies, and then create a predicate for - * the name you wish to match. For instance: + * To match a function of a particular name create a predicate for the name you wish to match. For + * instance: * * ```codeql * private string atomicInit() { result = "atomic_init" } * - * from StdFunctionOrMacro::Call c + * from StdFunctionOrMacro::Call c * select c.getArgument(0) * ``` */ @@ -33,7 +26,7 @@ import cpp as cpp private string atomicInit() { result = "atomic_init" } -class AtomicInitCall = StdFunctionOrMacro::Call; +class AtomicInitCall = StdFunctionOrMacro::Call; /** Specify the name of your function as a predicate */ private signature string getName(); @@ -44,15 +37,72 @@ private signature module InferMacroExpansionArguments { cpp::Expr inferArgument(cpp::MacroInvocation mi, int argumentIdx); } -/** Assume macro `f(x, y, ...)` expands to `__c11_f(x, y, ...)`. */ -private module C11FunctionWrapperMacro implements InferMacroExpansionArguments { +private module InferAtomicMacroArgs implements InferMacroExpansionArguments { + bindingset[pattern] + private cpp::Expr getMacroVarInitializer(cpp::MacroInvocation mi, string pattern) { + exists(cpp::VariableDeclarationEntry decl | + mi.getAGeneratedElement() = decl and + decl.getName().matches(pattern) and + result = decl.getDeclaration().getInitializer().getExpr() + ) + } + bindingset[mi, argumentIdx] cpp::Expr inferArgument(cpp::MacroInvocation mi, int argumentIdx) { - exists(cpp::FunctionCall fc | - fc = mi.getExpr() and - fc.getTarget().hasName("__c11_" + mi.getMacroName()) and - result = mi.getExpr().(cpp::FunctionCall).getArgument(argumentIdx) - ) + result = mi.getExpr().(cpp::FunctionCall).getArgument(argumentIdx) + or + if + argumentIdx = 0 and + exists(getMacroVarInitializer(mi, "__atomic_%_ptr")) + then result = getMacroVarInitializer(mi, "__atomic_%_ptr") + else + if + argumentIdx = [1, 2] and + exists(getMacroVarInitializer(mi, "__atomic_%_tmp")) + then result = getMacroVarInitializer(mi, "__atomic_%_tmp") + else + exists(cpp::FunctionCall fc | + fc = mi.getAnExpandedElement() and + fc.getTarget().getName().matches("%atomic_%") and + result = fc.getArgument(argumentIdx) + ) + } +} + +private string atomicReadOrWriteName() { + result = + [ + "atomic_load", + "atomic_store", + "atomic_fetch_" + ["add", "sub", "or", "xor", "and"], + "atomic_exchange", + "atomic_compare_exchange_" + ["strong", "weak"] + ] + ["", "_explicit"] +} + +class AtomicReadOrWriteCall = + StdFunctionOrMacro::Call; + +private string atomicallySequencedName() { + result = + [ + "atomic_thread_fence", + "atomic_signal_fence", + "atomic_flag_clear_explicit", + "atomic_flag_test_and_set_explicit", + ] + or + result = atomicReadOrWriteName() and + result.matches("%_explicit") +} + +/** A `stdatomic.h` function which accepts a `memory_order` value as a parameter. */ +class AtomicallySequencedCall extends StdFunctionOrMacro::Call +{ + cpp::Expr getAMemoryOrderArgument() { + if getName() = "atomic_compare_exchange_" + ["strong", "weak"] + "_explicit" + then result = getArgument(getNumberOfArguments() - [1, 2]) + else result = getArgument(getNumberOfArguments() - 1) } } @@ -66,7 +116,7 @@ private module C11FunctionWrapperMacro implements InferMacroExpansionArguments { * * ```codeql * private string atomicInit() { result = "atomic_init" } - * from StdFunctionOrMacro::Call c + * from StdFunctionOrMacro::Call c * select c.getArgument(0) * ``` */ @@ -99,6 +149,25 @@ private module StdFunctionOrMacro Date: Tue, 8 Apr 2025 22:22:59 +0000 Subject: [PATCH 287/370] Format c tests, c ql files --- .../TgMathArgumentWithInvalidEssentialType.ql | 4 +- ...gMathArgumentsWithDifferingStandardType.ql | 4 +- .../RULE-21-25/InvalidMemoryOrderArgument.ql | 4 +- c/misra/test/rules/RULE-18-10/test.c | 6 +- c/misra/test/rules/RULE-18-8/test.c | 2 +- c/misra/test/rules/RULE-21-22/test.c | 8 +-- c/misra/test/rules/RULE-21-25/test.c | 68 +++++++++---------- 7 files changed, 47 insertions(+), 49 deletions(-) diff --git a/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql b/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql index 3c918c10d3..fc8565ade5 100644 --- a/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql +++ b/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql @@ -34,7 +34,9 @@ string getAllowedTypesString(TgMathInvocation call) { else result = "essentially signed, unsigned, or real floating type" } -from TgMathInvocation call, Expr convertedArg, Expr unconverted, int argIndex, Type type, EssentialTypeCategory category +from + TgMathInvocation call, Expr convertedArg, Expr unconverted, int argIndex, Type type, + EssentialTypeCategory category where not isExcluded(call, EssentialTypes2Package::tgMathArgumentWithInvalidEssentialTypeQuery()) and // We must handle conversions specially, as clang inserts casts in the macro body we want to ignore. diff --git a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql index 1a19249982..34d3b62b2c 100644 --- a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql +++ b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql @@ -58,9 +58,7 @@ Type canonicalize(Type type) { else result = type } -Type getEffectiveStandardType(Expr e) { - result = canonicalize(getPromotedType(e)) -} +Type getEffectiveStandardType(Expr e) { result = canonicalize(getPromotedType(e)) } from TgMathInvocation call, Type firstType where diff --git a/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql b/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql index a7b599316a..684b4e50cb 100644 --- a/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql +++ b/c/misra/src/rules/RULE-21-25/InvalidMemoryOrderArgument.ql @@ -77,9 +77,7 @@ module MemoryOrderFlowConfig implements DataFlow::ConfigSig { } predicate isSink(DataFlow::Node node) { - exists(AtomicallySequencedCall call | - call.getAMemoryOrderArgument() = node.asExpr() - ) + exists(AtomicallySequencedCall call | call.getAMemoryOrderArgument() = node.asExpr()) } } diff --git a/c/misra/test/rules/RULE-18-10/test.c b/c/misra/test/rules/RULE-18-10/test.c index b5906a3039..565b51e8de 100644 --- a/c/misra/test/rules/RULE-18-10/test.c +++ b/c/misra/test/rules/RULE-18-10/test.c @@ -57,9 +57,9 @@ void f1( } p20, // Unknown array length types: - int p21[], // COMPLIANT - int p22[][2], // COMPLIANT - int (*p23)[], // COMPLIANT + int p21[], // COMPLIANT + int p22[][2], // COMPLIANT + int (*p23)[], // COMPLIANT // int (*p24)[2][], // doesn't compile int (*p25)[][2], // COMPLIANT diff --git a/c/misra/test/rules/RULE-18-8/test.c b/c/misra/test/rules/RULE-18-8/test.c index 7d6a1400d6..ea639de271 100644 --- a/c/misra/test/rules/RULE-18-8/test.c +++ b/c/misra/test/rules/RULE-18-8/test.c @@ -28,7 +28,7 @@ void f1(int n, int p1[n], // COMPLIANT // Pointers to variably-modified types are not VLAs. int p2[n][n], - int p3[], // array of unknown length is converted to pointer + int p3[], // array of unknown length is converted to pointer int p4[][n] // array of unknown length are not VLAs. ) {} diff --git a/c/misra/test/rules/RULE-21-22/test.c b/c/misra/test/rules/RULE-21-22/test.c index 66c889d168..970df4fd56 100644 --- a/c/misra/test/rules/RULE-21-22/test.c +++ b/c/misra/test/rules/RULE-21-22/test.c @@ -322,8 +322,8 @@ void f1() { remquo(i, i, c); // COMPLIANT /* Test casts */ - cos((char) i); // NON-COMPLIANT - cos((int) c); // COMPLIANT - cos((int) (char) i); // COMPLIANT - cos((char) (int) c); // NON-COMPLIANT + cos((char)i); // NON-COMPLIANT + cos((int)c); // COMPLIANT + cos((int)(char)i); // COMPLIANT + cos((char)(int)c); // NON-COMPLIANT } \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-25/test.c b/c/misra/test/rules/RULE-21-25/test.c index fc9fc67e95..d096634d30 100644 --- a/c/misra/test/rules/RULE-21-25/test.c +++ b/c/misra/test/rules/RULE-21-25/test.c @@ -21,52 +21,52 @@ void f(int p) { atomic_load_explicit(&l1, memory_order_release); // NON-COMPLIANT // Implicit values: - atomic_store(&l1, 0); // COMPLIANT - atomic_load(&l1); // COMPLIANT - atomic_flag_test_and_set(&l2); // COMPLIANT - atomic_flag_clear(&l2); // COMPLIANT - atomic_exchange(&l1, 0); // COMPLIANT + atomic_store(&l1, 0); // COMPLIANT + atomic_load(&l1); // COMPLIANT + atomic_flag_test_and_set(&l2); // COMPLIANT + atomic_flag_clear(&l2); // COMPLIANT + atomic_exchange(&l1, 0); // COMPLIANT atomic_compare_exchange_strong(&l1, ptr, 1); // COMPLIANT atomic_compare_exchange_weak(&l1, ptr, 1); // COMPLIANT - atomic_fetch_add(&l1, 0); // COMPLIANT - atomic_fetch_sub(&l1, 0); // COMPLIANT - atomic_fetch_or(&l1, 0); // COMPLIANT - atomic_fetch_xor(&l1, 0); // COMPLIANT - atomic_fetch_and(&l1, 0); // COMPLIANT + atomic_fetch_add(&l1, 0); // COMPLIANT + atomic_fetch_sub(&l1, 0); // COMPLIANT + atomic_fetch_or(&l1, 0); // COMPLIANT + atomic_fetch_xor(&l1, 0); // COMPLIANT + atomic_fetch_and(&l1, 0); // COMPLIANT // Compliant flowed values (one test per sink): - atomic_store_explicit(&l1, 0, g1); // COMPLIANT - atomic_load_explicit(&l1, g1); // COMPLIANT - atomic_flag_test_and_set_explicit(&l2, g1); // COMPLIANT - atomic_flag_clear_explicit(&l2, g1); // COMPLIANT - atomic_exchange_explicit(&l1, 0, g1); // COMPLIANT + atomic_store_explicit(&l1, 0, g1); // COMPLIANT + atomic_load_explicit(&l1, g1); // COMPLIANT + atomic_flag_test_and_set_explicit(&l2, g1); // COMPLIANT + atomic_flag_clear_explicit(&l2, g1); // COMPLIANT + atomic_exchange_explicit(&l1, 0, g1); // COMPLIANT atomic_compare_exchange_strong_explicit(&l1, ptr, 1, g1, g1); // COMPLIANT atomic_compare_exchange_weak_explicit(&l1, ptr, 1, g1, g1); // COMPLIANT - atomic_fetch_add_explicit(&l1, 0, g1); // COMPLIANT - atomic_fetch_sub_explicit(&l1, 0, g1); // COMPLIANT - atomic_fetch_or_explicit(&l1, 0, g1); // COMPLIANT - atomic_fetch_xor_explicit(&l1, 0, g1); // COMPLIANT - atomic_fetch_and_explicit(&l1, 0, g1); // COMPLIANT - atomic_thread_fence(g1); // COMPLIANT - atomic_signal_fence(g1); // COMPLIANT + atomic_fetch_add_explicit(&l1, 0, g1); // COMPLIANT + atomic_fetch_sub_explicit(&l1, 0, g1); // COMPLIANT + atomic_fetch_or_explicit(&l1, 0, g1); // COMPLIANT + atomic_fetch_xor_explicit(&l1, 0, g1); // COMPLIANT + atomic_fetch_and_explicit(&l1, 0, g1); // COMPLIANT + atomic_thread_fence(g1); // COMPLIANT + atomic_signal_fence(g1); // COMPLIANT // Non-compliant flowed values (one test per sink): - atomic_store_explicit(&l1, 0, g2); // NON-COMPLIANT - atomic_load_explicit(&l1, g2); // NON-COMPLIANT - atomic_flag_test_and_set_explicit(&l2, g2); // NON-COMPLIANT - atomic_flag_clear_explicit(&l2, g2); // NON-COMPLIANT - atomic_exchange_explicit(&l1, 0, g2); // NON-COMPLIANT + atomic_store_explicit(&l1, 0, g2); // NON-COMPLIANT + atomic_load_explicit(&l1, g2); // NON-COMPLIANT + atomic_flag_test_and_set_explicit(&l2, g2); // NON-COMPLIANT + atomic_flag_clear_explicit(&l2, g2); // NON-COMPLIANT + atomic_exchange_explicit(&l1, 0, g2); // NON-COMPLIANT atomic_compare_exchange_strong_explicit(&l1, ptr, 1, g2, g1); // NON-COMPLIANT atomic_compare_exchange_strong_explicit(&l1, ptr, 1, g1, g2); // NON-COMPLIANT atomic_compare_exchange_weak_explicit(&l1, ptr, 1, g2, g1); // NON-COMPLIANT atomic_compare_exchange_weak_explicit(&l1, ptr, 1, g1, g2); // NON-COMPLIANT - atomic_fetch_add_explicit(&l1, 0, g2); // NON-COMPLIANT - atomic_fetch_sub_explicit(&l1, 0, g2); // NON-COMPLIANT - atomic_fetch_or_explicit(&l1, 0, g2); // NON-COMPLIANT - atomic_fetch_xor_explicit(&l1, 0, g2); // NON-COMPLIANT - atomic_fetch_and_explicit(&l1, 0, g2); // NON-COMPLIANT - atomic_thread_fence(g2); // NON-COMPLIANT - atomic_signal_fence(g2); // NON-COMPLIANT + atomic_fetch_add_explicit(&l1, 0, g2); // NON-COMPLIANT + atomic_fetch_sub_explicit(&l1, 0, g2); // NON-COMPLIANT + atomic_fetch_or_explicit(&l1, 0, g2); // NON-COMPLIANT + atomic_fetch_xor_explicit(&l1, 0, g2); // NON-COMPLIANT + atomic_fetch_and_explicit(&l1, 0, g2); // NON-COMPLIANT + atomic_thread_fence(g2); // NON-COMPLIANT + atomic_signal_fence(g2); // NON-COMPLIANT // Non-compliant flowed values (one test per source): atomic_thread_fence(g2); // NON-COMPLIANT From b9e1c0b26f1b0cbcb7d9efe38b29a9ea1e520a9a Mon Sep 17 00:00:00 2001 From: Michael R Fairhurst Date: Wed, 9 Apr 2025 03:01:38 +0000 Subject: [PATCH 288/370] Fix 21-22 test expectations --- .../TgMathArgumentWithInvalidEssentialType.expected | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected index 46e4e8f5c8..03dddb8dfe 100644 --- a/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected +++ b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected @@ -130,5 +130,5 @@ | test.c:303:14:303:15 | cf | Argument 2 provided to type-generic macro 'scalbln' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | | test.c:309:10:309:11 | cf | Argument 1 provided to type-generic macro 'tgamma' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | | test.c:310:9:310:10 | cf | Argument 1 provided to type-generic macro 'trunc' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | -| test.c:325:14:325:14 | i | Argument 1 provided to type-generic macro 'cos' has essentially character type, which is not essentially signed, unsigned, or floating type. | -| test.c:328:20:328:20 | c | Argument 1 provided to type-generic macro 'cos' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:325:13:325:13 | i | Argument 1 provided to type-generic macro 'cos' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:328:18:328:18 | c | Argument 1 provided to type-generic macro 'cos' has essentially character type, which is not essentially signed, unsigned, or floating type. | From 315276902e53b55bfbb6ecd458f04d6a8b4abc27 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 9 Apr 2025 19:25:48 -0700 Subject: [PATCH 289/370] Update obligation level of new CERT-C rules --- rules.csv | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rules.csv b/rules.csv index 2db1d7a66d..68049625e6 100644 --- a/rules.csv +++ b/rules.csv @@ -515,7 +515,7 @@ c,CERT-C,ERR30-C,Yes,Rule,,,Take care when reading errno,M19-3-1,Contracts4,Hard c,CERT-C,ERR32-C,Yes,Rule,,,Do not rely on indeterminate values of errno,,Contracts5,Hard, c,CERT-C,ERR33-C,Yes,Rule,,,Detect and handle standard library errors,MEM52-CPP,Contracts5,Hard, c,CERT-C,ERR34-C,OutOfScope,Rule,,,Detect errors when converting a string to a number,,,, -c,CERT-C,EXP16-C,Yes,Rule,,,Do not compare function pointers to constant values,,Expressions2,Medium, +c,CERT-C,EXP16-C,Yes,Recommendation,,,Do not compare function pointers to constant values,,Expressions2,Medium, c,CERT-C,EXP30-C,Yes,Rule,,,Do not depend on the order of evaluation for side effects,EXP50-CPP,SideEffects1,Easy, c,CERT-C,EXP32-C,Yes,Rule,,,Do not access a volatile object through a nonvolatile reference,,Pointers3,Easy, c,CERT-C,EXP33-C,Yes,Rule,,,Do not read uninitialized memory,EXP53-CPP,InvalidMemory1,Import, @@ -531,8 +531,8 @@ c,CERT-C,EXP44-C,Yes,Rule,,,"Do not rely on side effects in operands to sizeof, c,CERT-C,EXP45-C,Yes,Rule,,,Do not perform assignments in selection statements,M6-2-1,SideEffects1,Medium, c,CERT-C,EXP46-C,Yes,Rule,,,Do not use a bitwise operator with a Boolean-like operand,,Expressions,Easy, c,CERT-C,EXP47-C,OutOfScope,Rule,,,Do not call va_arg with an argument of the incorrect type,,,, -c,CERT-C,FIO03-C,Yes,Rule,,,Do not make assumptions about fopen() and file creation,,IO5,Hard, -c,CERT-C,FIO21-C,Yes,Rule,,,Do not create temporary files in shared directories,,IO5,Easy, +c,CERT-C,FIO03-C,Yes,Recommendation,,,Do not make assumptions about fopen() and file creation,,IO5,Hard, +c,CERT-C,FIO21-C,Yes,Recommendation,,,Do not create temporary files in shared directories,,IO5,Easy, c,CERT-C,FIO30-C,Yes,Rule,,,Exclude user input from format strings,A27-0-1,IO1,Import, c,CERT-C,FIO32-C,Yes,Rule,,,Do not perform operations on devices that are only appropriate for files,,IO3,Medium, c,CERT-C,FIO34-C,Yes,Rule,,,Distinguish between characters read from a file and EOF or WEOF,,IO1,Hard, From 64ad8fb8955f3e749ce61c8aca33c0272657b30d Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 9 Apr 2025 23:30:12 -0700 Subject: [PATCH 290/370] Add new query suites for CERT-C recommendations --- c/cert/src/codeql-suites/cert-c-default.qls | 10 ++++++++++ c/cert/src/codeql-suites/cert-c-recommendation.qls | 10 ++++++++++ c/cert/src/codeql-suites/cert-default.qls | 11 ++--------- c/cert/src/qlpack.yml | 1 + ...5-04-09-new-cert-c-recommendation-query-suite.md | 9 +++++++++ cpp/cert/src/codeql-suites/cert-cpp-default.qls | 9 +++++++++ .../cert-cpp-single-translation-unit.qls | 11 +++++++++++ cpp/cert/src/codeql-suites/cert-default.qls | 11 ++--------- .../codeql-suites/cert-single-translation-unit.qls | 13 ++----------- cpp/cert/src/qlpack.yml | 1 + 10 files changed, 57 insertions(+), 29 deletions(-) create mode 100644 c/cert/src/codeql-suites/cert-c-default.qls create mode 100644 c/cert/src/codeql-suites/cert-c-recommendation.qls create mode 100644 change_notes/2025-04-09-new-cert-c-recommendation-query-suite.md create mode 100644 cpp/cert/src/codeql-suites/cert-cpp-default.qls create mode 100644 cpp/cert/src/codeql-suites/cert-cpp-single-translation-unit.qls diff --git a/c/cert/src/codeql-suites/cert-c-default.qls b/c/cert/src/codeql-suites/cert-c-default.qls new file mode 100644 index 0000000000..348d2f37ae --- /dev/null +++ b/c/cert/src/codeql-suites/cert-c-default.qls @@ -0,0 +1,10 @@ +- description: CERT C 2016 (Default) +- qlpack: codeql/cert-c-coding-standards +- include: + kind: + - problem + - path-problem + - external/cert/obligation/rule +- exclude: + tags contain: + - external/cert/default-disabled diff --git a/c/cert/src/codeql-suites/cert-c-recommendation.qls b/c/cert/src/codeql-suites/cert-c-recommendation.qls new file mode 100644 index 0000000000..59ac5e9c2d --- /dev/null +++ b/c/cert/src/codeql-suites/cert-c-recommendation.qls @@ -0,0 +1,10 @@ +- description: CERT C 2016 (Recommendations) +- qlpack: codeql/cert-c-coding-standards +- include: + kind: + - problem + - path-problem + - external/cert/obligation/recommendation +- exclude: + tags contain: + - external/cert/default-disabled diff --git a/c/cert/src/codeql-suites/cert-default.qls b/c/cert/src/codeql-suites/cert-default.qls index 1e11a0afca..c093b31fa7 100644 --- a/c/cert/src/codeql-suites/cert-default.qls +++ b/c/cert/src/codeql-suites/cert-default.qls @@ -1,9 +1,2 @@ -- description: CERT C 2016 (Default) -- qlpack: codeql/cert-c-coding-standards -- include: - kind: - - problem - - path-problem -- exclude: - tags contain: - - external/cert/default-disabled +- description: "DEPRECATED - CERT C 2016 - use cert-c-default.qls instead" +- import: codeql-suites/cert-c-default.qls diff --git a/c/cert/src/qlpack.yml b/c/cert/src/qlpack.yml index 631639301e..e3664d75b5 100644 --- a/c/cert/src/qlpack.yml +++ b/c/cert/src/qlpack.yml @@ -3,6 +3,7 @@ version: 2.44.0-dev description: CERT C 2016 suites: codeql-suites license: MIT +default-suite-file: codeql-suites/cert-c-default.qls dependencies: codeql/common-c-coding-standards: '*' codeql/cpp-all: 2.1.1 diff --git a/change_notes/2025-04-09-new-cert-c-recommendation-query-suite.md b/change_notes/2025-04-09-new-cert-c-recommendation-query-suite.md new file mode 100644 index 0000000000..910433e351 --- /dev/null +++ b/change_notes/2025-04-09-new-cert-c-recommendation-query-suite.md @@ -0,0 +1,9 @@ + - The following query suites have been added or modified for CERT C: + - A new query suite has been created `cert-c-default.qls` to avoid confusion with the CERT C++ query suites. The `cert-default.qls` suite has been deprecated, and will be removed in a future releases, and is replaced by the `cert-c-default.qls` suite. + - The `cert-c-default.qls` suite has been specified as the default for the pack, and will include our most up-to-date coverage for CERT C. + - One new query suite, `cert-c-recommended.qls` has been added to enable running CERT recommendations (as opposed to rules) that will be added in the future. + - The default query suite, `cert-c-default.qls` has been set to exclude CERT recommendations (as opposed to rules) that will be added in the future. + - The following query suites have been added or modified for CERT C++: + - A new query suite has been created `cert-cpp-default.qls` to avoid confusion with the CERT C query suites. The `cert-default.qls` suite has been deprecated, and will be removed in a future releases, and is replaced by the `cert-cpp-default.qls` suite. + - The `cert-cpp-default.qls` suite has been specified as the default for the pack, and will include our most up-to-date coverage for CERT C. + - A new query suite has been created `cert-cpp-single-translation-unit.qls` to avoid confusion with the CERT C query suites. The `cert-single-translation-unit.qls` suite has been deprecated, and will be removed in a future releases, and is replaced by the `cert-cpp-single-translation-unit.qls` suite. \ No newline at end of file diff --git a/cpp/cert/src/codeql-suites/cert-cpp-default.qls b/cpp/cert/src/codeql-suites/cert-cpp-default.qls new file mode 100644 index 0000000000..e9211246b1 --- /dev/null +++ b/cpp/cert/src/codeql-suites/cert-cpp-default.qls @@ -0,0 +1,9 @@ +- description: CERT C++ 2016 (Default) +- qlpack: codeql/cert-cpp-coding-standards +- include: + kind: + - problem + - path-problem +- exclude: + tags contain: + - external/cert/default-disabled diff --git a/cpp/cert/src/codeql-suites/cert-cpp-single-translation-unit.qls b/cpp/cert/src/codeql-suites/cert-cpp-single-translation-unit.qls new file mode 100644 index 0000000000..2f09815e0d --- /dev/null +++ b/cpp/cert/src/codeql-suites/cert-cpp-single-translation-unit.qls @@ -0,0 +1,11 @@ +- description: CERT C++ 2016 (Single Translation Unit) +- qlpack: codeql/cert-cpp-coding-standards +- include: + kind: + - problem + - path-problem + tags contain: + - scope/single-translation-unit +- exclude: + tags contain: + - external/cert/default-disabled diff --git a/cpp/cert/src/codeql-suites/cert-default.qls b/cpp/cert/src/codeql-suites/cert-default.qls index e9211246b1..66599b60fb 100644 --- a/cpp/cert/src/codeql-suites/cert-default.qls +++ b/cpp/cert/src/codeql-suites/cert-default.qls @@ -1,9 +1,2 @@ -- description: CERT C++ 2016 (Default) -- qlpack: codeql/cert-cpp-coding-standards -- include: - kind: - - problem - - path-problem -- exclude: - tags contain: - - external/cert/default-disabled +- description: "DEPRECATED - CERT C++ 2016 - use cert-cpp-default.qls instead" +- import: codeql-suites/cert-cpp-default.qls \ No newline at end of file diff --git a/cpp/cert/src/codeql-suites/cert-single-translation-unit.qls b/cpp/cert/src/codeql-suites/cert-single-translation-unit.qls index 2f09815e0d..4966648394 100644 --- a/cpp/cert/src/codeql-suites/cert-single-translation-unit.qls +++ b/cpp/cert/src/codeql-suites/cert-single-translation-unit.qls @@ -1,11 +1,2 @@ -- description: CERT C++ 2016 (Single Translation Unit) -- qlpack: codeql/cert-cpp-coding-standards -- include: - kind: - - problem - - path-problem - tags contain: - - scope/single-translation-unit -- exclude: - tags contain: - - external/cert/default-disabled +- description: "DEPRECATED - CERT C++ 2016 (Single Translation Unit) - use cert-cpp-single-translation-unit.qls instead" +- import: codeql-suites/cert-cpp-single-translation-unit.qls \ No newline at end of file diff --git a/cpp/cert/src/qlpack.yml b/cpp/cert/src/qlpack.yml index f44646cdbe..97976d30cd 100644 --- a/cpp/cert/src/qlpack.yml +++ b/cpp/cert/src/qlpack.yml @@ -3,6 +3,7 @@ version: 2.44.0-dev description: CERT C++ 2016 suites: codeql-suites license: MIT +default-suite-file: codeql-suites/cert-cpp-default.qls dependencies: codeql/cpp-all: 2.1.1 codeql/common-cpp-coding-standards: '*' From 8843822ec1b46b0a913edfc5a5f7372d1e4752a8 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 10 Apr 2025 08:45:07 -0700 Subject: [PATCH 291/370] Add 'recommendation' to CERT schema --- schemas/rule-package.schema.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/schemas/rule-package.schema.json b/schemas/rule-package.schema.json index b4f729afe2..f9f65d679c 100644 --- a/schemas/rule-package.schema.json +++ b/schemas/rule-package.schema.json @@ -94,7 +94,8 @@ "obligation": { "type": "string", "enum": [ - "rule" + "rule", + "recommendation" ] } }, From d39ec8d75696f4d5ee0493f97b55102f47d5da52 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 10 Apr 2025 09:25:26 -0700 Subject: [PATCH 292/370] Fix, move 'recommendation' from CERT-C++ to CERT-C in schema --- schemas/rule-package.schema.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/schemas/rule-package.schema.json b/schemas/rule-package.schema.json index f9f65d679c..f8c3f028e3 100644 --- a/schemas/rule-package.schema.json +++ b/schemas/rule-package.schema.json @@ -94,8 +94,7 @@ "obligation": { "type": "string", "enum": [ - "rule", - "recommendation" + "rule" ] } }, @@ -142,7 +141,8 @@ "obligation": { "type": "string", "enum": [ - "rule" + "rule", + "recommendation" ] } }, From 14bd93788a59b7265a730626fe44178b0f56d8a1 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 30 Mar 2025 18:30:36 -0700 Subject: [PATCH 293/370] Update cert-help-extraction.py to support CERT-C optional (recommendation) rules --- scripts/help/cert-help-extraction.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/scripts/help/cert-help-extraction.py b/scripts/help/cert-help-extraction.py index 6bd1abccd5..f785b0955f 100755 --- a/scripts/help/cert-help-extraction.py +++ b/scripts/help/cert-help-extraction.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 from argparse import ArgumentParser +from typing import Generator import tempfile import re import urllib.request @@ -23,6 +24,7 @@ CERT_WIKI = "https://wiki.sei.cmu.edu" RULES_LIST_C = "/confluence/display/c/2+Rules" +RECOMMENDED_LIST_C = "/confluence/display/c/3+Recommendations" RULES_LIST_CPP = "/confluence/display/cplusplus/2+Rules" cache_path = script_path.parent / '.cache' @@ -47,16 +49,22 @@ def soupify(url: str) -> BeautifulSoup: return BeautifulSoup(content, 'html.parser') - -def get_rules(): - rules = [] - for soup in [soupify(f"{CERT_WIKI}{RULES_LIST_C}"), soupify(f"{CERT_WIKI}{RULES_LIST_CPP}")]: +def get_rule_listings() -> Generator[Tag, None, None]: + for rule_list_id in [RULES_LIST_C, RULES_LIST_CPP]: + soup = soupify(f"{CERT_WIKI}{rule_list_id}") if soup == None: - return None - - rule_listing_start = soup.find( + continue + + yield soup.find( "h1", string="Rule Listing") + soup = soupify(f"{CERT_WIKI}{RECOMMENDED_LIST_C}") + if soup != None: + yield soup.find("h1", string="Recommendation Listing") + +def get_rules(): + rules = [] + for rule_listing_start in get_rule_listings(): for link in rule_listing_start.next_element.next_element.find_all('a'): if '-C' in link.string: rule, title = map(str.strip, link.string.split('.', 1)) @@ -214,6 +222,8 @@ def helper(node): # Fix a broken url present in many CERT-C pages if node.name == 'a' and 'href' in node.attrs and node['href'] == "http://BB. Definitions#vulnerability": node['href'] = "https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-vulnerability" + elif node.name == 'a' and 'href' in node.attrs and node['href'] == "http://BB. Definitions#unexpected behavior": + node['href'] = "https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-unexpectedbehavior" # Turn relative URLs into absolute URLS elif node.name == 'a' and 'href' in node.attrs and node['href'].startswith("/confluence"): node['href'] = f"{CERT_WIKI}{node['href']}" From d2e638eedab86f076b1cbd04cd81383e09cb5611 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 30 Mar 2025 18:27:49 -0700 Subject: [PATCH 294/370] Implement expressions2 package --- ...CompareFunctionPointersToConstantValues.md | 129 ++++++++++++++++++ ...CompareFunctionPointersToConstantValues.ql | 101 ++++++++++++++ ...eFunctionPointersToConstantValues.expected | 16 +++ ...pareFunctionPointersToConstantValues.qlref | 1 + c/cert/test/rules/EXP16-C/test.c | 113 +++++++++++++++ .../cpp/exclusions/c/Expressions2.qll | 26 ++++ .../cpp/exclusions/c/RuleMetadata.qll | 3 + .../codingstandards/cpp/types/Compatible.qll | 19 +-- .../cpp/types/FunctionType.qll | 19 +++ rule_packages/c/Expressions2.json | 23 ++++ 10 files changed, 432 insertions(+), 18 deletions(-) create mode 100644 c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.md create mode 100644 c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql create mode 100644 c/cert/test/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.expected create mode 100644 c/cert/test/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.qlref create mode 100644 c/cert/test/rules/EXP16-C/test.c create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/c/Expressions2.qll create mode 100644 cpp/common/src/codingstandards/cpp/types/FunctionType.qll create mode 100644 rule_packages/c/Expressions2.json diff --git a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.md b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.md new file mode 100644 index 0000000000..b5a7c98bd6 --- /dev/null +++ b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.md @@ -0,0 +1,129 @@ +# EXP16-C: Do not compare function pointers to constant values + +This query implements the CERT-C rule EXP16-C: + +> Do not compare function pointers to constant values + + +## Description + +Comparing a function pointer to a value that is not a null function pointer of the same type will be diagnosed because it typically indicates programmer error and can result in [unexpected behavior](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-unexpectedbehavior). Implicit comparisons will be diagnosed, as well. + +## Noncompliant Code Example + +In this noncompliant code example, the addresses of the POSIX functions `getuid` and `geteuid` are compared for equality to 0. Because no function address shall be null, the first subexpression will always evaluate to false (0), and the second subexpression always to true (nonzero). Consequently, the entire expression will always evaluate to true, leading to a potential security vulnerability. + +```cpp +/* First the options that are allowed only for root */ +if (getuid == 0 || geteuid != 0) { + /* ... */ +} + +``` + +## Noncompliant Code Example + +In this noncompliant code example, the function pointers `getuid` and `geteuid` are compared to 0. This example is from an actual [vulnerability](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-vulnerability) ([VU\#837857](http://www.kb.cert.org/vuls/id/837857)) discovered in some versions of the X Window System server. The vulnerability exists because the programmer neglected to provide the open and close parentheses following the `geteuid()` function identifier. As a result, the `geteuid` token returns the address of the function, which is never equal to 0. Consequently, the `or` condition of this `if` statement is always true, and access is provided to the protected block for all users. Many compilers issue a warning noting such pointless expressions. Therefore, this coding error is normally detected by adherence to [MSC00-C. Compile cleanly at high warning levels](https://wiki.sei.cmu.edu/confluence/display/c/MSC00-C.+Compile+cleanly+at+high+warning+levels). + +```cpp +/* First the options that are allowed only for root */ +if (getuid() == 0 || geteuid != 0) { + /* ... */ +} + +``` + +## Compliant Solution + +The solution is to provide the open and close parentheses following the `geteuid` token so that the function is properly invoked: + +```cpp +/* First the options that are allowed only for root */ +if (getuid() == 0 || geteuid() != 0) { + /* ... */ +} + +``` + +## Compliant Solution + +A function pointer can be compared to a null function pointer of the same type: + +```cpp +/* First the options that are allowed only for root */ +if (getuid == (uid_t(*)(void))0 || geteuid != (uid_t(*)(void))0) { + /* ... */ +} + +``` +This code should not be diagnosed by an analyzer. + +## Noncompliant Code Example + +In this noncompliant code example, the function pointer `do_xyz` is implicitly compared unequal to 0: + +```cpp +int do_xyz(void); + +int f(void) { +/* ... */ + if (do_xyz) { + return -1; /* Indicate failure */ + } +/* ... */ + return 0; +} + +``` + +## Compliant Solution + +In this compliant solution, the function `do_xyz()` is invoked and the return value is compared to 0: + +```cpp +int do_xyz(void); + +int f(void) { +/* ... */ + if (do_xyz()) { + return -1; /* Indicate failure */ + } +/* ... */ + return 0; +} + +``` + +## Risk Assessment + +Errors of omission can result in unintended program flow. + +
    Recommendation Severity Likelihood Remediation Cost Priority Level
    EXP16-C Low Likely Medium P6 L2
    + + +## Automated Detection + +
    Tool Version Checker Description
    Astrée 24.04 function-name-constant-comparison Partially checked
    Coverity 2017.07 BAD_COMPARE Can detect the specific instance where the address of a function is compared against 0, such as in the case of geteuid versus getuid() in the implementation-specific details
    GCC 4.3.5 Can detect violations of this recommendation when the -Wall flag is used
    Helix QAC 2024.4 C0428, C3004, C3344
    Klocwork 2024.4 CWARN.NULLCHECK.FUNCNAMECWARN.FUNCADDR
    LDRA tool suite 9.7.1 99 S Partially implemented
    Parasoft C/C++test 2024.2 CERT_C-EXP16-a Function address should not be compared to zero
    PC-lint Plus 1.4 2440, 2441 Partially supported: reports address of function, array, or variable directly or indirectly compared to null
    PVS-Studio 7.35 V516, V1058
    RuleChecker 24.04 function-name-constant-comparison Partially checked
    + + +## Related Vulnerabilities + +Search for [vulnerabilities](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-vulnerability) resulting from the violation of this rule on the [CERT website](https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+EXP16-C). + +## Related Guidelines + +
    SEI CERT C++ Coding Standard VOID EXP16-CPP. Avoid conversions using void pointers
    ISO/IEC TR 24772:2013 Likely incorrect expressions \[KOA\]
    ISO/IEC TS 17961 Comparing function addresses to zero \[funcaddr\]
    MITRE CWE CWE-480 , Use of incorrect operator CWE-482 , Comparing instead of assigning
    + + +## Bibliography + +
    \[ Hatton 1995 \] Section 2.7.2, "Errors of Omission and Addition"
    + + +## Implementation notes + +None + +## References + +* CERT-C: [EXP16-C: Do not compare function pointers to constant values](https://wiki.sei.cmu.edu/confluence/display/c) diff --git a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql new file mode 100644 index 0000000000..561374d66b --- /dev/null +++ b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql @@ -0,0 +1,101 @@ +/** + * @id c/cert/do-not-compare-function-pointers-to-constant-values + * @name EXP16-C: Do not compare function pointers to constant values + * @description Comparing function pointers to a constant value is not reliable and likely indicates + * a programmer error. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/cert/id/exp16-c + * correctness + * external/cert/obligation/rule + */ + +import cpp +import codingstandards.c.cert +import codingstandards.cpp.types.FunctionType +import semmle.code.cpp.controlflow.IRGuards + +class FunctionExpr extends Expr { + Element function; + string funcName; + + FunctionExpr() { + function = this.(FunctionAccess).getTarget() and + funcName = "Function " + function.(Function).getName() + or + this.(VariableAccess).getUnderlyingType() instanceof FunctionType and + function = this and + funcName = "Function pointer variable " + this.(VariableAccess).getTarget().getName() + or + this.getUnderlyingType() instanceof FunctionType and + not this instanceof FunctionAccess and + not this instanceof VariableAccess and + function = this and + funcName = "Expression with function pointer type" + } + + Element getFunction() { result = function } + + string getFuncName() { result = funcName } +} + +abstract class EffectivelyComparison extends Element { + abstract string getExplanation(); + + abstract FunctionExpr getFunctionExpr(); +} + +class ExplicitComparison extends EffectivelyComparison, ComparisonOperation { + Expr constantExpr; + FunctionExpr funcExpr; + + ExplicitComparison() { + funcExpr = getAnOperand() and + constantExpr = getAnOperand() and + exists(constantExpr.getValue()) and + not funcExpr = constantExpr and + not constantExpr.getExplicitlyConverted().getUnderlyingType() = + funcExpr.getExplicitlyConverted().getUnderlyingType() + } + + override string getExplanation() { result = "$@ compared to constant value." } + + override FunctionExpr getFunctionExpr() { result = funcExpr } +} + +class ImplicitComparison extends EffectivelyComparison, GuardCondition { + ImplicitComparison() { + this instanceof FunctionExpr and + not getParent() instanceof ComparisonOperation + } + + override string getExplanation() { result = "$@ undergoes implicit constant comparison." } + + override FunctionExpr getFunctionExpr() { result = this } +} + +from EffectivelyComparison comparison, FunctionExpr funcExpr, Element function, string funcName +where + not isExcluded(comparison, + Expressions2Package::doNotCompareFunctionPointersToConstantValuesQuery()) and + funcExpr = comparison.getFunctionExpr() and + function = funcExpr.getFunction() and + funcName = funcExpr.getFuncName() +select comparison, comparison.getExplanation(), function, funcName +//from +// EqualityOperation equality, FunctionExpr funcExpr, Element function, string funcName, +// Expr constantExpr +//where +// not isExcluded(equality, Expressions2Package::doNotCompareFunctionPointersToConstantValuesQuery()) and +// funcExpr = equality.getAnOperand() and +// constantExpr = equality.getAnOperand() and +// exists(constantExpr.getValue()) and +// function = funcExpr.getFunction() and +// funcName = funcExpr.getFuncName() and +// constantExpr.getFullyConverted().getUnderlyingType() = +// funcExpr.getFullyConverted().getUnderlyingType() +//select equality, +// "Pointer to function $@ compared to constant value." + +// constantExpr.getFullyConverted().getUnderlyingType().explain() + " / " + +// funcExpr.getFullyConverted().getUnderlyingType().explain(), function, funcName diff --git a/c/cert/test/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.expected b/c/cert/test/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.expected new file mode 100644 index 0000000000..a18f0d32f6 --- /dev/null +++ b/c/cert/test/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.expected @@ -0,0 +1,16 @@ +| test.c:17:7:17:13 | ... == ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Function f1 | +| test.c:20:7:20:12 | ... > ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Function f1 | +| test.c:29:7:29:13 | ... == ... | $@ compared to constant value. | test.c:29:7:29:8 | g1 | Function pointer variable g1 | +| test.c:32:7:32:16 | ... == ... | $@ compared to constant value. | test.c:32:7:32:8 | g2 | Function pointer variable g2 | +| test.c:35:7:35:15 | ... != ... | $@ compared to constant value. | test.c:35:7:35:8 | g1 | Function pointer variable g1 | +| test.c:38:7:38:8 | f1 | $@ undergoes implicit constant comparison. | test.c:3:5:3:6 | f1 | Function f1 | +| test.c:41:7:41:8 | g1 | $@ undergoes implicit constant comparison. | test.c:41:7:41:8 | g1 | Function pointer variable g1 | +| test.c:68:7:68:27 | ... == ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Function f1 | +| test.c:71:7:71:18 | ... == ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Function f1 | +| test.c:74:7:76:14 | ... == ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Function f1 | +| test.c:83:3:83:9 | ... == ... | $@ compared to constant value. | test.c:83:3:83:4 | l1 | Function pointer variable l1 | +| test.c:84:3:84:12 | ... == ... | $@ compared to constant value. | test.c:84:3:84:4 | l1 | Function pointer variable l1 | +| test.c:91:3:91:4 | g1 | $@ undergoes implicit constant comparison. | test.c:91:3:91:4 | g1 | Function pointer variable g1 | +| test.c:96:7:96:18 | ... == ... | $@ compared to constant value. | test.c:96:9:96:10 | fp | Function pointer variable fp | +| test.c:102:7:102:22 | ... == ... | $@ compared to constant value. | test.c:14:11:14:21 | get_handler | Function get_handler | +| test.c:105:7:105:24 | ... == ... | $@ compared to constant value. | test.c:105:7:105:17 | call to get_handler | Expression with function pointer type | diff --git a/c/cert/test/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.qlref b/c/cert/test/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.qlref new file mode 100644 index 0000000000..7d99fa9879 --- /dev/null +++ b/c/cert/test/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.qlref @@ -0,0 +1 @@ +rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql \ No newline at end of file diff --git a/c/cert/test/rules/EXP16-C/test.c b/c/cert/test/rules/EXP16-C/test.c new file mode 100644 index 0000000000..afc1b1b53e --- /dev/null +++ b/c/cert/test/rules/EXP16-C/test.c @@ -0,0 +1,113 @@ +#include + +int f1(); +void (*g1)(void); +int (*g2)(int); +void *g3 = NULL; + +struct S { + int (*fp)(void); + int x; +}; + +typedef int (*handler_t)(void); +handler_t get_handler(void); + +void f2(void) { + if (f1 == 0) // NON-COMPLIANT + return; + + if (f1 > 0) // NON-COMPLIANT + return; + + if (f1() == 0) // COMPLIANT + return; + + if (f1() > 0) // COMPLIANT + return; + + if (g1 == 0) // NON-COMPLIANT + return; + + if (g2 == NULL) // NON-COMPLIANT + return; + + if (g1 != 0x0) // NON-COMPLIANT + return; + + if (f1) // NON-COMPLIANT - implicit comparison + return; + + if (g1) // NON-COMPLIANT - implicit comparison + return; +} + +void f3(void *p1) { + if (g1 == p1) // COMPLIANT - comparing to variable + return; + + if (g2 == g3) // COMPLIANT - comparing to variable + return; +} + +void f4(void) { + int (*l1)(void) = 0; + + if (f1 == f1) // COMPLIANT - comparing to constant value of same type + return; + + if (f1 == l1) // COMPLIANT - comparing to constant value of same type + return; + + if (f1 == (int (*)(void))0) // COMPLIANT - explicit cast + return; + + if (f1 == (int (*)(void))0) // COMPLIANT - explicit cast + return; + + if (f1 == (int (*)(int))0) // NON-COMPLIANT - explicit cast to wrong type + return; + + if (f1 == (int)0) // NON-COMPLIANT - cast to non-function pointer type + return; + + if (f1 == + (int)(int (*)(void)) + NULL) // NON-COMPLIANT - compliant cast subsumed by non-compliant cast + return; +} + +typedef void (*func_t)(void); +void f5(void) { + func_t l1 = g1; + l1 == 0; // NON-COMPLIANT + l1 == NULL; // NON-COMPLIANT + l1 == (func_t)0; // COMPLIANT - cast to function pointer type +} + +void f6(void) { + g1 + 0; // COMPLIANT - not a comparison + g1 == g2; // COMPLIANT - not comparing to constant + g1 ? 1 : 0; // NON-COMPLIANT - implicit comparison +} + +void f7(void) { + struct S s; + if (s.fp == NULL) // NON-COMPLIANT + return; + + if (s.fp() == NULL) // COMPLIANT + return; + + if (get_handler == 0) // NON-COMPLIANT - missing parentheses + return; + + if (get_handler() == 0) // NON-COMPLIANT + return; + + if (get_handler() == (handler_t)0) // COMPLIANT + return; + + if (get_handler()() == 0) // COMPLIANT + return; +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Expressions2.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Expressions2.qll new file mode 100644 index 0000000000..cc22a5ce02 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Expressions2.qll @@ -0,0 +1,26 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype Expressions2Query = TDoNotCompareFunctionPointersToConstantValuesQuery() + +predicate isExpressions2QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `doNotCompareFunctionPointersToConstantValues` query + Expressions2Package::doNotCompareFunctionPointersToConstantValuesQuery() and + queryId = + // `@id` for the `doNotCompareFunctionPointersToConstantValues` query + "c/cert/do-not-compare-function-pointers-to-constant-values" and + ruleId = "EXP16-C" and + category = "rule" +} + +module Expressions2Package { + Query doNotCompareFunctionPointersToConstantValuesQuery() { + //autogenerate `Query` type + result = + // `Query` type for `doNotCompareFunctionPointersToConstantValues` query + TQueryC(TExpressions2PackageQuery(TDoNotCompareFunctionPointersToConstantValuesQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index ae035b9c5d..b574f7551c 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -38,6 +38,7 @@ import Declarations9 import EssentialTypes import EssentialTypes2 import Expressions +import Expressions2 import FloatingTypes import FloatingTypes2 import FunctionTypes @@ -127,6 +128,7 @@ newtype TCQuery = TEssentialTypesPackageQuery(EssentialTypesQuery q) or TEssentialTypes2PackageQuery(EssentialTypes2Query q) or TExpressionsPackageQuery(ExpressionsQuery q) or + TExpressions2PackageQuery(Expressions2Query q) or TFloatingTypesPackageQuery(FloatingTypesQuery q) or TFloatingTypes2PackageQuery(FloatingTypes2Query q) or TFunctionTypesPackageQuery(FunctionTypesQuery q) or @@ -216,6 +218,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isEssentialTypesQueryMetadata(query, queryId, ruleId, category) or isEssentialTypes2QueryMetadata(query, queryId, ruleId, category) or isExpressionsQueryMetadata(query, queryId, ruleId, category) or + isExpressions2QueryMetadata(query, queryId, ruleId, category) or isFloatingTypesQueryMetadata(query, queryId, ruleId, category) or isFloatingTypes2QueryMetadata(query, queryId, ruleId, category) or isFunctionTypesQueryMetadata(query, queryId, ruleId, category) or diff --git a/cpp/common/src/codingstandards/cpp/types/Compatible.qll b/cpp/common/src/codingstandards/cpp/types/Compatible.qll index d6f65126e8..56966b5772 100644 --- a/cpp/common/src/codingstandards/cpp/types/Compatible.qll +++ b/cpp/common/src/codingstandards/cpp/types/Compatible.qll @@ -1,6 +1,7 @@ import cpp import codeql.util.Boolean import codingstandards.cpp.types.Graph +import codingstandards.cpp.types.FunctionType module TypeNamesMatchConfig implements TypeEquivalenceSig { predicate resolveTypedefs() { @@ -352,21 +353,3 @@ module FunctionDeclarationTypeEquivalence { ) } } - -/** - * Convenience class to reduce the awkwardness of how `RoutineType` and `FunctionPointerIshType` - * don't have a common ancestor. - */ -private class FunctionType extends Type { - FunctionType() { this instanceof RoutineType or this instanceof FunctionPointerIshType } - - Type getReturnType() { - result = this.(RoutineType).getReturnType() or - result = this.(FunctionPointerIshType).getReturnType() - } - - Type getParameterType(int i) { - result = this.(RoutineType).getParameterType(i) or - result = this.(FunctionPointerIshType).getParameterType(i) - } -} diff --git a/cpp/common/src/codingstandards/cpp/types/FunctionType.qll b/cpp/common/src/codingstandards/cpp/types/FunctionType.qll new file mode 100644 index 0000000000..e43d1067f1 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/types/FunctionType.qll @@ -0,0 +1,19 @@ +import cpp + +/** + * Convenience class to reduce the awkwardness of how `RoutineType` and `FunctionPointerIshType` + * don't have a common ancestor. + */ +class FunctionType extends Type { + FunctionType() { this instanceof RoutineType or this instanceof FunctionPointerIshType } + + Type getReturnType() { + result = this.(RoutineType).getReturnType() or + result = this.(FunctionPointerIshType).getReturnType() + } + + Type getParameterType(int i) { + result = this.(RoutineType).getParameterType(i) or + result = this.(FunctionPointerIshType).getParameterType(i) + } +} \ No newline at end of file diff --git a/rule_packages/c/Expressions2.json b/rule_packages/c/Expressions2.json new file mode 100644 index 0000000000..88b5dff988 --- /dev/null +++ b/rule_packages/c/Expressions2.json @@ -0,0 +1,23 @@ +{ + "CERT-C": { + "EXP16-C": { + "properties": { + "obligation": "rule" + }, + "queries": [ + { + "description": "Comparing function pointers to a constant value is not reliable and likely indicates a programmer error.", + "kind": "problem", + "name": "Do not compare function pointers to constant values", + "precision": "very-high", + "severity": "error", + "short_name": "DoNotCompareFunctionPointersToConstantValues", + "tags": [ + "correctness" + ] + } + ], + "title": "Do not compare function pointers to constant values" + } + } +} \ No newline at end of file From f6d62ecf55ec81dec636c3ce3d9fa2ead440aa3e Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 31 Mar 2025 13:09:44 -0700 Subject: [PATCH 295/370] Format --- cpp/common/src/codingstandards/cpp/types/FunctionType.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/types/FunctionType.qll b/cpp/common/src/codingstandards/cpp/types/FunctionType.qll index e43d1067f1..20166322f1 100644 --- a/cpp/common/src/codingstandards/cpp/types/FunctionType.qll +++ b/cpp/common/src/codingstandards/cpp/types/FunctionType.qll @@ -16,4 +16,4 @@ class FunctionType extends Type { result = this.(RoutineType).getParameterType(i) or result = this.(FunctionPointerIshType).getParameterType(i) } -} \ No newline at end of file +} From 067e1724a04df9eaaad348c4886a72e3276c9bd1 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 9 Apr 2025 20:39:32 -0700 Subject: [PATCH 296/370] Change obligation --- .../EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql | 2 +- .../src/codingstandards/cpp/exclusions/c/Expressions2.qll | 2 +- rule_packages/c/Expressions2.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql index 561374d66b..88beae6bc0 100644 --- a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql +++ b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql @@ -8,7 +8,7 @@ * @problem.severity error * @tags external/cert/id/exp16-c * correctness - * external/cert/obligation/rule + * external/cert/obligation/recommendation */ import cpp diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Expressions2.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Expressions2.qll index cc22a5ce02..e7dffc30bb 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/Expressions2.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Expressions2.qll @@ -13,7 +13,7 @@ predicate isExpressions2QueryMetadata(Query query, string queryId, string ruleId // `@id` for the `doNotCompareFunctionPointersToConstantValues` query "c/cert/do-not-compare-function-pointers-to-constant-values" and ruleId = "EXP16-C" and - category = "rule" + category = "recommendation" } module Expressions2Package { diff --git a/rule_packages/c/Expressions2.json b/rule_packages/c/Expressions2.json index 88b5dff988..7eaa2ff2ec 100644 --- a/rule_packages/c/Expressions2.json +++ b/rule_packages/c/Expressions2.json @@ -2,7 +2,7 @@ "CERT-C": { "EXP16-C": { "properties": { - "obligation": "rule" + "obligation": "recommendation" }, "queries": [ { From 010b7c7d2b626dad88511d6292afc837eecd534d Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Wed, 9 Apr 2025 20:40:20 -0700 Subject: [PATCH 297/370] Remove commented out code --- ...NotCompareFunctionPointersToConstantValues.ql | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql index 88beae6bc0..d9622b03b9 100644 --- a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql +++ b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql @@ -83,19 +83,3 @@ where function = funcExpr.getFunction() and funcName = funcExpr.getFuncName() select comparison, comparison.getExplanation(), function, funcName -//from -// EqualityOperation equality, FunctionExpr funcExpr, Element function, string funcName, -// Expr constantExpr -//where -// not isExcluded(equality, Expressions2Package::doNotCompareFunctionPointersToConstantValuesQuery()) and -// funcExpr = equality.getAnOperand() and -// constantExpr = equality.getAnOperand() and -// exists(constantExpr.getValue()) and -// function = funcExpr.getFunction() and -// funcName = funcExpr.getFuncName() and -// constantExpr.getFullyConverted().getUnderlyingType() = -// funcExpr.getFullyConverted().getUnderlyingType() -//select equality, -// "Pointer to function $@ compared to constant value." + -// constantExpr.getFullyConverted().getUnderlyingType().explain() + " / " + -// funcExpr.getFullyConverted().getUnderlyingType().explain(), function, funcName From 65045370e3665cf3b15edcc044ddf5d81364bbce Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 15 Apr 2025 06:42:44 -0700 Subject: [PATCH 298/370] Implement package FloatingPoint --- ...suseOfInfiniteFloatingPointValue.expected} | 56 ++--- .../MisuseOfInfiniteFloatingPointValue.ql | 4 + .../test.c | 44 ++-- .../MisuseOfNaNFloatingPointValue.expected} | 68 +++--- .../MisuseOfNaNFloatingPointValue.ql | 4 + .../misuseofnanfloatingpointvalue/test.c | 212 ++++++++++++++++++ .../PossibleMisuseOfUndetectedInfinity.ql | 127 +---------- .../DIR-4-15/PossibleMisuseOfUndetectedNaN.ql | 189 +--------------- ...PossibleMisuseOfUndetectedInfinity.testref | 1 + .../PossibleMisuseOfUndetectedNaN.testref | 1 + ...025-04-14-update-infinity-nan-detection.md | 4 + .../src/codingstandards/cpp/FloatingPoint.qll | 3 +- .../cpp/RestrictedRangeAnalysis.qll | 3 +- .../cpp/exclusions/cpp/FloatingPoint.qll | 44 ++++ .../cpp/exclusions/cpp/RuleMetadata.qll | 3 + .../MisuseOfInfiniteFloatingPointValue.qll | 141 ++++++++++++ .../MisuseOfNaNFloatingPointValue.qll | 201 +++++++++++++++++ .../test/includes/standard-library/cmath | 19 ++ .../test/includes/standard-library/math.h | 6 + ...isuseOfInfiniteFloatingPointValue.expected | 113 ++++++++++ .../MisuseOfInfiniteFloatingPointValue.ql | 4 + .../test.cpp | 212 ++++++++++++++++++ .../MisuseOfNaNFloatingPointValue.expected | 136 +++++++++++ .../MisuseOfNaNFloatingPointValue.ql | 4 + .../misuseofnanfloatingpointvalue/test.cpp | 212 ++++++++++++++++++ ...sibleMisuseOfInfiniteFloatingPointValue.ql | 22 ++ .../PossibleMisuseOfNaNFloatingPointValue.ql | 23 ++ ...MisuseOfInfiniteFloatingPointValue.testref | 1 + ...sibleMisuseOfNaNFloatingPointValue.testref | 1 + rule_packages/c/FloatingTypes2.json | 2 + rule_packages/cpp/FloatingPoint.json | 38 ++++ 31 files changed, 1505 insertions(+), 393 deletions(-) rename c/{misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected => common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.expected} (99%) create mode 100644 c/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.ql rename c/{misra/test/rules/DIR-4-15 => common/test/rules/misuseofinfinitefloatingpointvalue}/test.c (82%) rename c/{misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected => common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected} (99%) create mode 100644 c/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.ql create mode 100644 c/common/test/rules/misuseofnanfloatingpointvalue/test.c create mode 100644 c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.testref create mode 100644 c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.testref create mode 100644 change_notes/2025-04-14-update-infinity-nan-detection.md create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/cpp/FloatingPoint.qll create mode 100644 cpp/common/src/codingstandards/cpp/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.qll create mode 100644 cpp/common/src/codingstandards/cpp/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.qll create mode 100644 cpp/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.expected create mode 100644 cpp/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.ql create mode 100644 cpp/common/test/rules/misuseofinfinitefloatingpointvalue/test.cpp create mode 100644 cpp/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected create mode 100644 cpp/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.ql create mode 100644 cpp/common/test/rules/misuseofnanfloatingpointvalue/test.cpp create mode 100644 cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.ql create mode 100644 cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfNaNFloatingPointValue.ql create mode 100644 cpp/misra/test/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.testref create mode 100644 cpp/misra/test/rules/DIR-0-3-1/PossibleMisuseOfNaNFloatingPointValue.testref create mode 100644 rule_packages/cpp/FloatingPoint.json diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected b/c/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.expected similarity index 99% rename from c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected rename to c/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.expected index 8dd5ac15b8..f3b94b6095 100644 --- a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.expected +++ b/c/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.expected @@ -1,3 +1,30 @@ +problems +| test.c:12:8:12:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:12:8:12:9 | l2 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:13:8:13:9 | l3 | test.c:8:14:8:20 | ... / ... | test.c:13:8:13:9 | l3 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:18:8:18:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:18:3:18:9 | l2 | Possibly infinite float value $@ flows to cast to integer. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:19:8:19:9 | l3 | test.c:8:14:8:20 | ... / ... | test.c:19:3:19:9 | l3 | Possibly infinite float value $@ flows to cast to integer. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:27:19:27:20 | l2 | test.c:8:14:8:20 | ... / ... | test.c:27:19:27:20 | l2 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:28:19:28:20 | l3 | test.c:8:14:8:20 | ... / ... | test.c:28:19:28:20 | l3 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:38:8:38:9 | l7 | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | Possibly infinite float value $@ flows to cast to integer. | test.c:31:14:32:15 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:61:11:61:17 | ... / ... | test.c:61:5:61:18 | ... / ... | test.c:61:5:61:18 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.c:61:11:61:17 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:66:11:66:19 | ... / ... | test.c:66:5:66:20 | ... / ... | test.c:66:5:66:20 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.c:66:11:66:19 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:72:20:72:28 | ... / ... | test.c:72:14:72:29 | ... / ... | test.c:72:14:72:29 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.c:72:20:72:28 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:75:24:75:32 | ... / ... | test.c:75:18:75:33 | ... / ... | test.c:75:18:75:33 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.c:75:24:75:32 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:79:10:79:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:79:5:79:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:87:10:87:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:87:5:87:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:91:10:91:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:91:5:91:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:93:10:93:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:93:5:93:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:99:10:99:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:99:5:99:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:105:10:105:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:105:5:105:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:111:10:111:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:111:5:111:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:114:21:114:23 | l12 | test.c:77:15:77:21 | ... / ... | test.c:114:16:114:23 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:117:28:117:30 | l12 | test.c:77:15:77:21 | ... / ... | test.c:117:23:117:30 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:120:25:120:27 | l12 | test.c:77:15:77:21 | ... / ... | test.c:120:20:120:27 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:163:9:164:15 | ... / ... | test.c:163:3:164:16 | ... / ... | test.c:163:3:164:16 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.c:163:9:164:15 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:175:32:175:32 | p | test.c:189:51:189:59 | ... / ... | test.c:175:27:175:32 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.c:189:51:189:59 | ... / ... | from division by zero | test.c:189:6:189:24 | addInfThenCastToInt | addInfThenCastToInt | +| test.c:175:32:175:32 | p | test.c:193:13:194:15 | ... / ... | test.c:175:27:175:32 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.c:193:13:194:15 | ... / ... | from division by zero | test.c:192:6:192:7 | f2 | f2 | +| test.c:175:32:175:32 | p | test.c:204:19:204:27 | ... / ... | test.c:175:27:175:32 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.c:204:19:204:27 | ... / ... | from division by zero | test.c:192:6:192:7 | f2 | f2 | +| test.c:185:18:185:18 | p | test.c:200:25:200:33 | ... / ... | test.c:185:13:185:18 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.c:200:25:200:33 | ... / ... | from division by zero | test.c:192:6:192:7 | f2 | f2 | edges | test.c:8:14:8:20 | ... / ... | test.c:8:14:8:20 | ... / ... | provenance | | | test.c:8:14:8:20 | ... / ... | test.c:9:14:9:16 | - ... | provenance | Config | @@ -83,31 +110,4 @@ nodes | test.c:206:21:206:31 | ... + ... | semmle.label | ... + ... | | test.c:208:13:208:21 | middleInf | semmle.label | middleInf | | test.c:210:23:210:31 | middleInf | semmle.label | middleInf | -subpaths -#select -| test.c:12:8:12:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:12:8:12:9 | l2 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:13:8:13:9 | l3 | test.c:8:14:8:20 | ... / ... | test.c:13:8:13:9 | l3 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:18:8:18:9 | l2 | test.c:8:14:8:20 | ... / ... | test.c:18:3:18:9 | l2 | Possibly infinite float value $@ flows to cast to integer. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:19:8:19:9 | l3 | test.c:8:14:8:20 | ... / ... | test.c:19:3:19:9 | l3 | Possibly infinite float value $@ flows to cast to integer. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:27:19:27:20 | l2 | test.c:8:14:8:20 | ... / ... | test.c:27:19:27:20 | l2 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:28:19:28:20 | l3 | test.c:8:14:8:20 | ... / ... | test.c:28:19:28:20 | l3 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.c:8:14:8:20 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:38:8:38:9 | l7 | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | Possibly infinite float value $@ flows to cast to integer. | test.c:31:14:32:15 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:61:11:61:17 | ... / ... | test.c:61:5:61:18 | ... / ... | test.c:61:5:61:18 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.c:61:11:61:17 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:66:11:66:19 | ... / ... | test.c:66:5:66:20 | ... / ... | test.c:66:5:66:20 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.c:66:11:66:19 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:72:20:72:28 | ... / ... | test.c:72:14:72:29 | ... / ... | test.c:72:14:72:29 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.c:72:20:72:28 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:75:24:75:32 | ... / ... | test.c:75:18:75:33 | ... / ... | test.c:75:18:75:33 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.c:75:24:75:32 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:79:10:79:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:79:5:79:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:87:10:87:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:87:5:87:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:91:10:91:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:91:5:91:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:93:10:93:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:93:5:93:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:99:10:99:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:99:5:99:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:105:10:105:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:105:5:105:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:111:10:111:12 | l12 | test.c:77:15:77:21 | ... / ... | test.c:111:5:111:12 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:114:21:114:23 | l12 | test.c:77:15:77:21 | ... / ... | test.c:114:16:114:23 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:117:28:117:30 | l12 | test.c:77:15:77:21 | ... / ... | test.c:117:23:117:30 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:120:25:120:27 | l12 | test.c:77:15:77:21 | ... / ... | test.c:120:20:120:27 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.c:77:15:77:21 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:163:9:164:15 | ... / ... | test.c:163:3:164:16 | ... / ... | test.c:163:3:164:16 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.c:163:9:164:15 | ... / ... | from division by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:175:32:175:32 | p | test.c:189:51:189:59 | ... / ... | test.c:175:27:175:32 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.c:189:51:189:59 | ... / ... | from division by zero | test.c:189:6:189:24 | addInfThenCastToInt | addInfThenCastToInt | -| test.c:175:32:175:32 | p | test.c:193:13:194:15 | ... / ... | test.c:175:27:175:32 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.c:193:13:194:15 | ... / ... | from division by zero | test.c:192:6:192:7 | f2 | f2 | -| test.c:175:32:175:32 | p | test.c:204:19:204:27 | ... / ... | test.c:175:27:175:32 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.c:204:19:204:27 | ... / ... | from division by zero | test.c:192:6:192:7 | f2 | f2 | -| test.c:185:18:185:18 | p | test.c:200:25:200:33 | ... / ... | test.c:185:13:185:18 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.c:200:25:200:33 | ... / ... | from division by zero | test.c:192:6:192:7 | f2 | f2 | +subpaths \ No newline at end of file diff --git a/c/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.ql b/c/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.ql new file mode 100644 index 0000000000..f0d160a650 --- /dev/null +++ b/c/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.ql @@ -0,0 +1,4 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.misuseofinfinitefloatingpointvalue.MisuseOfInfiniteFloatingPointValue + +class TestFileQuery extends MisuseOfInfiniteFloatingPointValueSharedQuery, TestQuery { } diff --git a/c/misra/test/rules/DIR-4-15/test.c b/c/common/test/rules/misuseofinfinitefloatingpointvalue/test.c similarity index 82% rename from c/misra/test/rules/DIR-4-15/test.c rename to c/common/test/rules/misuseofinfinitefloatingpointvalue/test.c index a827a7df97..85097d828b 100644 --- a/c/misra/test/rules/DIR-4-15/test.c +++ b/c/common/test/rules/misuseofinfinitefloatingpointvalue/test.c @@ -33,10 +33,10 @@ void f1(float p1) { float l8 = 0.0 / 0.0; (int)l4; // COMPLIANT - (int)l5; // NON_COMPLIANT: Casting NaN to int - (int)l6; // NON_COMPLIANT: Casting NaN to int - (int)l7; // NON_COMPLIANT: Casting NaN to int - (int)l8; // NON_COMPLIANT: Casting NaN to int + (int)l5; // COMPLIANT: Casting NaN to int + (int)l6; // COMPLIANT: Casting NaN to int + (int)l7; // NON_COMPLIANT: Casting Infinity to int + (int)l8; // COMPLIANT: Casting NaN to int l4 == 0; // COMPLIANT l4 != 0; // COMPLIANT @@ -58,21 +58,21 @@ void f1(float p1) { if (l9 != 0) { (int)(l9 / l9); // COMPLIANT: l9 is not zero } else { - (int)(l9 / l9); // NON_COMPLIANT: Guarded to not be NaN + (int)(l9 / l9); // NON_COMPLIANT[False positive]: Guarded to not be NaN } float l10 = 0; if (l10 == 0) { - (int)(l10 / l10); // NON_COMPLIANT: Casting NaN to integer + (int)(l10 / l10); // NON_COMPLIANT[False positive]: Casting NaN to integer } else { (int)(l10 / l10); // COMPLIANT: Guarded to not be NaN } float l11 = 0; - l11 == 0 ? (int)(l11 / l11) : 0; // NON_COMPLIANT + l11 == 0 ? (int)(l11 / l11) : 0; // NON_COMPLIANT[False positive] l11 == 0 ? 0 : (int)(l11 / l11); // COMPLIANT l11 != 0 ? (int)(l11 / l11) : 0; // COMPLIANT - l11 != 0 ? 0 : (int)(l11 / l11); // NON_COMPLIANT + l11 != 0 ? 0 : (int)(l11 / l11); // NON_COMPLIANT[False positive] float l12 = 1.0 / 0; if (isinf(l12)) { @@ -123,29 +123,29 @@ void f1(float p1) { if (isinf(l13)) { (int)l13; // COMPLIANT: Guarded not to be NaN } else { - (int)l13; // NON_COMPLIANT: Casting NaN to integer + (int)l13; // COMPLIANT: Casting NaN to integer } if (isinf(l13) == 1) { (int)l13; // COMPLIANT: Guarded not to be NaN (must be +Infinity) } else { - (int)l13; // NON_COMPLIANT: Casting NaN to integer + (int)l13; // COMPLIANT: Casting NaN to integer } if (isfinite(l13)) { (int)l13; // COMPLIANT: Guarded not to be NaN } else { - (int)l13; // NON_COMPLIANT: Casting NaN to integer + (int)l13; // COMPLIANT: Casting NaN to integer } if (isnormal(l13)) { (int)l13; // COMPLIANT: Guarded not to be NaN } else { - (int)l13; // NON_COMPLIANT: Casting NaN to integer + (int)l13; // COMPLIANT: Casting NaN to integer } if (isnan(l13)) { - (int)l13; // NON_COMPLIANT: Casting NaN to integer + (int)l13; // COMPLIANT: Casting NaN to integer } else { (int)l13; // COMPLIANT: Guarded not to be NaN } @@ -154,21 +154,21 @@ void f1(float p1) { : 0; // COMPLIANT: Checked infinite, therefore not NaN, before use isinf(l13) ? 0 : (int)l13; // COMPLIANT: Check on wrong branch isfinite(l13) ? (int)l13 : 0; // COMPLIANT: Checked finite before use - isfinite(l13) ? 0 : (int)l13; // NON_COMPLIANT: Checked on wrong branch - isnan(l13) ? (int)l13 : 0; // NON_COMPLIANT: Check on wrong branch + isfinite(l13) ? 0 : (int)l13; // COMPLIANT: Checked on wrong branch + isnan(l13) ? (int)l13 : 0; // COMPLIANT: Check on wrong branch isnan(l13) ? 0 : (int)l13; // COMPLIANT: Checked not NaN before use - (int)pow(2, p1); // NON_COMPLIANT: likely to be Infinity + (int)pow(2, p1); // NON_COMPLIANT[False negative]: likely to be Infinity (int)pow(2, sin(p1)); // COMPLIANT: not likely to be Infinity (int)(1 / sin(p1)); // NON_COMPLIANT: possible infinity from zero in denominator (int)(1 / log(p1)); // COMPLIANT: not possibly zero in denominator - (int)pow(p1, p1); // NON_COMPLIANT: NaN if p1 is zero + (int)pow(p1, p1); // COMPLIANT: NaN if p1 is zero if (p1 != 0) { (int)pow(p1, p1); // COMPLIANT: p1 is not zero } - (int)acos(p1); // NON_COMPLIANT: NaN if p1 is not within -1..1 + (int)acos(p1); // COMPLIANT: NaN if p1 is not within -1..1 (int)acos(cos(p1)); // COMPLIANT: cos(p1) is within -1..1 } @@ -192,13 +192,13 @@ void addNaNThenCastToInt(float p) { castToInt(p + 0.0 / 0.0); } void f2() { castToInt(1.0 / 0.0); // NON_COMPLIANT: Infinity flows to denominator in division - castToInt(0.0 / 0.0); // NON_COMPLIANT: NaN flows to denominator in division + castToInt(0.0 / 0.0); // COMPLIANT checkBeforeCastToInt(1.0 / 0.0); // COMPLIANT checkBeforeCastToInt(0.0 / 0.0); // COMPLIANT addOneThenCastToInt(1.0 / 0.0); // NON_COMPLIANT[False negative] addOneThenCastToInt(0.0 / 0.0); // NON_COMPLIANT castToIntToFloatToInt(1.0 / 0.0); // NON_COMPLIANT - castToIntToFloatToInt(0.0 / 0.0); // NON_COMPLIANT + castToIntToFloatToInt(0.0 / 0.0); // COMPLIANT // Check that during flow analysis, we only report the true root cause: float rootInf = 1.0 / 0.0; @@ -206,7 +206,7 @@ void f2() { float middleInf = rootInf + 1; float middleNaN = rootNaN + 1; castToInt(middleInf); // NON_COMPLIANT - castToInt(middleNaN); // NON_COMPLIANT + castToInt(middleNaN); // COMPLIANT addInfThenCastToInt(middleInf); // NON_COMPLIANT - addNaNThenCastToInt(middleNaN); // NON_COMPLIANT + addNaNThenCastToInt(middleNaN); // COMPLIANT } \ No newline at end of file diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected b/c/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected similarity index 99% rename from c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected rename to c/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected index aeec3c943f..1555fd5bd8 100644 --- a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.expected +++ b/c/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected @@ -1,3 +1,36 @@ +problems +| test.c:36:8:36:9 | l5 | test.c:27:14:27:20 | ... / ... | test.c:36:3:36:9 | l5 | Possible NaN value $@ flows to a cast to integer. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:37:8:37:9 | l6 | test.c:28:14:28:20 | ... / ... | test.c:37:3:37:9 | l6 | Possible NaN value $@ flows to a cast to integer. | test.c:28:14:28:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:38:8:38:9 | l7 | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | Possible NaN value $@ flows to a cast to integer. | test.c:31:14:32:15 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:39:8:39:9 | l8 | test.c:33:14:33:22 | ... / ... | test.c:39:3:39:9 | l8 | Possible NaN value $@ flows to a cast to integer. | test.c:33:14:33:22 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:46:3:46:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:46:3:46:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:47:3:47:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:47:3:47:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:48:3:48:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:48:3:48:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:49:3:49:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:49:3:49:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:50:3:50:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:50:3:50:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:51:3:51:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:51:3:51:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:52:3:52:4 | l6 | test.c:28:14:28:20 | ... / ... | test.c:52:3:52:4 | l6 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:28:14:28:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | +| test.c:53:3:53:4 | l7 | test.c:31:14:32:15 | ... / ... | test.c:53:3:53:4 | l7 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:31:14:32:15 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:54:3:54:4 | l8 | test.c:33:14:33:22 | ... / ... | test.c:54:3:54:4 | l8 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:33:14:33:22 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:61:11:61:17 | ... / ... | test.c:61:5:61:18 | ... / ... | test.c:61:5:61:18 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.c:61:11:61:17 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:66:11:66:19 | ... / ... | test.c:66:5:66:20 | ... / ... | test.c:66:5:66:20 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.c:66:11:66:19 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:72:20:72:28 | ... / ... | test.c:72:14:72:29 | ... / ... | test.c:72:14:72:29 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.c:72:20:72:28 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:75:24:75:32 | ... / ... | test.c:75:18:75:33 | ... / ... | test.c:75:18:75:33 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.c:75:24:75:32 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:126:10:126:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:126:5:126:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:132:10:132:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:132:5:132:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:138:10:138:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:138:5:138:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:144:10:144:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:144:5:144:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:148:10:148:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:148:5:148:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:155:25:155:27 | l13 | test.c:122:15:122:21 | ... / ... | test.c:155:20:155:27 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:157:28:157:30 | l13 | test.c:122:15:122:21 | ... / ... | test.c:157:23:157:30 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:158:21:158:23 | l13 | test.c:122:15:122:21 | ... / ... | test.c:158:16:158:23 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:166:8:166:10 | call to pow | test.c:166:3:166:18 | call to pow | test.c:166:3:166:18 | call to pow | Possible NaN value $@ flows to a cast to integer. | test.c:166:8:166:10 | call to pow | both arguments are equal to zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:171:8:171:11 | call to acos | test.c:171:3:171:15 | call to acos | test.c:171:3:171:15 | call to acos | Possible NaN value $@ flows to a cast to integer. | test.c:171:8:171:11 | call to acos | the argument has a range -1000000000000000...1000000000000000 which is outside the domain of this function (-1.0...1.0) | test.c:6:6:6:7 | f1 | f1 | +| test.c:175:32:175:32 | p | test.c:190:51:190:59 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:190:51:190:59 | ... / ... | from division of zero by zero | test.c:190:6:190:24 | addNaNThenCastToInt | addNaNThenCastToInt | +| test.c:175:32:175:32 | p | test.c:195:13:195:21 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:195:13:195:21 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | +| test.c:175:32:175:32 | p | test.c:199:23:199:31 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:199:23:199:31 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | +| test.c:175:32:175:32 | p | test.c:205:19:205:27 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:205:19:205:27 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | +| test.c:185:18:185:18 | p | test.c:201:25:201:33 | ... / ... | test.c:185:13:185:18 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:201:25:201:33 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | edges | test.c:27:14:27:20 | ... / ... | test.c:27:14:27:20 | ... / ... | provenance | | | test.c:27:14:27:20 | ... / ... | test.c:36:3:36:9 | l5 | provenance | | @@ -100,37 +133,4 @@ nodes | test.c:207:21:207:31 | ... + ... | semmle.label | ... + ... | | test.c:209:13:209:21 | middleNaN | semmle.label | middleNaN | | test.c:211:23:211:31 | middleNaN | semmle.label | middleNaN | -subpaths -#select -| test.c:36:8:36:9 | l5 | test.c:27:14:27:20 | ... / ... | test.c:36:3:36:9 | l5 | Possible NaN value $@ flows to a cast to integer. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | -| test.c:37:8:37:9 | l6 | test.c:28:14:28:20 | ... / ... | test.c:37:3:37:9 | l6 | Possible NaN value $@ flows to a cast to integer. | test.c:28:14:28:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | -| test.c:38:8:38:9 | l7 | test.c:31:14:32:15 | ... / ... | test.c:38:3:38:9 | l7 | Possible NaN value $@ flows to a cast to integer. | test.c:31:14:32:15 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:39:8:39:9 | l8 | test.c:33:14:33:22 | ... / ... | test.c:39:3:39:9 | l8 | Possible NaN value $@ flows to a cast to integer. | test.c:33:14:33:22 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:46:3:46:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:46:3:46:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | -| test.c:47:3:47:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:47:3:47:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | -| test.c:48:3:48:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:48:3:48:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | -| test.c:49:3:49:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:49:3:49:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | -| test.c:50:3:50:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:50:3:50:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | -| test.c:51:3:51:4 | l5 | test.c:27:14:27:20 | ... / ... | test.c:51:3:51:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:27:14:27:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | -| test.c:52:3:52:4 | l6 | test.c:28:14:28:20 | ... / ... | test.c:52:3:52:4 | l6 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:28:14:28:20 | ... / ... | from division of infinity by infinity | test.c:6:6:6:7 | f1 | f1 | -| test.c:53:3:53:4 | l7 | test.c:31:14:32:15 | ... / ... | test.c:53:3:53:4 | l7 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:31:14:32:15 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:54:3:54:4 | l8 | test.c:33:14:33:22 | ... / ... | test.c:54:3:54:4 | l8 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.c:33:14:33:22 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:61:11:61:17 | ... / ... | test.c:61:5:61:18 | ... / ... | test.c:61:5:61:18 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.c:61:11:61:17 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:66:11:66:19 | ... / ... | test.c:66:5:66:20 | ... / ... | test.c:66:5:66:20 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.c:66:11:66:19 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:72:20:72:28 | ... / ... | test.c:72:14:72:29 | ... / ... | test.c:72:14:72:29 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.c:72:20:72:28 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:75:24:75:32 | ... / ... | test.c:75:18:75:33 | ... / ... | test.c:75:18:75:33 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.c:75:24:75:32 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:126:10:126:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:126:5:126:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:132:10:132:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:132:5:132:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:138:10:138:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:138:5:138:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:144:10:144:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:144:5:144:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:148:10:148:12 | l13 | test.c:122:15:122:21 | ... / ... | test.c:148:5:148:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:155:25:155:27 | l13 | test.c:122:15:122:21 | ... / ... | test.c:155:20:155:27 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:157:28:157:30 | l13 | test.c:122:15:122:21 | ... / ... | test.c:157:23:157:30 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:158:21:158:23 | l13 | test.c:122:15:122:21 | ... / ... | test.c:158:16:158:23 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:166:8:166:10 | call to pow | test.c:166:3:166:18 | call to pow | test.c:166:3:166:18 | call to pow | Possible NaN value $@ flows to a cast to integer. | test.c:166:8:166:10 | call to pow | both arguments are equal to zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:171:8:171:11 | call to acos | test.c:171:3:171:15 | call to acos | test.c:171:3:171:15 | call to acos | Possible NaN value $@ flows to a cast to integer. | test.c:171:8:171:11 | call to acos | the argument has a range -1000000000000000...1000000000000000 which is outside the domain of this function (-1.0...1.0) | test.c:6:6:6:7 | f1 | f1 | -| test.c:175:32:175:32 | p | test.c:190:51:190:59 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:190:51:190:59 | ... / ... | from division of zero by zero | test.c:190:6:190:24 | addNaNThenCastToInt | addNaNThenCastToInt | -| test.c:175:32:175:32 | p | test.c:195:13:195:21 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:195:13:195:21 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | -| test.c:175:32:175:32 | p | test.c:199:23:199:31 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:199:23:199:31 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | -| test.c:175:32:175:32 | p | test.c:205:19:205:27 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:205:19:205:27 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | -| test.c:185:18:185:18 | p | test.c:201:25:201:33 | ... / ... | test.c:185:13:185:18 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:201:25:201:33 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | +subpaths \ No newline at end of file diff --git a/c/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.ql b/c/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.ql new file mode 100644 index 0000000000..a1f729ed02 --- /dev/null +++ b/c/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.ql @@ -0,0 +1,4 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.misuseofnanfloatingpointvalue.MisuseOfNaNFloatingPointValue + +class TestFileQuery extends MisuseOfNaNFloatingPointValueSharedQuery, TestQuery { } diff --git a/c/common/test/rules/misuseofnanfloatingpointvalue/test.c b/c/common/test/rules/misuseofnanfloatingpointvalue/test.c new file mode 100644 index 0000000000..5115727115 --- /dev/null +++ b/c/common/test/rules/misuseofnanfloatingpointvalue/test.c @@ -0,0 +1,212 @@ +#include "math.h" + +float getFloat() { return 1.0; } + +// Parameter could be infinity +void f1(float p1) { + float l1 = 1; + float l2 = 1.0 / 0; + float l3 = -l2; + + 10 / l1; // COMPLIANT + 10 / l2; // COMPLIANT: Underflows to zero + 10 / l3; // COMPLIANT: Underflow to negative zero + 10 / p1; // COMPLIANT: Reduce false positives by assuming not infinity + 10 / getFloat(); // COMPLIANT: Reduce false positives by assuming not infinity + + (int)l1; // COMPLIANT + (int)l2; // COMPLIANT + (int)l3; // COMPLIANT + (int)p1; // COMPLIANT: Reduce false positives by assuming not infinity + (int)getFloat(); // COMPLIANT: Reduce false positives by assuming not infinity + + // Not NaN: + float l4 = l1 / l1; // COMPLIANT + + // NaN because of infinity divided by itself: + float l5 = l2 / l2; // COMPLIANT: Division by infinity not allowed. + float l6 = l3 / l3; // COMPLIANT: Division by infinity not allowed. + + // NaN because of zero divided by itself: + float l7 = getFloat() / + p1; // COMPLIANT: Reduce false positives by assuming not infinity + float l8 = 0.0 / 0.0; + + (int)l4; // COMPLIANT + (int)l5; // NON_COMPLIANT: Casting NaN to int + (int)l6; // NON_COMPLIANT: Casting NaN to int + (int)l7; // NON_COMPLIANT: Casting NaN to int + (int)l8; // NON_COMPLIANT: Casting NaN to int + + l4 == 0; // COMPLIANT + l4 != 0; // COMPLIANT + l4 <= 0; // COMPLIANT + l4 < 0; // COMPLIANT + l4 >= 0; // COMPLIANT + l5 == 0; // NON_COMPLIANT: Comparison with NaN always false + l5 != 0; // NON_COMPLIANT: Comparison with NaN always false + l5 < 0; // NON_COMPLIANT: Comparison with NaN always false + l5 <= 0; // NON_COMPLIANT: Comparison with NaN always false + l5 > 0; // NON_COMPLIANT: Comparison with NaN always false + l5 >= 0; // NON_COMPLIANT: Comparison with NaN always false + l6 == 0; // NON_COMPLIANT: Comparison with NaN always false + l7 == 0; // NON_COMPLIANT: Comparison with NaN always false + l8 == 0; // NON_COMPLIANT: Comparison with NaN always false + + // Guards + float l9 = 0; + if (l9 != 0) { + (int)(l9 / l9); // COMPLIANT: l9 is not zero + } else { + (int)(l9 / l9); // NON_COMPLIANT: Casting NaN to integer + } + + float l10 = 0; + if (l10 == 0) { + (int)(l10 / l10); // NON_COMPLIANT: Casting NaN to integer + } else { + (int)(l10 / l10); // COMPLIANT: Guarded to not be NaN + } + + float l11 = 0; + l11 == 0 ? (int)(l11 / l11) : 0; // NON_COMPLIANT + l11 == 0 ? 0 : (int)(l11 / l11); // COMPLIANT + l11 != 0 ? (int)(l11 / l11) : 0; // COMPLIANT + l11 != 0 ? 0 : (int)(l11 / l11); // NON_COMPLIANT + + float l12 = 1.0 / 0; + if (isinf(l12)) { + (int)l12; // COMPLIANT: Casting Infinity to integer + } else { + (int)l12; // COMPLIANT: Guarded not to be Infinity + } + + if (!isinf(l12)) { + (int)l12; // COMPLIANT: Guarded not to be Infinity + } else { + (int)l12; // COMPLIANT: Casting Infinity to integer + } + + if (isinf(l12) == 1) { + (int)l12; // COMPLIANT: Must be +Infinity + } else { + (int)l12; // COMPLIANT: May be -Infinity + } + + if (isfinite(l12)) { + (int)l12; // COMPLIANT: Guarded not to be Infinity + } else { + (int)l12; // COMPLIANT: Casting Infinity to integer + } + + if (isnormal(l12)) { + (int)l12; // COMPLIANT: Guarded not to be Infinity + } else { + (int)l12; // COMPLIANT: Casting Infinity to integer + } + + if (isnan(l12)) { + (int)l12; // COMPLIANT: Guarded not to be Infinity + } else { + (int)l12; // COMPLIANT: Casting Infinity to integer + } + + isinf(l12) ? (int)l12 : 0; // COMPLIANT: Check on wrong branch + isinf(l12) ? 0 : (int)l12; // COMPLIANT: Checked not infinite before use + isfinite(l12) ? (int)l12 : 0; // COMPLIANT: Checked finite before use + isfinite(l12) ? 0 : (int)l12; // COMPLIANT: Checked on wrong branch + isnan(l12) ? (int)l12 + : 0; // COMPLIANT: Checked NaN, therefore not infinite, before use + isnan(l12) ? 0 : (int)l12; // COMPLIANT: Check on wrong branch + + float l13 = 0.0 / 0; + if (isinf(l13)) { + (int)l13; // COMPLIANT: Guarded not to be NaN + } else { + (int)l13; // NON_COMPLIANT: Casting NaN to integer + } + + if (isinf(l13) == 1) { + (int)l13; // COMPLIANT: Guarded not to be NaN (must be +Infinity) + } else { + (int)l13; // NON_COMPLIANT: Casting NaN to integer + } + + if (isfinite(l13)) { + (int)l13; // COMPLIANT: Guarded not to be NaN + } else { + (int)l13; // NON_COMPLIANT: Casting NaN to integer + } + + if (isnormal(l13)) { + (int)l13; // COMPLIANT: Guarded not to be NaN + } else { + (int)l13; // NON_COMPLIANT: Casting NaN to integer + } + + if (isnan(l13)) { + (int)l13; // NON_COMPLIANT: Casting NaN to integer + } else { + (int)l13; // COMPLIANT: Guarded not to be NaN + } + + isinf(l13) ? (int)l13 + : 0; // COMPLIANT: Checked infinite, therefore not NaN, before use + isinf(l13) ? 0 : (int)l13; // NON_COMPLIANT: Check on wrong branch + isfinite(l13) ? (int)l13 : 0; // COMPLIANT: Checked finite before use + isfinite(l13) ? 0 : (int)l13; // NON_COMPLIANT: Checked on wrong branch + isnan(l13) ? (int)l13 : 0; // NON_COMPLIANT: Check on wrong branch + isnan(l13) ? 0 : (int)l13; // COMPLIANT: Checked not NaN before use + + (int)pow(2, p1); // COMPLIANT: likely to be Infinity + (int)pow(2, sin(p1)); // COMPLIANT: not likely to be Infinity + (int)(1 / + sin(p1)); // COMPLIANT: possible infinity from zero in denominator + (int)(1 / log(p1)); // COMPLIANT: not possibly zero in denominator + (int)pow(p1, p1); // NON_COMPLIANT: NaN if p1 is zero + if (p1 != 0) { + (int)pow(p1, p1); // COMPLIANT: p1 is not zero + } + + (int)acos(p1); // NON_COMPLIANT: NaN if p1 is not within -1..1 + (int)acos(cos(p1)); // COMPLIANT: cos(p1) is within -1..1 +} + +void castToInt(float p) { (int)p; } + +void checkBeforeCastToInt(float p) { + if (isfinite(p)) { + castToInt(p); + } +} + +void castToIntToFloatToInt(float p) { + // This should be reported as a violation, but not downstream from here. + castToInt((int)p); +} + +void addOneThenCastToInt(float p) { castToInt(p + 1); } +void addInfThenCastToInt(float p) { castToInt(p + 1.0 / 0.0); } +void addNaNThenCastToInt(float p) { castToInt(p + 0.0 / 0.0); } + +void f2() { + castToInt(1.0 / + 0.0); // COMPLIANT: Infinity flows to denominator in division + castToInt(0.0 / 0.0); // COMPLIANT: NaN flows to denominator in division + checkBeforeCastToInt(1.0 / 0.0); // COMPLIANT + checkBeforeCastToInt(0.0 / 0.0); // COMPLIANT + addOneThenCastToInt(1.0 / 0.0); // COMPLIANT + addOneThenCastToInt(0.0 / 0.0); // NON_COMPLIANT + castToIntToFloatToInt(1.0 / 0.0); // COMPLIANT + castToIntToFloatToInt(0.0 / 0.0); // NON_COMPLIANT + + // Check that during flow analysis, we only report the true root cause: + float rootInf = 1.0 / 0.0; + float rootNaN = 0.0 / 0.0; + float middleInf = rootInf + 1; + float middleNaN = rootNaN + 1; + castToInt(middleInf); // COMPLIANT + castToInt(middleNaN); // NON_COMPLIANT + addInfThenCastToInt(middleInf); // NON_COMPLIANT + addNaNThenCastToInt(middleNaN); // NON_COMPLIANT +} \ No newline at end of file diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql index 812e9fe1e2..0294fc6919 100644 --- a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql @@ -13,130 +13,11 @@ */ import cpp -import codeql.util.Boolean import codingstandards.c.misra -import codingstandards.cpp.RestrictedRangeAnalysis -import codingstandards.cpp.FloatingPoint -import codingstandards.cpp.AlertReporting -import semmle.code.cpp.controlflow.Guards -import semmle.code.cpp.dataflow.new.DataFlow -import semmle.code.cpp.dataflow.new.TaintTracking -import semmle.code.cpp.controlflow.Dominance +import codingstandards.cpp.rules.misuseofinfinitefloatingpointvalue.MisuseOfInfiniteFloatingPointValue -module InvalidInfinityUsage implements DataFlow::ConfigSig { - /** - * An operation which does not have Infinity as an input, but may produce Infinity, according - * to the `RestrictedRangeAnalysis` module. - */ - predicate isSource(DataFlow::Node node) { - potentialSource(node) and - not exists(DataFlow::Node prior | - isAdditionalFlowStep(prior, node) and - potentialSource(prior) - ) - } - - /** - * An operation which may produce Infinity acconding to the `RestrictedRangeAnalysis` module. - */ - additional predicate potentialSource(DataFlow::Node node) { - node.asExpr() instanceof Operation and - exprMayEqualInfinity(node.asExpr(), _) - } - - predicate isBarrierOut(DataFlow::Node node) { - guardedNotFPClass(node.asExpr(), TInfinite()) - or - exists(Expr e | - e.getType() instanceof IntegralType and - e = node.asConvertedExpr() - ) - } - - /** - * An additional flow step to handle operations which propagate Infinity. - * - * This double checks that an Infinity may propagate by checking the `RestrictedRangeAnalysis` - * value estimate. This is conservative, since `RestrictedRangeAnalysis` is performed locally - * in scope with unanalyzable values in a finite range. However, this conservative approach - * leverages analysis of guards and other local conditions to avoid false positives. - */ - predicate isAdditionalFlowStep(DataFlow::Node source, DataFlow::Node sink) { - exists(Operation o | - o.getAnOperand() = source.asExpr() and - o = sink.asExpr() and - potentialSource(sink) - ) - } - - predicate isSink(DataFlow::Node node) { - node instanceof InvalidInfinityUsage and - ( - // Require that range analysis finds this value potentially infinite, to avoid false positives - // in the presence of guards. This may induce false negatives. - exprMayEqualInfinity(node.asExpr(), _) - or - // Unanalyzable expressions are not checked against range analysis, which assumes a finite - // range. - not RestrictedRangeAnalysis::canBoundExpr(node.asExpr()) - or - node.asExpr().(VariableAccess).getTarget() instanceof Parameter - ) +class PossibleMisuseOfUndetectedInfinityQuery extends MisuseOfInfiniteFloatingPointValueSharedQuery { + PossibleMisuseOfUndetectedInfinityQuery() { + this = FloatingTypes2Package::possibleMisuseOfUndetectedInfinityQuery() } } - -class InvalidInfinityUsage extends DataFlow::Node { - string description; - - InvalidInfinityUsage() { - // Case 2: NaNs and infinities shall not be cast to integers - exists(Conversion c | - asExpr() = c.getUnconverted() and - c.getExpr().getType() instanceof FloatingPointType and - c.getType() instanceof IntegralType and - description = "cast to integer." - ) - or - // Case 3: Infinities shall not underflow or otherwise produce finite values - exists(BinaryOperation op | - asExpr() = op.getRightOperand() and - op.getOperator() = "/" and - description = "divisor, which would silently underflow and produce zero." - ) - } - - string getDescription() { result = description } -} - -module InvalidInfinityFlow = DataFlow::Global; - -import InvalidInfinityFlow::PathGraph - -from - Element elem, InvalidInfinityFlow::PathNode source, InvalidInfinityFlow::PathNode sink, - InvalidInfinityUsage usage, Expr sourceExpr, string sourceString, Function function, - string computedInFunction -where - elem = MacroUnwrapper::unwrapElement(sink.getNode().asExpr()) and - not InvalidInfinityFlow::PathGraph::edges(_, source, _, _) and - not InvalidInfinityFlow::PathGraph::edges(sink, _, _, _) and - not isExcluded(elem, FloatingTypes2Package::possibleMisuseOfUndetectedInfinityQuery()) and - not sourceExpr.isFromTemplateInstantiation(_) and - not usage.asExpr().isFromTemplateInstantiation(_) and - usage = sink.getNode() and - sourceExpr = source.getNode().asExpr() and - function = sourceExpr.getEnclosingFunction() and - InvalidInfinityFlow::flow(source.getNode(), usage) and - ( - if not sourceExpr.getEnclosingFunction() = usage.asExpr().getEnclosingFunction() - then computedInFunction = "computed in function $@ " - else computedInFunction = "" - ) and - ( - if sourceExpr instanceof DivExpr - then sourceString = "from division by zero" - else sourceString = sourceExpr.toString() - ) -select elem, source, sink, - "Possibly infinite float value $@ " + computedInFunction + "flows to " + usage.getDescription(), - sourceExpr, sourceString, function, function.getName() diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql index e1b6762ada..10bfcafeba 100644 --- a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql @@ -13,190 +13,11 @@ */ import cpp -import codeql.util.Boolean import codingstandards.c.misra -import codingstandards.cpp.RestrictedRangeAnalysis -import codingstandards.cpp.FloatingPoint -import codingstandards.cpp.AlertReporting -import semmle.code.cpp.controlflow.Guards -import semmle.code.cpp.dataflow.new.DataFlow -import semmle.code.cpp.dataflow.new.TaintTracking -import semmle.code.cpp.controlflow.Dominance +import codingstandards.cpp.rules.misuseofnanfloatingpointvalue.MisuseOfNaNFloatingPointValue -abstract class PotentiallyNaNExpr extends Expr { - abstract string getReason(); -} - -class DomainErrorFunctionCall extends FunctionCall, PotentiallyNaNExpr { - string reason; - - DomainErrorFunctionCall() { RestrictedDomainError::hasDomainError(this, reason) } - - override string getReason() { result = reason } -} - -// IEEE 754-1985 Section 7.1 invalid operations -class InvalidOperationExpr extends BinaryOperation, PotentiallyNaNExpr { - string reason; - - InvalidOperationExpr() { - // Usual arithmetic conversions in both languages mean that if either operand is a floating - // type, the other one is converted to a floating type as well. - getAnOperand().getFullyConverted().getType() instanceof FloatingPointType and - ( - // 7.1.1 propagates signaling NaNs, we rely on flow analysis and/or assume quiet NaNs, so we - // intentionally do not cover this case. - // 7.1.2: magnitude subtraction of infinities, such as +Inf + -Inf - getOperator() = "+" and - exists(Boolean sign | - exprMayEqualInfinity(getLeftOperand(), sign) and - exprMayEqualInfinity(getRightOperand(), sign.booleanNot()) - ) and - reason = "from addition of infinity and negative infinity" - or - // 7.1.2 continued - getOperator() = "-" and - exists(Boolean sign | - exprMayEqualInfinity(getLeftOperand(), sign) and - exprMayEqualInfinity(getRightOperand(), sign) - ) and - reason = "from subtraction of an infinity from itself" - or - // 7.1.3: multiplication of zero by infinity - getOperator() = "*" and - exists(Expr zeroOp, Expr infinityOp | - zeroOp = getAnOperand() and - infinityOp = getAnOperand() and - not zeroOp = infinityOp and - exprMayEqualZero(zeroOp) and - exprMayEqualInfinity(infinityOp, _) - ) and - reason = "from multiplication of zero by infinity" - or - // 7.1.4: Division of zero by zero, or infinity by infinity - getOperator() = "/" and - exprMayEqualZero(getLeftOperand()) and - exprMayEqualZero(getRightOperand()) and - reason = "from division of zero by zero" - or - // 7.1.4 continued - getOperator() = "/" and - exprMayEqualInfinity(getLeftOperand(), _) and - exprMayEqualInfinity(getRightOperand(), _) and - reason = "from division of infinity by infinity" - or - // 7.1.5: x % y where y is zero or x is infinite - getOperator() = "%" and - exprMayEqualInfinity(getLeftOperand(), _) and - reason = "from modulus of infinity" - or - // 7.1.5 continued - getOperator() = "%" and - exprMayEqualZero(getRightOperand()) and - reason = "from modulus by zero" - // 7.1.6 handles the sqrt function, not covered here. - // 7.1.7 declares exceptions during invalid conversions, which we catch as sinks in our flow - // analysis. - // 7.1.8 declares exceptions for unordered comparisons, which we catch as sinks in our flow - // analysis. - ) - } - - override string getReason() { result = reason } -} - -module InvalidNaNUsage implements DataFlow::ConfigSig { - /** - * An expression which has non-NaN inputs and may produce a NaN output. - */ - predicate isSource(DataFlow::Node node) { - potentialSource(node) and - not exists(DataFlow::Node prior | - isAdditionalFlowStep(prior, node) and - potentialSource(prior) - ) - } - - /** - * An expression which may produce a NaN output. - */ - additional predicate potentialSource(DataFlow::Node node) { - node.asExpr() instanceof PotentiallyNaNExpr - } - - predicate isBarrierOut(DataFlow::Node node) { - guardedNotFPClass(node.asExpr(), TNaN()) - or - exists(Expr e | - e.getType() instanceof IntegralType and - e = node.asConvertedExpr() - ) +class PossibleMisuseOfUndetectedNaNQuery extends MisuseOfNaNFloatingPointValueSharedQuery { + PossibleMisuseOfUndetectedNaNQuery() { + this = FloatingTypes2Package::possibleMisuseOfUndetectedNaNQuery() } - - /** - * Add an additional flow step to handle NaN propagation through floating point operations. - */ - predicate isAdditionalFlowStep(DataFlow::Node source, DataFlow::Node sink) { - exists(Operation o | - o.getAnOperand() = source.asExpr() and - o = sink.asExpr() and - o.getType() instanceof FloatingPointType - ) - } - - predicate isSink(DataFlow::Node node) { - not guardedNotFPClass(node.asExpr(), TNaN()) and - node instanceof InvalidNaNUsage - } -} - -class InvalidNaNUsage extends DataFlow::Node { - string description; - - InvalidNaNUsage() { - // Case 1: NaNs shall not be compared, except to themselves - exists(ComparisonOperation cmp | - this.asExpr() = cmp.getAnOperand() and - not hashCons(cmp.getLeftOperand()) = hashCons(cmp.getRightOperand()) and - description = "comparison, which would always evaluate to false." - ) - or - // Case 2: NaNs and infinities shall not be cast to integers - exists(Conversion c | - this.asExpr() = c.getUnconverted() and - c.getExpr().getType() instanceof FloatingPointType and - c.getType() instanceof IntegralType and - description = "a cast to integer." - ) - } - - string getDescription() { result = description } -} - -module InvalidNaNFlow = DataFlow::Global; - -import InvalidNaNFlow::PathGraph - -from - Element elem, InvalidNaNFlow::PathNode source, InvalidNaNFlow::PathNode sink, - InvalidNaNUsage usage, Expr sourceExpr, string sourceString, Function function, - string computedInFunction -where - not InvalidNaNFlow::PathGraph::edges(_, source, _, _) and - not InvalidNaNFlow::PathGraph::edges(sink, _, _, _) and - not sourceExpr.isFromTemplateInstantiation(_) and - not usage.asExpr().isFromTemplateInstantiation(_) and - elem = MacroUnwrapper::unwrapElement(sink.getNode().asExpr()) and - usage = sink.getNode() and - sourceExpr = source.getNode().asExpr() and - sourceString = source.getNode().asExpr().(PotentiallyNaNExpr).getReason() and - function = sourceExpr.getEnclosingFunction() and - InvalidNaNFlow::flow(source.getNode(), usage) and - ( - if not sourceExpr.getEnclosingFunction() = usage.asExpr().getEnclosingFunction() - then computedInFunction = "computed in function $@ " - else computedInFunction = "" - ) -select elem, source, sink, - "Possible NaN value $@ " + computedInFunction + "flows to " + usage.getDescription(), sourceExpr, - sourceString, function, function.getName() +} \ No newline at end of file diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.testref b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.testref new file mode 100644 index 0000000000..176855a83d --- /dev/null +++ b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.testref @@ -0,0 +1 @@ +c/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.ql \ No newline at end of file diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.testref b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.testref new file mode 100644 index 0000000000..7cd2a4d431 --- /dev/null +++ b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.testref @@ -0,0 +1 @@ +c/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.ql \ No newline at end of file diff --git a/change_notes/2025-04-14-update-infinity-nan-detection.md b/change_notes/2025-04-14-update-infinity-nan-detection.md new file mode 100644 index 0000000000..fe484a37fe --- /dev/null +++ b/change_notes/2025-04-14-update-infinity-nan-detection.md @@ -0,0 +1,4 @@ + - `DIR-4-15` - `PossibleMisuseOfUndetectedInfinity.ql`, `PossibleMisuseOfUndetectedNaN.ql`: + - Add logic to suppress NaNs from the CodeQL extractor in the new restricted range analysis, which can have unexpected downstream effects. + - Alter the behavior of floating point class guards (such as `isinf`, `isfinite`, `isnan`) to more correctly reflect the branches that have been guarded. + - Query files have been moved/refactored to share logic across MISRA-C and MISRA-C++; no observable change in behavior from this is expected. \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/FloatingPoint.qll b/cpp/common/src/codingstandards/cpp/FloatingPoint.qll index f5ff2fefca..cebb9dd29f 100644 --- a/cpp/common/src/codingstandards/cpp/FloatingPoint.qll +++ b/cpp/common/src/codingstandards/cpp/FloatingPoint.qll @@ -325,7 +325,8 @@ predicate guardedNotFPClass(Expr e, FPClassification cls) { hashCons(checked) = hashCons(e) and guard.controls(e, cmpEq) and guard.constrainsFPClass(checked, constraint, cmpEq) and - constraint.mustNotBe(cls) + constraint.mustNotBe(cls) and + not e = checked ) } diff --git a/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll index 05290b3aaf..5d955cc117 100644 --- a/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll +++ b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll @@ -1093,7 +1093,8 @@ module RestrictedRangeAnalysis { ( // If the expression evaluates to a constant, then there is no // need to call getUpperBoundsImpl. - if exists(getValue(expr).toFloat()) + if exists(getValue(expr).toFloat()) and + not getValue(expr) = "NaN" then result = getValue(expr).toFloat() else ( // Some of the bounds computed by `getUpperBoundsImpl` diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/FloatingPoint.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/FloatingPoint.qll new file mode 100644 index 0000000000..0ff7a07214 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/FloatingPoint.qll @@ -0,0 +1,44 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype FloatingPointQuery = + TPossibleMisuseOfInfiniteFloatingPointValueQuery() or + TPossibleMisuseOfNaNFloatingPointValueQuery() + +predicate isFloatingPointQueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `possibleMisuseOfInfiniteFloatingPointValue` query + FloatingPointPackage::possibleMisuseOfInfiniteFloatingPointValueQuery() and + queryId = + // `@id` for the `possibleMisuseOfInfiniteFloatingPointValue` query + "cpp/misra/possible-misuse-of-infinite-floating-point-value" and + ruleId = "DIR-0-3-1" and + category = "advisory" + or + query = + // `Query` instance for the `possibleMisuseOfNaNFloatingPointValue` query + FloatingPointPackage::possibleMisuseOfNaNFloatingPointValueQuery() and + queryId = + // `@id` for the `possibleMisuseOfNaNFloatingPointValue` query + "cpp/misra/possible-misuse-of-nan-floating-point-value" and + ruleId = "DIR-0-3-1" and + category = "advisory" +} + +module FloatingPointPackage { + Query possibleMisuseOfInfiniteFloatingPointValueQuery() { + //autogenerate `Query` type + result = + // `Query` type for `possibleMisuseOfInfiniteFloatingPointValue` query + TQueryCPP(TFloatingPointPackageQuery(TPossibleMisuseOfInfiniteFloatingPointValueQuery())) + } + + Query possibleMisuseOfNaNFloatingPointValueQuery() { + //autogenerate `Query` type + result = + // `Query` type for `possibleMisuseOfNaNFloatingPointValue` query + TQueryCPP(TFloatingPointPackageQuery(TPossibleMisuseOfNaNFloatingPointValueQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll index 4a6cbe936b..abd6aeff96 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll @@ -18,6 +18,7 @@ import ExceptionSafety import Exceptions1 import Exceptions2 import Expressions +import FloatingPoint import Freed import Functions import IO @@ -72,6 +73,7 @@ newtype TCPPQuery = TExceptions1PackageQuery(Exceptions1Query q) or TExceptions2PackageQuery(Exceptions2Query q) or TExpressionsPackageQuery(ExpressionsQuery q) or + TFloatingPointPackageQuery(FloatingPointQuery q) or TFreedPackageQuery(FreedQuery q) or TFunctionsPackageQuery(FunctionsQuery q) or TIOPackageQuery(IOQuery q) or @@ -126,6 +128,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isExceptions1QueryMetadata(query, queryId, ruleId, category) or isExceptions2QueryMetadata(query, queryId, ruleId, category) or isExpressionsQueryMetadata(query, queryId, ruleId, category) or + isFloatingPointQueryMetadata(query, queryId, ruleId, category) or isFreedQueryMetadata(query, queryId, ruleId, category) or isFunctionsQueryMetadata(query, queryId, ruleId, category) or isIOQueryMetadata(query, queryId, ruleId, category) or diff --git a/cpp/common/src/codingstandards/cpp/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.qll b/cpp/common/src/codingstandards/cpp/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.qll new file mode 100644 index 0000000000..eecd349ad7 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.qll @@ -0,0 +1,141 @@ +/** + * Provides a library with a `problems` predicate for the following issue: + * Possible misuse of a generate infinite floating point value. + */ + +import cpp +import codeql.util.Boolean +import codingstandards.cpp.Customizations +import codingstandards.cpp.Exclusions +import codingstandards.cpp.RestrictedRangeAnalysis +import codingstandards.cpp.FloatingPoint +import codingstandards.cpp.AlertReporting +import semmle.code.cpp.controlflow.Guards +import semmle.code.cpp.dataflow.new.DataFlow +import semmle.code.cpp.dataflow.new.TaintTracking +import semmle.code.cpp.controlflow.Dominance + +module InvalidInfinityUsage implements DataFlow::ConfigSig { + /** + * An operation which does not have Infinity as an input, but may produce Infinity, according + * to the `RestrictedRangeAnalysis` module. + */ + predicate isSource(DataFlow::Node node) { + potentialSource(node) and + not exists(DataFlow::Node prior | + isAdditionalFlowStep(prior, node) and + potentialSource(prior) + ) + } + + /** + * An operation which may produce Infinity acconding to the `RestrictedRangeAnalysis` module. + */ + additional predicate potentialSource(DataFlow::Node node) { + node.asExpr() instanceof Operation and + exprMayEqualInfinity(node.asExpr(), _) + } + + predicate isBarrierOut(DataFlow::Node node) { + guardedNotFPClass(node.asExpr(), TInfinite()) + or + exists(Expr e | + e.getType() instanceof IntegralType and + e = node.asConvertedExpr() + ) + } + + /** + * An additional flow step to handle operations which propagate Infinity. + * + * This double checks that an Infinity may propagate by checking the `RestrictedRangeAnalysis` + * value estimate. This is conservative, since `RestrictedRangeAnalysis` is performed locally + * in scope with unanalyzable values in a finite range. However, this conservative approach + * leverages analysis of guards and other local conditions to avoid false positives. + */ + predicate isAdditionalFlowStep(DataFlow::Node source, DataFlow::Node sink) { + exists(Operation o | + o.getAnOperand() = source.asExpr() and + o = sink.asExpr() and + potentialSource(sink) + ) + } + + predicate isSink(DataFlow::Node node) { + node instanceof InvalidInfinityUsage and + ( + // Require that range analysis finds this value potentially infinite, to avoid false positives + // in the presence of guards. This may induce false negatives. + exprMayEqualInfinity(node.asExpr(), _) + or + // Unanalyzable expressions are not checked against range analysis, which assumes a finite + // range. + not RestrictedRangeAnalysis::canBoundExpr(node.asExpr()) + or + node.asExpr().(VariableAccess).getTarget() instanceof Parameter + ) + } +} + +class InvalidInfinityUsage extends DataFlow::Node { + string description; + + InvalidInfinityUsage() { + // Case 2: NaNs and infinities shall not be cast to integers + exists(Conversion c | + asExpr() = c.getUnconverted() and + c.getExpr().getType() instanceof FloatingPointType and + c.getType() instanceof IntegralType and + description = "cast to integer." + ) + or + // Case 3: Infinities shall not underflow or otherwise produce finite values + exists(BinaryOperation op | + asExpr() = op.getRightOperand() and + op.getOperator() = "/" and + description = "divisor, which would silently underflow and produce zero." + ) + } + + string getDescription() { result = description } +} + +module InvalidInfinityFlow = DataFlow::Global; + +import InvalidInfinityFlow::PathGraph + +abstract class MisuseOfInfiniteFloatingPointValueSharedQuery extends Query { } + +Query getQuery() { result instanceof MisuseOfInfiniteFloatingPointValueSharedQuery } + +query predicate problems( + Element elem, InvalidInfinityFlow::PathNode source, InvalidInfinityFlow::PathNode sink, + string message, Expr sourceExpr, string sourceString, Function function, string functionName +) { + not isExcluded(elem, getQuery()) and + exists(InvalidInfinityUsage usage, string computedInFunction | + elem = MacroUnwrapper::unwrapElement(sink.getNode().asExpr()) and + not InvalidInfinityFlow::PathGraph::edges(_, source, _, _) and + not InvalidInfinityFlow::PathGraph::edges(sink, _, _, _) and + not sourceExpr.isFromTemplateInstantiation(_) and + not usage.asExpr().isFromTemplateInstantiation(_) and + usage = sink.getNode() and + sourceExpr = source.getNode().asExpr() and + function = sourceExpr.getEnclosingFunction() and + InvalidInfinityFlow::flow(source.getNode(), usage) and + ( + if not sourceExpr.getEnclosingFunction() = usage.asExpr().getEnclosingFunction() + then computedInFunction = "computed in function $@ " + else computedInFunction = "" + ) and + ( + if sourceExpr instanceof DivExpr + then sourceString = "from division by zero" + else sourceString = sourceExpr.toString() + ) and + message = + "Possibly infinite float value $@ " + computedInFunction + "flows to " + + usage.getDescription() and + functionName = function.getName() + ) +} diff --git a/cpp/common/src/codingstandards/cpp/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.qll b/cpp/common/src/codingstandards/cpp/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.qll new file mode 100644 index 0000000000..19ec4e1986 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.qll @@ -0,0 +1,201 @@ +/** + * Provides a library with a `problems` predicate for the following issue: + * Possible mishandling of an undetected NaN value produced by a floating point + * operation. + */ + +import cpp +import codeql.util.Boolean +import codingstandards.cpp.Customizations +import codingstandards.cpp.Exclusions +import codingstandards.cpp.RestrictedRangeAnalysis +import codingstandards.cpp.FloatingPoint +import codingstandards.cpp.AlertReporting +import semmle.code.cpp.controlflow.Guards +import semmle.code.cpp.dataflow.new.DataFlow +import semmle.code.cpp.dataflow.new.TaintTracking +import semmle.code.cpp.controlflow.Dominance + +abstract class PotentiallyNaNExpr extends Expr { + abstract string getReason(); +} + +class DomainErrorFunctionCall extends FunctionCall, PotentiallyNaNExpr { + string reason; + + DomainErrorFunctionCall() { RestrictedDomainError::hasDomainError(this, reason) } + + override string getReason() { result = reason } +} + +// IEEE 754-1985 Section 7.1 invalid operations +class InvalidOperationExpr extends BinaryOperation, PotentiallyNaNExpr { + string reason; + + InvalidOperationExpr() { + // Usual arithmetic conversions in both languages mean that if either operand is a floating + // type, the other one is converted to a floating type as well. + getAnOperand().getFullyConverted().getType() instanceof FloatingPointType and + ( + // 7.1.1 propagates signaling NaNs, we rely on flow analysis and/or assume quiet NaNs, so we + // intentionally do not cover this case. + // 7.1.2: magnitude subtraction of infinities, such as +Inf + -Inf + getOperator() = "+" and + exists(Boolean sign | + exprMayEqualInfinity(getLeftOperand(), sign) and + exprMayEqualInfinity(getRightOperand(), sign.booleanNot()) + ) and + reason = "from addition of infinity and negative infinity" + or + // 7.1.2 continued + getOperator() = "-" and + exists(Boolean sign | + exprMayEqualInfinity(getLeftOperand(), sign) and + exprMayEqualInfinity(getRightOperand(), sign) + ) and + reason = "from subtraction of an infinity from itself" + or + // 7.1.3: multiplication of zero by infinity + getOperator() = "*" and + exists(Expr zeroOp, Expr infinityOp | + zeroOp = getAnOperand() and + infinityOp = getAnOperand() and + not zeroOp = infinityOp and + exprMayEqualZero(zeroOp) and + exprMayEqualInfinity(infinityOp, _) + ) and + reason = "from multiplication of zero by infinity" + or + // 7.1.4: Division of zero by zero, or infinity by infinity + getOperator() = "/" and + exprMayEqualZero(getLeftOperand()) and + exprMayEqualZero(getRightOperand()) and + reason = "from division of zero by zero" + or + // 7.1.4 continued + getOperator() = "/" and + exprMayEqualInfinity(getLeftOperand(), _) and + exprMayEqualInfinity(getRightOperand(), _) and + reason = "from division of infinity by infinity" + or + // 7.1.5: x % y where y is zero or x is infinite + getOperator() = "%" and + exprMayEqualInfinity(getLeftOperand(), _) and + reason = "from modulus of infinity" + or + // 7.1.5 continued + getOperator() = "%" and + exprMayEqualZero(getRightOperand()) and + reason = "from modulus by zero" + // 7.1.6 handles the sqrt function, not covered here. + // 7.1.7 declares exceptions during invalid conversions, which we catch as sinks in our flow + // analysis. + // 7.1.8 declares exceptions for unordered comparisons, which we catch as sinks in our flow + // analysis. + ) + } + + override string getReason() { result = reason } +} + +module InvalidNaNUsage implements DataFlow::ConfigSig { + /** + * An expression which has non-NaN inputs and may produce a NaN output. + */ + predicate isSource(DataFlow::Node node) { + potentialSource(node) and + not exists(DataFlow::Node prior | + isAdditionalFlowStep(prior, node) and + potentialSource(prior) + ) + } + + /** + * An expression which may produce a NaN output. + */ + additional predicate potentialSource(DataFlow::Node node) { + node.asExpr() instanceof PotentiallyNaNExpr + } + + predicate isBarrierOut(DataFlow::Node node) { + guardedNotFPClass(node.asExpr(), TNaN()) + or + exists(Expr e | + e.getType() instanceof IntegralType and + e = node.asConvertedExpr() + ) + } + + /** + * Add an additional flow step to handle NaN propagation through floating point operations. + */ + predicate isAdditionalFlowStep(DataFlow::Node source, DataFlow::Node sink) { + exists(Operation o | + o.getAnOperand() = source.asExpr() and + o = sink.asExpr() and + o.getType() instanceof FloatingPointType + ) + } + + predicate isSink(DataFlow::Node node) { + not guardedNotFPClass(node.asExpr(), TNaN()) and + node instanceof InvalidNaNUsage + } +} + +class InvalidNaNUsage extends DataFlow::Node { + string description; + + InvalidNaNUsage() { + // Case 1: NaNs shall not be compared, except to themselves + exists(ComparisonOperation cmp | + this.asExpr() = cmp.getAnOperand() and + not hashCons(cmp.getLeftOperand()) = hashCons(cmp.getRightOperand()) and + description = "comparison, which would always evaluate to false." + ) + or + // Case 2: NaNs and infinities shall not be cast to integers + exists(Conversion c | + this.asExpr() = c.getUnconverted() and + c.getExpr().getType() instanceof FloatingPointType and + c.getType() instanceof IntegralType and + description = "a cast to integer." + ) + } + + string getDescription() { result = description } +} + +module InvalidNaNFlow = DataFlow::Global; + +import InvalidNaNFlow::PathGraph + +abstract class MisuseOfNaNFloatingPointValueSharedQuery extends Query { } + +Query getQuery() { result instanceof MisuseOfNaNFloatingPointValueSharedQuery } + +query predicate problems( + Element elem, InvalidNaNFlow::PathNode source, InvalidNaNFlow::PathNode sink, string message, + Expr sourceExpr, string sourceString, Function function, string functionName +) { + not isExcluded(elem, getQuery()) and + exists(InvalidNaNUsage usage, string computedInFunction | + not InvalidNaNFlow::PathGraph::edges(_, source, _, _) and + not InvalidNaNFlow::PathGraph::edges(sink, _, _, _) and + not sourceExpr.isFromTemplateInstantiation(_) and + not usage.asExpr().isFromTemplateInstantiation(_) and + elem = MacroUnwrapper::unwrapElement(sink.getNode().asExpr()) and + usage = sink.getNode() and + sourceExpr = source.getNode().asExpr() and + sourceString = source.getNode().asExpr().(PotentiallyNaNExpr).getReason() and + function = sourceExpr.getEnclosingFunction() and + InvalidNaNFlow::flow(source.getNode(), usage) and + ( + if not sourceExpr.getEnclosingFunction() = usage.asExpr().getEnclosingFunction() + then computedInFunction = "computed in function $@ " + else computedInFunction = "" + ) and + message = "Possible NaN value $@ " + computedInFunction + "flows to " + usage.getDescription() and + functionName = function.getName() + ) +} diff --git a/cpp/common/test/includes/standard-library/cmath b/cpp/common/test/includes/standard-library/cmath index e69de29bb2..9f3fffda8d 100644 --- a/cpp/common/test/includes/standard-library/cmath +++ b/cpp/common/test/includes/standard-library/cmath @@ -0,0 +1,19 @@ +namespace std { +#include + +int isinf(float x); +int isinf(double x); +int isinf(long double x); +bool isfinite(float x); +bool isfinite(double x); +bool isfinite(long double x); +bool isnan(float x); +bool isnan(double x); +bool isnan(long double x); +bool isnormal(float x); +bool isnormal(double x); +bool isnormal(long double x); +int fpclassify(float x); +int fpclassify(double x); +int fpclassify(long double x); +} \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/math.h b/cpp/common/test/includes/standard-library/math.h index 460c0a9c2f..7ff0ef8357 100644 --- a/cpp/common/test/includes/standard-library/math.h +++ b/cpp/common/test/includes/standard-library/math.h @@ -17,6 +17,9 @@ long double acoshl(long double x); double atanh(double x); float atanhf(float x); long double atanhl(long double x); +float cos(float x); +double cos(double x); +long double cos(long double x); double fmod(double x, double y); float fmodf(float x, float y); long double fmodl(long double x, long double y); @@ -47,6 +50,9 @@ long double logbl(long double x); double pow(double x, double y); float powf(float x, float y); long double powl(long double x, long double y); +float sin(float x); +double sin(double x); +long double sin(long double x); double sqrt(double x); float sqrtf(float x); long double sqrtl(long double x); diff --git a/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.expected b/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.expected new file mode 100644 index 0000000000..6624187d42 --- /dev/null +++ b/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.expected @@ -0,0 +1,113 @@ +problems +| test.cpp:12:8:12:9 | l2 | test.cpp:8:14:8:20 | ... / ... | test.cpp:12:8:12:9 | l2 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.cpp:8:14:8:20 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:13:8:13:9 | l3 | test.cpp:8:14:8:20 | ... / ... | test.cpp:13:8:13:9 | l3 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.cpp:8:14:8:20 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:18:20:18:21 | l2 | test.cpp:8:14:8:20 | ... / ... | test.cpp:18:3:18:22 | l2 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:8:14:8:20 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:19:20:19:21 | l3 | test.cpp:8:14:8:20 | ... / ... | test.cpp:19:3:19:22 | l3 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:8:14:8:20 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:27:19:27:20 | l2 | test.cpp:8:14:8:20 | ... / ... | test.cpp:27:19:27:20 | l2 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.cpp:8:14:8:20 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:28:19:28:20 | l3 | test.cpp:8:14:8:20 | ... / ... | test.cpp:28:19:28:20 | l3 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.cpp:8:14:8:20 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:38:20:38:21 | l7 | test.cpp:31:14:32:15 | ... / ... | test.cpp:38:3:38:22 | l7 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:31:14:32:15 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:61:22:61:28 | ... / ... | test.cpp:61:5:61:29 | ... / ... | test.cpp:61:5:61:29 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.cpp:61:22:61:28 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:66:22:66:30 | ... / ... | test.cpp:66:5:66:31 | ... / ... | test.cpp:66:5:66:31 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.cpp:66:22:66:30 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:72:31:72:39 | ... / ... | test.cpp:72:14:72:40 | ... / ... | test.cpp:72:14:72:40 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.cpp:72:31:72:39 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:75:35:75:43 | ... / ... | test.cpp:75:18:75:44 | ... / ... | test.cpp:75:18:75:44 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.cpp:75:35:75:43 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:79:22:79:24 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:79:5:79:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:87:22:87:24 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:87:5:87:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:91:22:91:24 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:91:5:91:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:93:22:93:24 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:93:5:93:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:99:22:99:24 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:99:5:99:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:105:22:105:24 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:105:5:105:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:111:22:111:24 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:111:5:111:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:114:38:114:40 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:114:21:114:41 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:117:45:117:47 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:117:28:117:48 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:120:42:120:44 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:120:25:120:45 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:163:20:164:20 | ... / ... | test.cpp:163:3:164:21 | ... / ... | test.cpp:163:3:164:21 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.cpp:163:20:164:20 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:175:44:175:44 | p | test.cpp:189:51:189:59 | ... / ... | test.cpp:175:27:175:45 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.cpp:189:51:189:59 | ... / ... | from division by zero | test.cpp:189:6:189:24 | addInfThenCastToInt | addInfThenCastToInt | +| test.cpp:175:44:175:44 | p | test.cpp:193:13:194:15 | ... / ... | test.cpp:175:27:175:45 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.cpp:193:13:194:15 | ... / ... | from division by zero | test.cpp:192:6:192:7 | f2 | f2 | +| test.cpp:175:44:175:44 | p | test.cpp:204:19:204:27 | ... / ... | test.cpp:175:27:175:45 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.cpp:204:19:204:27 | ... / ... | from division by zero | test.cpp:192:6:192:7 | f2 | f2 | +| test.cpp:185:30:185:30 | p | test.cpp:200:25:200:33 | ... / ... | test.cpp:185:13:185:31 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.cpp:200:25:200:33 | ... / ... | from division by zero | test.cpp:192:6:192:7 | f2 | f2 | +edges +| test.cpp:8:14:8:20 | ... / ... | test.cpp:8:14:8:20 | ... / ... | provenance | | +| test.cpp:8:14:8:20 | ... / ... | test.cpp:9:14:9:16 | - ... | provenance | Config | +| test.cpp:8:14:8:20 | ... / ... | test.cpp:12:8:12:9 | l2 | provenance | | +| test.cpp:8:14:8:20 | ... / ... | test.cpp:18:3:18:22 | l2 | provenance | | +| test.cpp:8:14:8:20 | ... / ... | test.cpp:27:19:27:20 | l2 | provenance | | +| test.cpp:9:14:9:16 | - ... | test.cpp:9:14:9:16 | - ... | provenance | | +| test.cpp:9:14:9:16 | - ... | test.cpp:13:8:13:9 | l3 | provenance | | +| test.cpp:9:14:9:16 | - ... | test.cpp:19:3:19:22 | l3 | provenance | | +| test.cpp:9:14:9:16 | - ... | test.cpp:28:19:28:20 | l3 | provenance | | +| test.cpp:31:14:32:15 | ... / ... | test.cpp:31:14:32:15 | ... / ... | provenance | | +| test.cpp:31:14:32:15 | ... / ... | test.cpp:38:3:38:22 | l7 | provenance | | +| test.cpp:77:15:77:21 | ... / ... | test.cpp:77:15:77:21 | ... / ... | provenance | | +| test.cpp:77:15:77:21 | ... / ... | test.cpp:79:5:79:25 | l12 | provenance | | +| test.cpp:77:15:77:21 | ... / ... | test.cpp:87:5:87:25 | l12 | provenance | | +| test.cpp:77:15:77:21 | ... / ... | test.cpp:91:5:91:25 | l12 | provenance | | +| test.cpp:77:15:77:21 | ... / ... | test.cpp:93:5:93:25 | l12 | provenance | | +| test.cpp:77:15:77:21 | ... / ... | test.cpp:99:5:99:25 | l12 | provenance | | +| test.cpp:77:15:77:21 | ... / ... | test.cpp:105:5:105:25 | l12 | provenance | | +| test.cpp:77:15:77:21 | ... / ... | test.cpp:111:5:111:25 | l12 | provenance | | +| test.cpp:77:15:77:21 | ... / ... | test.cpp:114:21:114:41 | l12 | provenance | | +| test.cpp:77:15:77:21 | ... / ... | test.cpp:117:28:117:48 | l12 | provenance | | +| test.cpp:77:15:77:21 | ... / ... | test.cpp:120:25:120:45 | l12 | provenance | | +| test.cpp:175:22:175:22 | p | test.cpp:175:27:175:45 | p | provenance | | +| test.cpp:183:34:183:34 | p | test.cpp:185:13:185:31 | p | provenance | | +| test.cpp:189:32:189:32 | p | test.cpp:189:47:189:59 | ... + ... | provenance | Config | +| test.cpp:189:47:189:59 | ... + ... | test.cpp:175:22:175:22 | p | provenance | | +| test.cpp:189:47:189:59 | ... + ... | test.cpp:175:22:175:22 | p | provenance | | +| test.cpp:189:51:189:59 | ... / ... | test.cpp:189:47:189:59 | ... + ... | provenance | Config | +| test.cpp:193:13:194:15 | ... / ... | test.cpp:175:22:175:22 | p | provenance | | +| test.cpp:200:25:200:33 | ... / ... | test.cpp:183:34:183:34 | p | provenance | | +| test.cpp:204:19:204:27 | ... / ... | test.cpp:204:19:204:27 | ... / ... | provenance | | +| test.cpp:204:19:204:27 | ... / ... | test.cpp:206:21:206:31 | ... + ... | provenance | Config | +| test.cpp:206:21:206:31 | ... + ... | test.cpp:206:21:206:31 | ... + ... | provenance | | +| test.cpp:206:21:206:31 | ... + ... | test.cpp:208:13:208:21 | middleInf | provenance | | +| test.cpp:206:21:206:31 | ... + ... | test.cpp:210:23:210:31 | middleInf | provenance | | +| test.cpp:208:13:208:21 | middleInf | test.cpp:175:22:175:22 | p | provenance | | +| test.cpp:210:23:210:31 | middleInf | test.cpp:189:32:189:32 | p | provenance | | +nodes +| test.cpp:8:14:8:20 | ... / ... | semmle.label | ... / ... | +| test.cpp:8:14:8:20 | ... / ... | semmle.label | ... / ... | +| test.cpp:9:14:9:16 | - ... | semmle.label | - ... | +| test.cpp:9:14:9:16 | - ... | semmle.label | - ... | +| test.cpp:12:8:12:9 | l2 | semmle.label | l2 | +| test.cpp:13:8:13:9 | l3 | semmle.label | l3 | +| test.cpp:18:3:18:22 | l2 | semmle.label | l2 | +| test.cpp:19:3:19:22 | l3 | semmle.label | l3 | +| test.cpp:27:19:27:20 | l2 | semmle.label | l2 | +| test.cpp:28:19:28:20 | l3 | semmle.label | l3 | +| test.cpp:31:14:32:15 | ... / ... | semmle.label | ... / ... | +| test.cpp:31:14:32:15 | ... / ... | semmle.label | ... / ... | +| test.cpp:38:3:38:22 | l7 | semmle.label | l7 | +| test.cpp:61:5:61:29 | ... / ... | semmle.label | ... / ... | +| test.cpp:66:5:66:31 | ... / ... | semmle.label | ... / ... | +| test.cpp:72:14:72:40 | ... / ... | semmle.label | ... / ... | +| test.cpp:75:18:75:44 | ... / ... | semmle.label | ... / ... | +| test.cpp:77:15:77:21 | ... / ... | semmle.label | ... / ... | +| test.cpp:77:15:77:21 | ... / ... | semmle.label | ... / ... | +| test.cpp:79:5:79:25 | l12 | semmle.label | l12 | +| test.cpp:87:5:87:25 | l12 | semmle.label | l12 | +| test.cpp:91:5:91:25 | l12 | semmle.label | l12 | +| test.cpp:93:5:93:25 | l12 | semmle.label | l12 | +| test.cpp:99:5:99:25 | l12 | semmle.label | l12 | +| test.cpp:105:5:105:25 | l12 | semmle.label | l12 | +| test.cpp:111:5:111:25 | l12 | semmle.label | l12 | +| test.cpp:114:21:114:41 | l12 | semmle.label | l12 | +| test.cpp:117:28:117:48 | l12 | semmle.label | l12 | +| test.cpp:120:25:120:45 | l12 | semmle.label | l12 | +| test.cpp:163:3:164:21 | ... / ... | semmle.label | ... / ... | +| test.cpp:175:22:175:22 | p | semmle.label | p | +| test.cpp:175:27:175:45 | p | semmle.label | p | +| test.cpp:183:34:183:34 | p | semmle.label | p | +| test.cpp:185:13:185:31 | p | semmle.label | p | +| test.cpp:189:32:189:32 | p | semmle.label | p | +| test.cpp:189:47:189:59 | ... + ... | semmle.label | ... + ... | +| test.cpp:189:47:189:59 | ... + ... | semmle.label | ... + ... | +| test.cpp:189:51:189:59 | ... / ... | semmle.label | ... / ... | +| test.cpp:193:13:194:15 | ... / ... | semmle.label | ... / ... | +| test.cpp:200:25:200:33 | ... / ... | semmle.label | ... / ... | +| test.cpp:204:19:204:27 | ... / ... | semmle.label | ... / ... | +| test.cpp:204:19:204:27 | ... / ... | semmle.label | ... / ... | +| test.cpp:206:21:206:31 | ... + ... | semmle.label | ... + ... | +| test.cpp:206:21:206:31 | ... + ... | semmle.label | ... + ... | +| test.cpp:208:13:208:21 | middleInf | semmle.label | middleInf | +| test.cpp:210:23:210:31 | middleInf | semmle.label | middleInf | +subpaths diff --git a/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.ql b/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.ql new file mode 100644 index 0000000000..f0d160a650 --- /dev/null +++ b/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.ql @@ -0,0 +1,4 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.misuseofinfinitefloatingpointvalue.MisuseOfInfiniteFloatingPointValue + +class TestFileQuery extends MisuseOfInfiniteFloatingPointValueSharedQuery, TestQuery { } diff --git a/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/test.cpp b/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/test.cpp new file mode 100644 index 0000000000..e9067d8ce7 --- /dev/null +++ b/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/test.cpp @@ -0,0 +1,212 @@ +#include + +float getFloat() { return 1.0; } + +// Parameter could be infinity +void f1(float p1) { + float l1 = 1; + float l2 = 1.0 / 0; + float l3 = -l2; + + 10 / l1; // COMPLIANT + 10 / l2; // NON_COMPLIANT: Underflows to zero + 10 / l3; // NON_COMPLIANT: Underflow to negative zero + 10 / p1; // COMPLIANT: Reduce false positives by assuming not infinity + 10 / getFloat(); // COMPLIANT: Reduce false positives by assuming not infinity + + static_cast(l1); // COMPLIANT + static_cast(l2); // NON_COMPLIANT + static_cast(l3); // NON_COMPLIANT + static_cast(p1); // COMPLIANT: Reduce false positives by assuming not infinity + static_cast(getFloat()); // COMPLIANT: Reduce false positives by assuming not infinity + + // Not NaN: + float l4 = l1 / l1; // COMPLIANT + + // NaN because of infinity divided by itself: + float l5 = l2 / l2; // NON_COMPLIANT: Division by infinity not allowed. + float l6 = l3 / l3; // NON_COMPLIANT: Division by infinity not allowed. + + // NaN because of zero divided by itself: + float l7 = getFloat() / + p1; // COMPLIANT: Reduce false positives by assuming not infinity + float l8 = 0.0 / 0.0; + + static_cast(l4); // COMPLIANT + static_cast(l5); // COMPLIANT: Casting NaN to int + static_cast(l6); // COMPLIANT: Casting NaN to int + static_cast(l7); // NON_COMPLIANT: Casting Infinity to int + static_cast(l8); // COMPLIANT: Casting NaN to int + + l4 == 0; // COMPLIANT + l4 != 0; // COMPLIANT + l4 <= 0; // COMPLIANT + l4 < 0; // COMPLIANT + l4 >= 0; // COMPLIANT + l5 == 0; // NON_COMPLIANT: Comparison with NaN always false + l5 != 0; // NON_COMPLIANT: Comparison with NaN always false + l5 < 0; // NON_COMPLIANT: Comparison with NaN always false + l5 <= 0; // NON_COMPLIANT: Comparison with NaN always false + l5 > 0; // NON_COMPLIANT: Comparison with NaN always false + l5 >= 0; // NON_COMPLIANT: Comparison with NaN always false + l6 == 0; // NON_COMPLIANT: Comparison with NaN always false + l7 == 0; // NON_COMPLIANT: Comparison with NaN always false + l8 == 0; // NON_COMPLIANT: Comparison with NaN always false + + // Guards + float l9 = 0; + if (l9 != 0) { + static_cast(l9 / l9); // COMPLIANT: l9 is not zero + } else { + static_cast(l9 / l9); // NON_COMPLIANT[False positive]: Guarded to not be NaN + } + + float l10 = 0; + if (l10 == 0) { + static_cast(l10 / l10); // NON_COMPLIANT[False positive]: Casting NaN to integer + } else { + static_cast(l10 / l10); // COMPLIANT: Guarded to not be NaN + } + + float l11 = 0; + l11 == 0 ? static_cast(l11 / l11) : 0; // NON_COMPLIANT[False positive] + l11 == 0 ? 0 : static_cast(l11 / l11); // COMPLIANT + l11 != 0 ? static_cast(l11 / l11) : 0; // COMPLIANT + l11 != 0 ? 0 : static_cast(l11 / l11); // NON_COMPLIANT[False positive] + + float l12 = 1.0 / 0; + if (std::isinf(l12)) { + static_cast(l12); // NON_COMPLIANT: Casting Infinity to integer + } else { + static_cast(l12); // COMPLIANT: Guarded not to be Infinity + } + + if (!std::isinf(l12)) { + static_cast(l12); // COMPLIANT: Guarded not to be Infinity + } else { + static_cast(l12); // NON_COMPLIANT: Casting Infinity to integer + } + + if (std::isinf(l12) == 1) { + static_cast(l12); // NON_COMPLIANT: Must be +Infinity + } else { + static_cast(l12); // NON_COMPLIANT: May be -Infinity + } + + if (std::isfinite(l12)) { + static_cast(l12); // COMPLIANT: Guarded not to be Infinity + } else { + static_cast(l12); // NON_COMPLIANT: Casting Infinity to integer + } + + if (std::isnormal(l12)) { + static_cast(l12); // COMPLIANT: Guarded not to be Infinity + } else { + static_cast(l12); // NON_COMPLIANT: Casting Infinity to integer + } + + if (std::isnan(l12)) { + static_cast(l12); // COMPLIANT: Guarded not to be Infinity + } else { + static_cast(l12); // NON_COMPLIANT: Casting Infinity to integer + } + + std::isinf(l12) ? static_cast(l12) : 0; // NON_COMPLIANT: Check on wrong branch + std::isinf(l12) ? 0 : static_cast(l12); // COMPLIANT: Checked not infinite before use + std::isfinite(l12) ? static_cast(l12) : 0; // COMPLIANT: Checked finite before use + std::isfinite(l12) ? 0 : static_cast(l12); // NON_COMPLIANT: Checked on wrong branch + std::isnan(l12) ? static_cast(l12) + : 0; // COMPLIANT: Checked NaN, therefore not infinite, before use + std::isnan(l12) ? 0 : static_cast(l12); // NON_COMPLIANT: Check on wrong branch + + float l13 = 0.0 / 0; + if (std::isinf(l13)) { + static_cast(l13); // COMPLIANT: Guarded not to be NaN + } else { + static_cast(l13); // COMPLIANT: Casting NaN to integer + } + + if (std::isinf(l13) == 1) { + static_cast(l13); // COMPLIANT: Guarded not to be NaN (must be +Infinity) + } else { + static_cast(l13); // COMPLIANT: Casting NaN to integer + } + + if (std::isfinite(l13)) { + static_cast(l13); // COMPLIANT: Guarded not to be NaN + } else { + static_cast(l13); // COMPLIANT: Casting NaN to integer + } + + if (std::isnormal(l13)) { + static_cast(l13); // COMPLIANT: Guarded not to be NaN + } else { + static_cast(l13); // COMPLIANT: Casting NaN to integer + } + + if (std::isnan(l13)) { + static_cast(l13); // COMPLIANT: Casting NaN to integer + } else { + static_cast(l13); // COMPLIANT: Guarded not to be NaN + } + + std::isinf(l13) ? static_cast(l13) + : 0; // COMPLIANT: Checked infinite, therefore not NaN, before use + std::isinf(l13) ? 0 : static_cast(l13); // COMPLIANT: Check on wrong branch + std::isfinite(l13) ? static_cast(l13) : 0; // COMPLIANT: Checked finite before use + std::isfinite(l13) ? 0 : static_cast(l13); // COMPLIANT: Checked on wrong branch + std::isnan(l13) ? static_cast(l13) : 0; // COMPLIANT: Check on wrong branch + std::isnan(l13) ? 0 : static_cast(l13); // COMPLIANT: Checked not NaN before use + + static_cast(std::pow(2, p1)); // NON_COMPLIANT[False negative]: likely to be Infinity + static_cast(std::pow(2, std::sin(p1))); // COMPLIANT: not likely to be Infinity + static_cast(1 / + std::sin(p1)); // NON_COMPLIANT: possible infinity from zero in denominator + static_cast(1 / std::log(p1)); // COMPLIANT: not possibly zero in denominator + static_cast(std::pow(p1, p1)); // COMPLIANT: NaN if p1 is zero + if (p1 != 0) { + static_cast(std::pow(p1, p1)); // COMPLIANT: p1 is not zero + } + + static_cast(std::acos(p1)); // COMPLIANT: NaN if p1 is not within -1..1 + static_cast(std::acos(std::cos(p1))); // COMPLIANT: cos(p1) is within -1..1 +} + +void castToInt(float p) { static_cast(p); } + +void checkBeforeCastToInt(float p) { + if (std::isfinite(p)) { + castToInt(p); + } +} + +void castToIntToFloatToInt(float p) { + // This should be reported as a violation, but not downstream from here. + castToInt(static_cast(p)); +} + +void addOneThenCastToInt(float p) { castToInt(p + 1); } +void addInfThenCastToInt(float p) { castToInt(p + 1.0 / 0.0); } +void addNaNThenCastToInt(float p) { castToInt(p + 0.0 / 0.0); } + +void f2() { + castToInt(1.0 / + 0.0); // NON_COMPLIANT: Infinity flows to denominator in division + castToInt(0.0 / 0.0); // COMPLIANT + checkBeforeCastToInt(1.0 / 0.0); // COMPLIANT + checkBeforeCastToInt(0.0 / 0.0); // COMPLIANT + addOneThenCastToInt(1.0 / 0.0); // NON_COMPLIANT[False negative] + addOneThenCastToInt(0.0 / 0.0); // NON_COMPLIANT + castToIntToFloatToInt(1.0 / 0.0); // NON_COMPLIANT + castToIntToFloatToInt(0.0 / 0.0); // COMPLIANT + + // Check that during flow analysis, we only report the true root cause: + float rootInf = 1.0 / 0.0; + float rootNaN = 0.0 / 0.0; + float middleInf = rootInf + 1; + float middleNaN = rootNaN + 1; + castToInt(middleInf); // NON_COMPLIANT + castToInt(middleNaN); // COMPLIANT + addInfThenCastToInt(middleInf); // NON_COMPLIANT + addNaNThenCastToInt(middleNaN); // COMPLIANT +} \ No newline at end of file diff --git a/cpp/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected b/cpp/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected new file mode 100644 index 0000000000..576327fb21 --- /dev/null +++ b/cpp/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected @@ -0,0 +1,136 @@ +problems +| test.cpp:36:8:36:9 | l5 | test.cpp:27:14:27:20 | ... / ... | test.cpp:36:3:36:9 | l5 | Possible NaN value $@ flows to a cast to integer. | test.cpp:27:14:27:20 | ... / ... | from division of infinity by infinity | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:37:8:37:9 | l6 | test.cpp:28:14:28:20 | ... / ... | test.cpp:37:3:37:9 | l6 | Possible NaN value $@ flows to a cast to integer. | test.cpp:28:14:28:20 | ... / ... | from division of infinity by infinity | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:38:8:38:9 | l7 | test.cpp:31:14:32:15 | ... / ... | test.cpp:38:3:38:9 | l7 | Possible NaN value $@ flows to a cast to integer. | test.cpp:31:14:32:15 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:39:8:39:9 | l8 | test.cpp:33:14:33:22 | ... / ... | test.cpp:39:3:39:9 | l8 | Possible NaN value $@ flows to a cast to integer. | test.cpp:33:14:33:22 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:46:3:46:4 | l5 | test.cpp:27:14:27:20 | ... / ... | test.cpp:46:3:46:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.cpp:27:14:27:20 | ... / ... | from division of infinity by infinity | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:47:3:47:4 | l5 | test.cpp:27:14:27:20 | ... / ... | test.cpp:47:3:47:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.cpp:27:14:27:20 | ... / ... | from division of infinity by infinity | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:48:3:48:4 | l5 | test.cpp:27:14:27:20 | ... / ... | test.cpp:48:3:48:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.cpp:27:14:27:20 | ... / ... | from division of infinity by infinity | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:49:3:49:4 | l5 | test.cpp:27:14:27:20 | ... / ... | test.cpp:49:3:49:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.cpp:27:14:27:20 | ... / ... | from division of infinity by infinity | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:50:3:50:4 | l5 | test.cpp:27:14:27:20 | ... / ... | test.cpp:50:3:50:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.cpp:27:14:27:20 | ... / ... | from division of infinity by infinity | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:51:3:51:4 | l5 | test.cpp:27:14:27:20 | ... / ... | test.cpp:51:3:51:4 | l5 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.cpp:27:14:27:20 | ... / ... | from division of infinity by infinity | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:52:3:52:4 | l6 | test.cpp:28:14:28:20 | ... / ... | test.cpp:52:3:52:4 | l6 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.cpp:28:14:28:20 | ... / ... | from division of infinity by infinity | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:53:3:53:4 | l7 | test.cpp:31:14:32:15 | ... / ... | test.cpp:53:3:53:4 | l7 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.cpp:31:14:32:15 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:54:3:54:4 | l8 | test.cpp:33:14:33:22 | ... / ... | test.cpp:54:3:54:4 | l8 | Possible NaN value $@ flows to comparison, which would always evaluate to false. | test.cpp:33:14:33:22 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:61:11:61:17 | ... / ... | test.cpp:61:5:61:18 | ... / ... | test.cpp:61:5:61:18 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.cpp:61:11:61:17 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:66:11:66:19 | ... / ... | test.cpp:66:5:66:20 | ... / ... | test.cpp:66:5:66:20 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.cpp:66:11:66:19 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:72:20:72:28 | ... / ... | test.cpp:72:14:72:29 | ... / ... | test.cpp:72:14:72:29 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.cpp:72:20:72:28 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:75:24:75:32 | ... / ... | test.cpp:75:18:75:33 | ... / ... | test.cpp:75:18:75:33 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.cpp:75:24:75:32 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:126:10:126:12 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:126:5:126:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:132:10:132:12 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:132:5:132:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:138:10:138:12 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:138:5:138:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:144:10:144:12 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:144:5:144:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:148:10:148:12 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:148:5:148:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:155:30:155:32 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:155:25:155:32 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:157:33:157:35 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:157:28:157:35 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:158:26:158:28 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:158:21:158:28 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:166:8:166:15 | call to pow | test.cpp:166:3:166:23 | call to pow | test.cpp:166:3:166:23 | call to pow | Possible NaN value $@ flows to a cast to integer. | test.cpp:166:8:166:15 | call to pow | both arguments are equal to zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:171:8:171:16 | call to acos | test.cpp:171:3:171:20 | call to acos | test.cpp:171:3:171:20 | call to acos | Possible NaN value $@ flows to a cast to integer. | test.cpp:171:8:171:16 | call to acos | the argument has a range -1000000000000000...1000000000000000 which is outside the domain of this function (-1.0...1.0) | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:175:32:175:32 | p | test.cpp:190:51:190:59 | ... / ... | test.cpp:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.cpp:190:51:190:59 | ... / ... | from division of zero by zero | test.cpp:190:6:190:24 | addNaNThenCastToInt | addNaNThenCastToInt | +| test.cpp:175:32:175:32 | p | test.cpp:195:13:195:21 | ... / ... | test.cpp:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.cpp:195:13:195:21 | ... / ... | from division of zero by zero | test.cpp:192:6:192:7 | f2 | f2 | +| test.cpp:175:32:175:32 | p | test.cpp:199:23:199:31 | ... / ... | test.cpp:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.cpp:199:23:199:31 | ... / ... | from division of zero by zero | test.cpp:192:6:192:7 | f2 | f2 | +| test.cpp:175:32:175:32 | p | test.cpp:205:19:205:27 | ... / ... | test.cpp:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.cpp:205:19:205:27 | ... / ... | from division of zero by zero | test.cpp:192:6:192:7 | f2 | f2 | +| test.cpp:185:18:185:18 | p | test.cpp:201:25:201:33 | ... / ... | test.cpp:185:13:185:18 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.cpp:201:25:201:33 | ... / ... | from division of zero by zero | test.cpp:192:6:192:7 | f2 | f2 | +edges +| test.cpp:27:14:27:20 | ... / ... | test.cpp:27:14:27:20 | ... / ... | provenance | | +| test.cpp:27:14:27:20 | ... / ... | test.cpp:36:3:36:9 | l5 | provenance | | +| test.cpp:27:14:27:20 | ... / ... | test.cpp:46:3:46:4 | l5 | provenance | | +| test.cpp:27:14:27:20 | ... / ... | test.cpp:47:3:47:4 | l5 | provenance | | +| test.cpp:27:14:27:20 | ... / ... | test.cpp:48:3:48:4 | l5 | provenance | | +| test.cpp:27:14:27:20 | ... / ... | test.cpp:49:3:49:4 | l5 | provenance | | +| test.cpp:27:14:27:20 | ... / ... | test.cpp:50:3:50:4 | l5 | provenance | | +| test.cpp:27:14:27:20 | ... / ... | test.cpp:51:3:51:4 | l5 | provenance | | +| test.cpp:28:14:28:20 | ... / ... | test.cpp:28:14:28:20 | ... / ... | provenance | | +| test.cpp:28:14:28:20 | ... / ... | test.cpp:37:3:37:9 | l6 | provenance | | +| test.cpp:28:14:28:20 | ... / ... | test.cpp:52:3:52:4 | l6 | provenance | | +| test.cpp:31:14:32:15 | ... / ... | test.cpp:31:14:32:15 | ... / ... | provenance | | +| test.cpp:31:14:32:15 | ... / ... | test.cpp:38:3:38:9 | l7 | provenance | | +| test.cpp:31:14:32:15 | ... / ... | test.cpp:53:3:53:4 | l7 | provenance | | +| test.cpp:33:14:33:22 | ... / ... | test.cpp:33:14:33:22 | ... / ... | provenance | | +| test.cpp:33:14:33:22 | ... / ... | test.cpp:39:3:39:9 | l8 | provenance | | +| test.cpp:33:14:33:22 | ... / ... | test.cpp:54:3:54:4 | l8 | provenance | | +| test.cpp:122:15:122:21 | ... / ... | test.cpp:122:15:122:21 | ... / ... | provenance | | +| test.cpp:122:15:122:21 | ... / ... | test.cpp:126:5:126:12 | l13 | provenance | | +| test.cpp:122:15:122:21 | ... / ... | test.cpp:132:5:132:12 | l13 | provenance | | +| test.cpp:122:15:122:21 | ... / ... | test.cpp:138:5:138:12 | l13 | provenance | | +| test.cpp:122:15:122:21 | ... / ... | test.cpp:144:5:144:12 | l13 | provenance | | +| test.cpp:122:15:122:21 | ... / ... | test.cpp:148:5:148:12 | l13 | provenance | | +| test.cpp:122:15:122:21 | ... / ... | test.cpp:155:25:155:32 | l13 | provenance | | +| test.cpp:122:15:122:21 | ... / ... | test.cpp:157:28:157:35 | l13 | provenance | | +| test.cpp:122:15:122:21 | ... / ... | test.cpp:158:21:158:28 | l13 | provenance | | +| test.cpp:175:22:175:22 | p | test.cpp:175:27:175:32 | p | provenance | | +| test.cpp:183:34:183:34 | p | test.cpp:185:13:185:18 | p | provenance | | +| test.cpp:188:32:188:32 | p | test.cpp:188:47:188:51 | ... + ... | provenance | Config | +| test.cpp:188:47:188:51 | ... + ... | test.cpp:175:22:175:22 | p | provenance | | +| test.cpp:190:32:190:32 | p | test.cpp:190:47:190:59 | ... + ... | provenance | Config | +| test.cpp:190:47:190:59 | ... + ... | test.cpp:175:22:175:22 | p | provenance | | +| test.cpp:190:47:190:59 | ... + ... | test.cpp:175:22:175:22 | p | provenance | | +| test.cpp:190:51:190:59 | ... / ... | test.cpp:190:47:190:59 | ... + ... | provenance | Config | +| test.cpp:195:13:195:21 | ... / ... | test.cpp:175:22:175:22 | p | provenance | | +| test.cpp:199:23:199:31 | ... / ... | test.cpp:188:32:188:32 | p | provenance | | +| test.cpp:201:25:201:33 | ... / ... | test.cpp:183:34:183:34 | p | provenance | | +| test.cpp:205:19:205:27 | ... / ... | test.cpp:205:19:205:27 | ... / ... | provenance | | +| test.cpp:205:19:205:27 | ... / ... | test.cpp:207:21:207:31 | ... + ... | provenance | Config | +| test.cpp:207:21:207:31 | ... + ... | test.cpp:207:21:207:31 | ... + ... | provenance | | +| test.cpp:207:21:207:31 | ... + ... | test.cpp:209:13:209:21 | middleNaN | provenance | | +| test.cpp:207:21:207:31 | ... + ... | test.cpp:211:23:211:31 | middleNaN | provenance | | +| test.cpp:209:13:209:21 | middleNaN | test.cpp:175:22:175:22 | p | provenance | | +| test.cpp:211:23:211:31 | middleNaN | test.cpp:190:32:190:32 | p | provenance | | +nodes +| test.cpp:27:14:27:20 | ... / ... | semmle.label | ... / ... | +| test.cpp:27:14:27:20 | ... / ... | semmle.label | ... / ... | +| test.cpp:28:14:28:20 | ... / ... | semmle.label | ... / ... | +| test.cpp:28:14:28:20 | ... / ... | semmle.label | ... / ... | +| test.cpp:31:14:32:15 | ... / ... | semmle.label | ... / ... | +| test.cpp:31:14:32:15 | ... / ... | semmle.label | ... / ... | +| test.cpp:33:14:33:22 | ... / ... | semmle.label | ... / ... | +| test.cpp:33:14:33:22 | ... / ... | semmle.label | ... / ... | +| test.cpp:36:3:36:9 | l5 | semmle.label | l5 | +| test.cpp:37:3:37:9 | l6 | semmle.label | l6 | +| test.cpp:38:3:38:9 | l7 | semmle.label | l7 | +| test.cpp:39:3:39:9 | l8 | semmle.label | l8 | +| test.cpp:46:3:46:4 | l5 | semmle.label | l5 | +| test.cpp:47:3:47:4 | l5 | semmle.label | l5 | +| test.cpp:48:3:48:4 | l5 | semmle.label | l5 | +| test.cpp:49:3:49:4 | l5 | semmle.label | l5 | +| test.cpp:50:3:50:4 | l5 | semmle.label | l5 | +| test.cpp:51:3:51:4 | l5 | semmle.label | l5 | +| test.cpp:52:3:52:4 | l6 | semmle.label | l6 | +| test.cpp:53:3:53:4 | l7 | semmle.label | l7 | +| test.cpp:54:3:54:4 | l8 | semmle.label | l8 | +| test.cpp:61:5:61:18 | ... / ... | semmle.label | ... / ... | +| test.cpp:66:5:66:20 | ... / ... | semmle.label | ... / ... | +| test.cpp:72:14:72:29 | ... / ... | semmle.label | ... / ... | +| test.cpp:75:18:75:33 | ... / ... | semmle.label | ... / ... | +| test.cpp:122:15:122:21 | ... / ... | semmle.label | ... / ... | +| test.cpp:122:15:122:21 | ... / ... | semmle.label | ... / ... | +| test.cpp:126:5:126:12 | l13 | semmle.label | l13 | +| test.cpp:132:5:132:12 | l13 | semmle.label | l13 | +| test.cpp:138:5:138:12 | l13 | semmle.label | l13 | +| test.cpp:144:5:144:12 | l13 | semmle.label | l13 | +| test.cpp:148:5:148:12 | l13 | semmle.label | l13 | +| test.cpp:155:25:155:32 | l13 | semmle.label | l13 | +| test.cpp:157:28:157:35 | l13 | semmle.label | l13 | +| test.cpp:158:21:158:28 | l13 | semmle.label | l13 | +| test.cpp:166:3:166:23 | call to pow | semmle.label | call to pow | +| test.cpp:171:3:171:20 | call to acos | semmle.label | call to acos | +| test.cpp:175:22:175:22 | p | semmle.label | p | +| test.cpp:175:27:175:32 | p | semmle.label | p | +| test.cpp:183:34:183:34 | p | semmle.label | p | +| test.cpp:185:13:185:18 | p | semmle.label | p | +| test.cpp:188:32:188:32 | p | semmle.label | p | +| test.cpp:188:47:188:51 | ... + ... | semmle.label | ... + ... | +| test.cpp:190:32:190:32 | p | semmle.label | p | +| test.cpp:190:47:190:59 | ... + ... | semmle.label | ... + ... | +| test.cpp:190:47:190:59 | ... + ... | semmle.label | ... + ... | +| test.cpp:190:51:190:59 | ... / ... | semmle.label | ... / ... | +| test.cpp:195:13:195:21 | ... / ... | semmle.label | ... / ... | +| test.cpp:199:23:199:31 | ... / ... | semmle.label | ... / ... | +| test.cpp:201:25:201:33 | ... / ... | semmle.label | ... / ... | +| test.cpp:205:19:205:27 | ... / ... | semmle.label | ... / ... | +| test.cpp:205:19:205:27 | ... / ... | semmle.label | ... / ... | +| test.cpp:207:21:207:31 | ... + ... | semmle.label | ... + ... | +| test.cpp:207:21:207:31 | ... + ... | semmle.label | ... + ... | +| test.cpp:209:13:209:21 | middleNaN | semmle.label | middleNaN | +| test.cpp:211:23:211:31 | middleNaN | semmle.label | middleNaN | +subpaths diff --git a/cpp/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.ql b/cpp/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.ql new file mode 100644 index 0000000000..a1f729ed02 --- /dev/null +++ b/cpp/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.ql @@ -0,0 +1,4 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.misuseofnanfloatingpointvalue.MisuseOfNaNFloatingPointValue + +class TestFileQuery extends MisuseOfNaNFloatingPointValueSharedQuery, TestQuery { } diff --git a/cpp/common/test/rules/misuseofnanfloatingpointvalue/test.cpp b/cpp/common/test/rules/misuseofnanfloatingpointvalue/test.cpp new file mode 100644 index 0000000000..51540bc3a1 --- /dev/null +++ b/cpp/common/test/rules/misuseofnanfloatingpointvalue/test.cpp @@ -0,0 +1,212 @@ +#include + +float getFloat() { return 1.0; } + +// Parameter could be infinity +void f1(float p1) { + float l1 = 1; + float l2 = 1.0 / 0; + float l3 = -l2; + + 10 / l1; // COMPLIANT + 10 / l2; // COMPLIANT: Underflows to zero + 10 / l3; // COMPLIANT: Underflow to negative zero + 10 / p1; // COMPLIANT: Reduce false positives by assuming not infinity + 10 / getFloat(); // COMPLIANT: Reduce false positives by assuming not infinity + + (int)l1; // COMPLIANT + (int)l2; // COMPLIANT + (int)l3; // COMPLIANT + (int)p1; // COMPLIANT: Reduce false positives by assuming not infinity + (int)getFloat(); // COMPLIANT: Reduce false positives by assuming not infinity + + // Not NaN: + float l4 = l1 / l1; // COMPLIANT + + // NaN because of infinity divided by itself: + float l5 = l2 / l2; // COMPLIANT: Division by infinity not allowed. + float l6 = l3 / l3; // COMPLIANT: Division by infinity not allowed. + + // NaN because of zero divided by itself: + float l7 = getFloat() / + p1; // COMPLIANT: Reduce false positives by assuming not infinity + float l8 = 0.0 / 0.0; + + (int)l4; // COMPLIANT + (int)l5; // NON_COMPLIANT: Casting NaN to int + (int)l6; // NON_COMPLIANT: Casting NaN to int + (int)l7; // NON_COMPLIANT: Casting NaN to int + (int)l8; // NON_COMPLIANT: Casting NaN to int + + l4 == 0; // COMPLIANT + l4 != 0; // COMPLIANT + l4 <= 0; // COMPLIANT + l4 < 0; // COMPLIANT + l4 >= 0; // COMPLIANT + l5 == 0; // NON_COMPLIANT: Comparison with NaN always false + l5 != 0; // NON_COMPLIANT: Comparison with NaN always false + l5 < 0; // NON_COMPLIANT: Comparison with NaN always false + l5 <= 0; // NON_COMPLIANT: Comparison with NaN always false + l5 > 0; // NON_COMPLIANT: Comparison with NaN always false + l5 >= 0; // NON_COMPLIANT: Comparison with NaN always false + l6 == 0; // NON_COMPLIANT: Comparison with NaN always false + l7 == 0; // NON_COMPLIANT: Comparison with NaN always false + l8 == 0; // NON_COMPLIANT: Comparison with NaN always false + + // Guards + float l9 = 0; + if (l9 != 0) { + (int)(l9 / l9); // COMPLIANT: l9 is not zero + } else { + (int)(l9 / l9); // NON_COMPLIANT: Casting NaN to integer + } + + float l10 = 0; + if (l10 == 0) { + (int)(l10 / l10); // NON_COMPLIANT: Casting NaN to integer + } else { + (int)(l10 / l10); // COMPLIANT: Guarded to not be NaN + } + + float l11 = 0; + l11 == 0 ? (int)(l11 / l11) : 0; // NON_COMPLIANT + l11 == 0 ? 0 : (int)(l11 / l11); // COMPLIANT + l11 != 0 ? (int)(l11 / l11) : 0; // COMPLIANT + l11 != 0 ? 0 : (int)(l11 / l11); // NON_COMPLIANT + + float l12 = 1.0 / 0; + if (std::isinf(l12)) { + (int)l12; // COMPLIANT: Casting Infinity to integer + } else { + (int)l12; // COMPLIANT: Guarded not to be Infinity + } + + if (!std::isinf(l12)) { + (int)l12; // COMPLIANT: Guarded not to be Infinity + } else { + (int)l12; // COMPLIANT: Casting Infinity to integer + } + + if (std::isinf(l12) == 1) { + (int)l12; // COMPLIANT: Must be +Infinity + } else { + (int)l12; // COMPLIANT: May be -Infinity + } + + if (std::isfinite(l12)) { + (int)l12; // COMPLIANT: Guarded not to be Infinity + } else { + (int)l12; // COMPLIANT: Casting Infinity to integer + } + + if (std::isnormal(l12)) { + (int)l12; // COMPLIANT: Guarded not to be Infinity + } else { + (int)l12; // COMPLIANT: Casting Infinity to integer + } + + if (std::isnan(l12)) { + (int)l12; // COMPLIANT: Guarded not to be Infinity + } else { + (int)l12; // COMPLIANT: Casting Infinity to integer + } + + std::isinf(l12) ? (int)l12 : 0; // COMPLIANT: Check on wrong branch + std::isinf(l12) ? 0 : (int)l12; // COMPLIANT: Checked not infinite before use + std::isfinite(l12) ? (int)l12 : 0; // COMPLIANT: Checked finite before use + std::isfinite(l12) ? 0 : (int)l12; // COMPLIANT: Checked on wrong branch + std::isnan(l12) ? (int)l12 + : 0; // COMPLIANT: Checked NaN, therefore not infinite, before use + std::isnan(l12) ? 0 : (int)l12; // COMPLIANT: Check on wrong branch + + float l13 = 0.0 / 0; + if (std::isinf(l13)) { + (int)l13; // COMPLIANT: Guarded not to be NaN + } else { + (int)l13; // NON_COMPLIANT: Casting NaN to integer + } + + if (std::isinf(l13) == 1) { + (int)l13; // COMPLIANT: Guarded not to be NaN (must be +Infinity) + } else { + (int)l13; // NON_COMPLIANT: Casting NaN to integer + } + + if (std::isfinite(l13)) { + (int)l13; // COMPLIANT: Guarded not to be NaN + } else { + (int)l13; // NON_COMPLIANT: Casting NaN to integer + } + + if (std::isnormal(l13)) { + (int)l13; // COMPLIANT: Guarded not to be NaN + } else { + (int)l13; // NON_COMPLIANT: Casting NaN to integer + } + + if (std::isnan(l13)) { + (int)l13; // NON_COMPLIANT: Casting NaN to integer + } else { + (int)l13; // COMPLIANT: Guarded not to be NaN + } + + std::isinf(l13) ? (int)l13 + : 0; // COMPLIANT: Checked infinite, therefore not NaN, before use + std::isinf(l13) ? 0 : (int)l13; // NON_COMPLIANT: Check on wrong branch + std::isfinite(l13) ? (int)l13 : 0; // COMPLIANT: Checked finite before use + std::isfinite(l13) ? 0 : (int)l13; // NON_COMPLIANT: Checked on wrong branch + std::isnan(l13) ? (int)l13 : 0; // NON_COMPLIANT: Check on wrong branch + std::isnan(l13) ? 0 : (int)l13; // COMPLIANT: Checked not NaN before use + + (int)std::pow(2, p1); // COMPLIANT: likely to be Infinity + (int)std::pow(2, std::sin(p1)); // COMPLIANT: not likely to be Infinity + (int)(1 / + std::sin(p1)); // COMPLIANT: possible infinity from zero in denominator + (int)(1 / std::log(p1)); // COMPLIANT: not possibly zero in denominator + (int)std::pow(p1, p1); // NON_COMPLIANT: NaN if p1 is zero + if (p1 != 0) { + (int)std::pow(p1, p1); // COMPLIANT: p1 is not zero + } + + (int)std::acos(p1); // NON_COMPLIANT: NaN if p1 is not within -1..1 + (int)std::acos(std::cos(p1)); // COMPLIANT: cos(p1) is within -1..1 +} + +void castToInt(float p) { (int)p; } + +void checkBeforeCastToInt(float p) { + if (std::isfinite(p)) { + castToInt(p); + } +} + +void castToIntToFloatToInt(float p) { + // This should be reported as a violation, but not downstream from here. + castToInt((int)p); +} + +void addOneThenCastToInt(float p) { castToInt(p + 1); } +void addInfThenCastToInt(float p) { castToInt(p + 1.0 / 0.0); } +void addNaNThenCastToInt(float p) { castToInt(p + 0.0 / 0.0); } + +void f2() { + castToInt(1.0 / + 0.0); // COMPLIANT: Infinity flows to denominator in division + castToInt(0.0 / 0.0); // COMPLIANT: NaN flows to denominator in division + checkBeforeCastToInt(1.0 / 0.0); // COMPLIANT + checkBeforeCastToInt(0.0 / 0.0); // COMPLIANT + addOneThenCastToInt(1.0 / 0.0); // COMPLIANT + addOneThenCastToInt(0.0 / 0.0); // NON_COMPLIANT + castToIntToFloatToInt(1.0 / 0.0); // COMPLIANT + castToIntToFloatToInt(0.0 / 0.0); // NON_COMPLIANT + + // Check that during flow analysis, we only report the true root cause: + float rootInf = 1.0 / 0.0; + float rootNaN = 0.0 / 0.0; + float middleInf = rootInf + 1; + float middleNaN = rootNaN + 1; + castToInt(middleInf); // COMPLIANT + castToInt(middleNaN); // NON_COMPLIANT + addInfThenCastToInt(middleInf); // COMPLIANT + addNaNThenCastToInt(middleNaN); // NON_COMPLIANT +} \ No newline at end of file diff --git a/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.ql b/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.ql new file mode 100644 index 0000000000..d9810c1135 --- /dev/null +++ b/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.ql @@ -0,0 +1,22 @@ +/** + * @id cpp/misra/possible-misuse-of-infinite-floating-point-value + * @name DIR-0-3-1: Possible misuse of a generate infinite floating point value + * @description Possible misuse of a generate infinite floating point value. + * @kind path-problem + * @precision medium + * @problem.severity warning + * @tags external/misra/id/dir-0-3-1 + * correctness + * external/misra/c/2012/amendment3 + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.cpp.misra +import codingstandards.cpp.rules.misuseofinfinitefloatingpointvalue.MisuseOfInfiniteFloatingPointValue + +class PossibleMisuseOfInfiniteFloatingPointValueQuery extends MisuseOfInfiniteFloatingPointValueSharedQuery { + PossibleMisuseOfInfiniteFloatingPointValueQuery() { + this = FloatingPointPackage::possibleMisuseOfInfiniteFloatingPointValueQuery() + } +} diff --git a/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfNaNFloatingPointValue.ql b/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfNaNFloatingPointValue.ql new file mode 100644 index 0000000000..934ee6d998 --- /dev/null +++ b/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfNaNFloatingPointValue.ql @@ -0,0 +1,23 @@ +/** + * @id cpp/misra/possible-misuse-of-nan-floating-point-value + * @name DIR-0-3-1: Possible mishandling of an undetected NaN value produced by a floating point operation + * @description Possible mishandling of an undetected NaN value produced by a floating point + * operation. + * @kind path-problem + * @precision low + * @problem.severity warning + * @tags external/misra/id/dir-0-3-1 + * correctness + * external/misra/c/2012/amendment3 + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.cpp.misra +import codingstandards.cpp.rules.misuseofnanfloatingpointvalue.MisuseOfNaNFloatingPointValue + +class PossibleMisuseOfNaNFloatingPointValueQuery extends MisuseOfNaNFloatingPointValueSharedQuery { + PossibleMisuseOfNaNFloatingPointValueQuery() { + this = FloatingPointPackage::possibleMisuseOfNaNFloatingPointValueQuery() + } +} diff --git a/cpp/misra/test/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.testref b/cpp/misra/test/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.testref new file mode 100644 index 0000000000..952d461d00 --- /dev/null +++ b/cpp/misra/test/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.testref @@ -0,0 +1 @@ +cpp/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.ql \ No newline at end of file diff --git a/cpp/misra/test/rules/DIR-0-3-1/PossibleMisuseOfNaNFloatingPointValue.testref b/cpp/misra/test/rules/DIR-0-3-1/PossibleMisuseOfNaNFloatingPointValue.testref new file mode 100644 index 0000000000..2cd2de067d --- /dev/null +++ b/cpp/misra/test/rules/DIR-0-3-1/PossibleMisuseOfNaNFloatingPointValue.testref @@ -0,0 +1 @@ +cpp/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.ql \ No newline at end of file diff --git a/rule_packages/c/FloatingTypes2.json b/rule_packages/c/FloatingTypes2.json index 3f4771dcc6..a1c02daaf5 100644 --- a/rule_packages/c/FloatingTypes2.json +++ b/rule_packages/c/FloatingTypes2.json @@ -12,6 +12,7 @@ "precision": "medium", "severity": "warning", "short_name": "PossibleMisuseOfUndetectedInfinity", + "shared_implementation_short_name": "MisuseOfInfiniteFloatingPointValue", "tags": [ "correctness", "external/misra/c/2012/amendment3" @@ -24,6 +25,7 @@ "precision": "low", "severity": "warning", "short_name": "PossibleMisuseOfUndetectedNaN", + "shared_implementation_short_name": "MisuseOfNaNFloatingPointValue", "tags": [ "correctness", "external/misra/c/2012/amendment3" diff --git a/rule_packages/cpp/FloatingPoint.json b/rule_packages/cpp/FloatingPoint.json new file mode 100644 index 0000000000..b085e5b289 --- /dev/null +++ b/rule_packages/cpp/FloatingPoint.json @@ -0,0 +1,38 @@ +{ + "MISRA-C++-2023": { + "DIR-0-3-1": { + "properties": { + "obligation": "advisory" + }, + "queries": [ + { + "description": "Possible misuse of a generate infinite floating point value.", + "kind": "path-problem", + "name": "Possible misuse of a generate infinite floating point value", + "precision": "medium", + "severity": "warning", + "short_name": "PossibleMisuseOfInfiniteFloatingPointValue", + "shared_implementation_short_name": "MisuseOfInfiniteFloatingPointValue", + "tags": [ + "correctness", + "external/misra/c/2012/amendment3" + ] + }, + { + "description": "Possible mishandling of an undetected NaN value produced by a floating point operation.", + "kind": "path-problem", + "name": "Possible mishandling of an undetected NaN value produced by a floating point operation", + "precision": "low", + "severity": "warning", + "short_name": "PossibleMisuseOfNaNFloatingPointValue", + "shared_implementation_short_name": "MisuseOfNaNFloatingPointValue", + "tags": [ + "correctness", + "external/misra/c/2012/amendment3" + ] + } + ], + "title": "Floating-point arithmetic should be used appropriately" + } + } +} \ No newline at end of file From 5fa421b286c997a3b792b5c2996f5deeb8bebee6 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 15 Apr 2025 07:40:56 -0700 Subject: [PATCH 299/370] Format --- .../misuseofinfinitefloatingpointvalue/test.c | 2 +- .../MisuseOfNaNFloatingPointValue.expected | 94 ++++----- .../misuseofnanfloatingpointvalue/test.c | 10 +- .../cpp/RestrictedRangeAnalysis.qll | 5 +- ...isuseOfInfiniteFloatingPointValue.expected | 178 +++++++++--------- .../test.cpp | 89 ++++++--- .../MisuseOfNaNFloatingPointValue.expected | 144 +++++++------- .../misuseofnanfloatingpointvalue/test.cpp | 21 ++- ...sibleMisuseOfInfiniteFloatingPointValue.ql | 3 +- rule_packages/cpp/FloatingPoint.json | 6 +- 10 files changed, 289 insertions(+), 263 deletions(-) diff --git a/c/common/test/rules/misuseofinfinitefloatingpointvalue/test.c b/c/common/test/rules/misuseofinfinitefloatingpointvalue/test.c index 85097d828b..6a4ebd94b9 100644 --- a/c/common/test/rules/misuseofinfinitefloatingpointvalue/test.c +++ b/c/common/test/rules/misuseofinfinitefloatingpointvalue/test.c @@ -192,7 +192,7 @@ void addNaNThenCastToInt(float p) { castToInt(p + 0.0 / 0.0); } void f2() { castToInt(1.0 / 0.0); // NON_COMPLIANT: Infinity flows to denominator in division - castToInt(0.0 / 0.0); // COMPLIANT + castToInt(0.0 / 0.0); // COMPLIANT checkBeforeCastToInt(1.0 / 0.0); // COMPLIANT checkBeforeCastToInt(0.0 / 0.0); // COMPLIANT addOneThenCastToInt(1.0 / 0.0); // NON_COMPLIANT[False negative] diff --git a/c/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected b/c/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected index 1555fd5bd8..b567e06bc2 100644 --- a/c/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected +++ b/c/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected @@ -24,13 +24,13 @@ problems | test.c:155:25:155:27 | l13 | test.c:122:15:122:21 | ... / ... | test.c:155:20:155:27 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | | test.c:157:28:157:30 | l13 | test.c:122:15:122:21 | ... / ... | test.c:157:23:157:30 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | | test.c:158:21:158:23 | l13 | test.c:122:15:122:21 | ... / ... | test.c:158:16:158:23 | l13 | Possible NaN value $@ flows to a cast to integer. | test.c:122:15:122:21 | ... / ... | from division of zero by zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:166:8:166:10 | call to pow | test.c:166:3:166:18 | call to pow | test.c:166:3:166:18 | call to pow | Possible NaN value $@ flows to a cast to integer. | test.c:166:8:166:10 | call to pow | both arguments are equal to zero | test.c:6:6:6:7 | f1 | f1 | -| test.c:171:8:171:11 | call to acos | test.c:171:3:171:15 | call to acos | test.c:171:3:171:15 | call to acos | Possible NaN value $@ flows to a cast to integer. | test.c:171:8:171:11 | call to acos | the argument has a range -1000000000000000...1000000000000000 which is outside the domain of this function (-1.0...1.0) | test.c:6:6:6:7 | f1 | f1 | -| test.c:175:32:175:32 | p | test.c:190:51:190:59 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:190:51:190:59 | ... / ... | from division of zero by zero | test.c:190:6:190:24 | addNaNThenCastToInt | addNaNThenCastToInt | -| test.c:175:32:175:32 | p | test.c:195:13:195:21 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:195:13:195:21 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | -| test.c:175:32:175:32 | p | test.c:199:23:199:31 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:199:23:199:31 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | -| test.c:175:32:175:32 | p | test.c:205:19:205:27 | ... / ... | test.c:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:205:19:205:27 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | -| test.c:185:18:185:18 | p | test.c:201:25:201:33 | ... / ... | test.c:185:13:185:18 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:201:25:201:33 | ... / ... | from division of zero by zero | test.c:192:6:192:7 | f2 | f2 | +| test.c:165:8:165:10 | call to pow | test.c:165:3:165:18 | call to pow | test.c:165:3:165:18 | call to pow | Possible NaN value $@ flows to a cast to integer. | test.c:165:8:165:10 | call to pow | both arguments are equal to zero | test.c:6:6:6:7 | f1 | f1 | +| test.c:170:8:170:11 | call to acos | test.c:170:3:170:15 | call to acos | test.c:170:3:170:15 | call to acos | Possible NaN value $@ flows to a cast to integer. | test.c:170:8:170:11 | call to acos | the argument has a range -1000000000000000...1000000000000000 which is outside the domain of this function (-1.0...1.0) | test.c:6:6:6:7 | f1 | f1 | +| test.c:174:32:174:32 | p | test.c:189:51:189:59 | ... / ... | test.c:174:27:174:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:189:51:189:59 | ... / ... | from division of zero by zero | test.c:189:6:189:24 | addNaNThenCastToInt | addNaNThenCastToInt | +| test.c:174:32:174:32 | p | test.c:193:13:193:21 | ... / ... | test.c:174:27:174:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:193:13:193:21 | ... / ... | from division of zero by zero | test.c:191:6:191:7 | f2 | f2 | +| test.c:174:32:174:32 | p | test.c:197:23:197:31 | ... / ... | test.c:174:27:174:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:197:23:197:31 | ... / ... | from division of zero by zero | test.c:191:6:191:7 | f2 | f2 | +| test.c:174:32:174:32 | p | test.c:203:19:203:27 | ... / ... | test.c:174:27:174:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:203:19:203:27 | ... / ... | from division of zero by zero | test.c:191:6:191:7 | f2 | f2 | +| test.c:184:18:184:18 | p | test.c:199:25:199:33 | ... / ... | test.c:184:13:184:18 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.c:199:25:199:33 | ... / ... | from division of zero by zero | test.c:191:6:191:7 | f2 | f2 | edges | test.c:27:14:27:20 | ... / ... | test.c:27:14:27:20 | ... / ... | provenance | | | test.c:27:14:27:20 | ... / ... | test.c:36:3:36:9 | l5 | provenance | | @@ -58,24 +58,24 @@ edges | test.c:122:15:122:21 | ... / ... | test.c:155:20:155:27 | l13 | provenance | | | test.c:122:15:122:21 | ... / ... | test.c:157:23:157:30 | l13 | provenance | | | test.c:122:15:122:21 | ... / ... | test.c:158:16:158:23 | l13 | provenance | | -| test.c:175:22:175:22 | p | test.c:175:27:175:32 | p | provenance | | -| test.c:183:34:183:34 | p | test.c:185:13:185:18 | p | provenance | | -| test.c:188:32:188:32 | p | test.c:188:47:188:51 | ... + ... | provenance | Config | -| test.c:188:47:188:51 | ... + ... | test.c:175:22:175:22 | p | provenance | | -| test.c:190:32:190:32 | p | test.c:190:47:190:59 | ... + ... | provenance | Config | -| test.c:190:47:190:59 | ... + ... | test.c:175:22:175:22 | p | provenance | | -| test.c:190:47:190:59 | ... + ... | test.c:175:22:175:22 | p | provenance | | -| test.c:190:51:190:59 | ... / ... | test.c:190:47:190:59 | ... + ... | provenance | Config | -| test.c:195:13:195:21 | ... / ... | test.c:175:22:175:22 | p | provenance | | -| test.c:199:23:199:31 | ... / ... | test.c:188:32:188:32 | p | provenance | | -| test.c:201:25:201:33 | ... / ... | test.c:183:34:183:34 | p | provenance | | -| test.c:205:19:205:27 | ... / ... | test.c:205:19:205:27 | ... / ... | provenance | | -| test.c:205:19:205:27 | ... / ... | test.c:207:21:207:31 | ... + ... | provenance | Config | -| test.c:207:21:207:31 | ... + ... | test.c:207:21:207:31 | ... + ... | provenance | | -| test.c:207:21:207:31 | ... + ... | test.c:209:13:209:21 | middleNaN | provenance | | -| test.c:207:21:207:31 | ... + ... | test.c:211:23:211:31 | middleNaN | provenance | | -| test.c:209:13:209:21 | middleNaN | test.c:175:22:175:22 | p | provenance | | -| test.c:211:23:211:31 | middleNaN | test.c:190:32:190:32 | p | provenance | | +| test.c:174:22:174:22 | p | test.c:174:27:174:32 | p | provenance | | +| test.c:182:34:182:34 | p | test.c:184:13:184:18 | p | provenance | | +| test.c:187:32:187:32 | p | test.c:187:47:187:51 | ... + ... | provenance | Config | +| test.c:187:47:187:51 | ... + ... | test.c:174:22:174:22 | p | provenance | | +| test.c:189:32:189:32 | p | test.c:189:47:189:59 | ... + ... | provenance | Config | +| test.c:189:47:189:59 | ... + ... | test.c:174:22:174:22 | p | provenance | | +| test.c:189:47:189:59 | ... + ... | test.c:174:22:174:22 | p | provenance | | +| test.c:189:51:189:59 | ... / ... | test.c:189:47:189:59 | ... + ... | provenance | Config | +| test.c:193:13:193:21 | ... / ... | test.c:174:22:174:22 | p | provenance | | +| test.c:197:23:197:31 | ... / ... | test.c:187:32:187:32 | p | provenance | | +| test.c:199:25:199:33 | ... / ... | test.c:182:34:182:34 | p | provenance | | +| test.c:203:19:203:27 | ... / ... | test.c:203:19:203:27 | ... / ... | provenance | | +| test.c:203:19:203:27 | ... / ... | test.c:205:21:205:31 | ... + ... | provenance | Config | +| test.c:205:21:205:31 | ... + ... | test.c:205:21:205:31 | ... + ... | provenance | | +| test.c:205:21:205:31 | ... + ... | test.c:207:13:207:21 | middleNaN | provenance | | +| test.c:205:21:205:31 | ... + ... | test.c:209:23:209:31 | middleNaN | provenance | | +| test.c:207:13:207:21 | middleNaN | test.c:174:22:174:22 | p | provenance | | +| test.c:209:23:209:31 | middleNaN | test.c:189:32:189:32 | p | provenance | | nodes | test.c:27:14:27:20 | ... / ... | semmle.label | ... / ... | | test.c:27:14:27:20 | ... / ... | semmle.label | ... / ... | @@ -112,25 +112,25 @@ nodes | test.c:155:20:155:27 | l13 | semmle.label | l13 | | test.c:157:23:157:30 | l13 | semmle.label | l13 | | test.c:158:16:158:23 | l13 | semmle.label | l13 | -| test.c:166:3:166:18 | call to pow | semmle.label | call to pow | -| test.c:171:3:171:15 | call to acos | semmle.label | call to acos | -| test.c:175:22:175:22 | p | semmle.label | p | -| test.c:175:27:175:32 | p | semmle.label | p | -| test.c:183:34:183:34 | p | semmle.label | p | -| test.c:185:13:185:18 | p | semmle.label | p | -| test.c:188:32:188:32 | p | semmle.label | p | -| test.c:188:47:188:51 | ... + ... | semmle.label | ... + ... | -| test.c:190:32:190:32 | p | semmle.label | p | -| test.c:190:47:190:59 | ... + ... | semmle.label | ... + ... | -| test.c:190:47:190:59 | ... + ... | semmle.label | ... + ... | -| test.c:190:51:190:59 | ... / ... | semmle.label | ... / ... | -| test.c:195:13:195:21 | ... / ... | semmle.label | ... / ... | -| test.c:199:23:199:31 | ... / ... | semmle.label | ... / ... | -| test.c:201:25:201:33 | ... / ... | semmle.label | ... / ... | -| test.c:205:19:205:27 | ... / ... | semmle.label | ... / ... | -| test.c:205:19:205:27 | ... / ... | semmle.label | ... / ... | -| test.c:207:21:207:31 | ... + ... | semmle.label | ... + ... | -| test.c:207:21:207:31 | ... + ... | semmle.label | ... + ... | -| test.c:209:13:209:21 | middleNaN | semmle.label | middleNaN | -| test.c:211:23:211:31 | middleNaN | semmle.label | middleNaN | -subpaths \ No newline at end of file +| test.c:165:3:165:18 | call to pow | semmle.label | call to pow | +| test.c:170:3:170:15 | call to acos | semmle.label | call to acos | +| test.c:174:22:174:22 | p | semmle.label | p | +| test.c:174:27:174:32 | p | semmle.label | p | +| test.c:182:34:182:34 | p | semmle.label | p | +| test.c:184:13:184:18 | p | semmle.label | p | +| test.c:187:32:187:32 | p | semmle.label | p | +| test.c:187:47:187:51 | ... + ... | semmle.label | ... + ... | +| test.c:189:32:189:32 | p | semmle.label | p | +| test.c:189:47:189:59 | ... + ... | semmle.label | ... + ... | +| test.c:189:47:189:59 | ... + ... | semmle.label | ... + ... | +| test.c:189:51:189:59 | ... / ... | semmle.label | ... / ... | +| test.c:193:13:193:21 | ... / ... | semmle.label | ... / ... | +| test.c:197:23:197:31 | ... / ... | semmle.label | ... / ... | +| test.c:199:25:199:33 | ... / ... | semmle.label | ... / ... | +| test.c:203:19:203:27 | ... / ... | semmle.label | ... / ... | +| test.c:203:19:203:27 | ... / ... | semmle.label | ... / ... | +| test.c:205:21:205:31 | ... + ... | semmle.label | ... + ... | +| test.c:205:21:205:31 | ... + ... | semmle.label | ... + ... | +| test.c:207:13:207:21 | middleNaN | semmle.label | middleNaN | +| test.c:209:23:209:31 | middleNaN | semmle.label | middleNaN | +subpaths diff --git a/c/common/test/rules/misuseofnanfloatingpointvalue/test.c b/c/common/test/rules/misuseofnanfloatingpointvalue/test.c index 5115727115..bd997282f0 100644 --- a/c/common/test/rules/misuseofnanfloatingpointvalue/test.c +++ b/c/common/test/rules/misuseofnanfloatingpointvalue/test.c @@ -160,10 +160,9 @@ void f1(float p1) { (int)pow(2, p1); // COMPLIANT: likely to be Infinity (int)pow(2, sin(p1)); // COMPLIANT: not likely to be Infinity - (int)(1 / - sin(p1)); // COMPLIANT: possible infinity from zero in denominator - (int)(1 / log(p1)); // COMPLIANT: not possibly zero in denominator - (int)pow(p1, p1); // NON_COMPLIANT: NaN if p1 is zero + (int)(1 / sin(p1)); // COMPLIANT: possible infinity from zero in denominator + (int)(1 / log(p1)); // COMPLIANT: not possibly zero in denominator + (int)pow(p1, p1); // NON_COMPLIANT: NaN if p1 is zero if (p1 != 0) { (int)pow(p1, p1); // COMPLIANT: p1 is not zero } @@ -190,8 +189,7 @@ void addInfThenCastToInt(float p) { castToInt(p + 1.0 / 0.0); } void addNaNThenCastToInt(float p) { castToInt(p + 0.0 / 0.0); } void f2() { - castToInt(1.0 / - 0.0); // COMPLIANT: Infinity flows to denominator in division + castToInt(1.0 / 0.0); // COMPLIANT: Infinity flows to denominator in division castToInt(0.0 / 0.0); // COMPLIANT: NaN flows to denominator in division checkBeforeCastToInt(1.0 / 0.0); // COMPLIANT checkBeforeCastToInt(0.0 / 0.0); // COMPLIANT diff --git a/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll index 5d955cc117..d92b46335d 100644 --- a/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll +++ b/cpp/common/src/codingstandards/cpp/RestrictedRangeAnalysis.qll @@ -1093,8 +1093,9 @@ module RestrictedRangeAnalysis { ( // If the expression evaluates to a constant, then there is no // need to call getUpperBoundsImpl. - if exists(getValue(expr).toFloat()) and - not getValue(expr) = "NaN" + if + exists(getValue(expr).toFloat()) and + not getValue(expr) = "NaN" then result = getValue(expr).toFloat() else ( // Some of the bounds computed by `getUpperBoundsImpl` diff --git a/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.expected b/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.expected index 6624187d42..45bc2466b6 100644 --- a/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.expected +++ b/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/MisuseOfInfiniteFloatingPointValue.expected @@ -3,66 +3,66 @@ problems | test.cpp:13:8:13:9 | l3 | test.cpp:8:14:8:20 | ... / ... | test.cpp:13:8:13:9 | l3 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.cpp:8:14:8:20 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | | test.cpp:18:20:18:21 | l2 | test.cpp:8:14:8:20 | ... / ... | test.cpp:18:3:18:22 | l2 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:8:14:8:20 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | | test.cpp:19:20:19:21 | l3 | test.cpp:8:14:8:20 | ... / ... | test.cpp:19:3:19:22 | l3 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:8:14:8:20 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:27:19:27:20 | l2 | test.cpp:8:14:8:20 | ... / ... | test.cpp:27:19:27:20 | l2 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.cpp:8:14:8:20 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:28:19:28:20 | l3 | test.cpp:8:14:8:20 | ... / ... | test.cpp:28:19:28:20 | l3 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.cpp:8:14:8:20 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:38:20:38:21 | l7 | test.cpp:31:14:32:15 | ... / ... | test.cpp:38:3:38:22 | l7 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:31:14:32:15 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:61:22:61:28 | ... / ... | test.cpp:61:5:61:29 | ... / ... | test.cpp:61:5:61:29 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.cpp:61:22:61:28 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:66:22:66:30 | ... / ... | test.cpp:66:5:66:31 | ... / ... | test.cpp:66:5:66:31 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.cpp:66:22:66:30 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:72:31:72:39 | ... / ... | test.cpp:72:14:72:40 | ... / ... | test.cpp:72:14:72:40 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.cpp:72:31:72:39 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:75:35:75:43 | ... / ... | test.cpp:75:18:75:44 | ... / ... | test.cpp:75:18:75:44 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.cpp:75:35:75:43 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:79:22:79:24 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:79:5:79:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:87:22:87:24 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:87:5:87:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:91:22:91:24 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:91:5:91:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:93:22:93:24 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:93:5:93:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:99:22:99:24 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:99:5:99:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:105:22:105:24 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:105:5:105:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:111:22:111:24 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:111:5:111:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:114:38:114:40 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:114:21:114:41 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:117:45:117:47 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:117:28:117:48 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:120:42:120:44 | l12 | test.cpp:77:15:77:21 | ... / ... | test.cpp:120:25:120:45 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:77:15:77:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:163:20:164:20 | ... / ... | test.cpp:163:3:164:21 | ... / ... | test.cpp:163:3:164:21 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.cpp:163:20:164:20 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:175:44:175:44 | p | test.cpp:189:51:189:59 | ... / ... | test.cpp:175:27:175:45 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.cpp:189:51:189:59 | ... / ... | from division by zero | test.cpp:189:6:189:24 | addInfThenCastToInt | addInfThenCastToInt | -| test.cpp:175:44:175:44 | p | test.cpp:193:13:194:15 | ... / ... | test.cpp:175:27:175:45 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.cpp:193:13:194:15 | ... / ... | from division by zero | test.cpp:192:6:192:7 | f2 | f2 | -| test.cpp:175:44:175:44 | p | test.cpp:204:19:204:27 | ... / ... | test.cpp:175:27:175:45 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.cpp:204:19:204:27 | ... / ... | from division by zero | test.cpp:192:6:192:7 | f2 | f2 | -| test.cpp:185:30:185:30 | p | test.cpp:200:25:200:33 | ... / ... | test.cpp:185:13:185:31 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.cpp:200:25:200:33 | ... / ... | from division by zero | test.cpp:192:6:192:7 | f2 | f2 | +| test.cpp:29:19:29:20 | l2 | test.cpp:8:14:8:20 | ... / ... | test.cpp:29:19:29:20 | l2 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.cpp:8:14:8:20 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:30:19:30:20 | l3 | test.cpp:8:14:8:20 | ... / ... | test.cpp:30:19:30:20 | l3 | Possibly infinite float value $@ flows to divisor, which would silently underflow and produce zero. | test.cpp:8:14:8:20 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:40:20:40:21 | l7 | test.cpp:33:14:34:15 | ... / ... | test.cpp:40:3:40:22 | l7 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:33:14:34:15 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:64:9:64:15 | ... / ... | test.cpp:63:5:64:16 | ... / ... | test.cpp:63:5:64:16 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.cpp:64:9:64:15 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:70:9:70:17 | ... / ... | test.cpp:69:5:70:18 | ... / ... | test.cpp:69:5:70:18 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.cpp:70:9:70:17 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:76:31:76:39 | ... / ... | test.cpp:76:14:76:40 | ... / ... | test.cpp:76:14:76:40 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.cpp:76:31:76:39 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:79:35:79:43 | ... / ... | test.cpp:79:18:79:44 | ... / ... | test.cpp:79:18:79:44 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.cpp:79:35:79:43 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:83:22:83:24 | l12 | test.cpp:81:15:81:21 | ... / ... | test.cpp:83:5:83:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:81:15:81:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:91:22:91:24 | l12 | test.cpp:81:15:81:21 | ... / ... | test.cpp:91:5:91:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:81:15:81:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:95:22:95:24 | l12 | test.cpp:81:15:81:21 | ... / ... | test.cpp:95:5:95:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:81:15:81:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:97:22:97:24 | l12 | test.cpp:81:15:81:21 | ... / ... | test.cpp:97:5:97:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:81:15:81:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:103:22:103:24 | l12 | test.cpp:81:15:81:21 | ... / ... | test.cpp:103:5:103:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:81:15:81:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:109:22:109:24 | l12 | test.cpp:81:15:81:21 | ... / ... | test.cpp:109:5:109:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:81:15:81:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:115:22:115:24 | l12 | test.cpp:81:15:81:21 | ... / ... | test.cpp:115:5:115:25 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:81:15:81:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:118:38:118:40 | l12 | test.cpp:81:15:81:21 | ... / ... | test.cpp:118:21:118:41 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:81:15:81:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:127:26:127:28 | l12 | test.cpp:81:15:81:21 | ... / ... | test.cpp:127:9:127:29 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:81:15:81:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:133:26:133:28 | l12 | test.cpp:81:15:81:21 | ... / ... | test.cpp:133:9:133:29 | l12 | Possibly infinite float value $@ flows to cast to integer. | test.cpp:81:15:81:21 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:188:7:189:17 | ... / ... | test.cpp:187:3:189:18 | ... / ... | test.cpp:187:3:189:18 | ... / ... | Possibly infinite float value $@ flows to cast to integer. | test.cpp:188:7:189:17 | ... / ... | from division by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:202:44:202:44 | p | test.cpp:216:51:216:59 | ... / ... | test.cpp:202:27:202:45 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.cpp:216:51:216:59 | ... / ... | from division by zero | test.cpp:216:6:216:24 | addInfThenCastToInt | addInfThenCastToInt | +| test.cpp:202:44:202:44 | p | test.cpp:220:13:221:15 | ... / ... | test.cpp:202:27:202:45 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.cpp:220:13:221:15 | ... / ... | from division by zero | test.cpp:219:6:219:7 | f2 | f2 | +| test.cpp:202:44:202:44 | p | test.cpp:231:19:231:27 | ... / ... | test.cpp:202:27:202:45 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.cpp:231:19:231:27 | ... / ... | from division by zero | test.cpp:219:6:219:7 | f2 | f2 | +| test.cpp:212:30:212:30 | p | test.cpp:227:25:227:33 | ... / ... | test.cpp:212:13:212:31 | p | Possibly infinite float value $@ computed in function $@ flows to cast to integer. | test.cpp:227:25:227:33 | ... / ... | from division by zero | test.cpp:219:6:219:7 | f2 | f2 | edges | test.cpp:8:14:8:20 | ... / ... | test.cpp:8:14:8:20 | ... / ... | provenance | | | test.cpp:8:14:8:20 | ... / ... | test.cpp:9:14:9:16 | - ... | provenance | Config | | test.cpp:8:14:8:20 | ... / ... | test.cpp:12:8:12:9 | l2 | provenance | | | test.cpp:8:14:8:20 | ... / ... | test.cpp:18:3:18:22 | l2 | provenance | | -| test.cpp:8:14:8:20 | ... / ... | test.cpp:27:19:27:20 | l2 | provenance | | +| test.cpp:8:14:8:20 | ... / ... | test.cpp:29:19:29:20 | l2 | provenance | | | test.cpp:9:14:9:16 | - ... | test.cpp:9:14:9:16 | - ... | provenance | | | test.cpp:9:14:9:16 | - ... | test.cpp:13:8:13:9 | l3 | provenance | | | test.cpp:9:14:9:16 | - ... | test.cpp:19:3:19:22 | l3 | provenance | | -| test.cpp:9:14:9:16 | - ... | test.cpp:28:19:28:20 | l3 | provenance | | -| test.cpp:31:14:32:15 | ... / ... | test.cpp:31:14:32:15 | ... / ... | provenance | | -| test.cpp:31:14:32:15 | ... / ... | test.cpp:38:3:38:22 | l7 | provenance | | -| test.cpp:77:15:77:21 | ... / ... | test.cpp:77:15:77:21 | ... / ... | provenance | | -| test.cpp:77:15:77:21 | ... / ... | test.cpp:79:5:79:25 | l12 | provenance | | -| test.cpp:77:15:77:21 | ... / ... | test.cpp:87:5:87:25 | l12 | provenance | | -| test.cpp:77:15:77:21 | ... / ... | test.cpp:91:5:91:25 | l12 | provenance | | -| test.cpp:77:15:77:21 | ... / ... | test.cpp:93:5:93:25 | l12 | provenance | | -| test.cpp:77:15:77:21 | ... / ... | test.cpp:99:5:99:25 | l12 | provenance | | -| test.cpp:77:15:77:21 | ... / ... | test.cpp:105:5:105:25 | l12 | provenance | | -| test.cpp:77:15:77:21 | ... / ... | test.cpp:111:5:111:25 | l12 | provenance | | -| test.cpp:77:15:77:21 | ... / ... | test.cpp:114:21:114:41 | l12 | provenance | | -| test.cpp:77:15:77:21 | ... / ... | test.cpp:117:28:117:48 | l12 | provenance | | -| test.cpp:77:15:77:21 | ... / ... | test.cpp:120:25:120:45 | l12 | provenance | | -| test.cpp:175:22:175:22 | p | test.cpp:175:27:175:45 | p | provenance | | -| test.cpp:183:34:183:34 | p | test.cpp:185:13:185:31 | p | provenance | | -| test.cpp:189:32:189:32 | p | test.cpp:189:47:189:59 | ... + ... | provenance | Config | -| test.cpp:189:47:189:59 | ... + ... | test.cpp:175:22:175:22 | p | provenance | | -| test.cpp:189:47:189:59 | ... + ... | test.cpp:175:22:175:22 | p | provenance | | -| test.cpp:189:51:189:59 | ... / ... | test.cpp:189:47:189:59 | ... + ... | provenance | Config | -| test.cpp:193:13:194:15 | ... / ... | test.cpp:175:22:175:22 | p | provenance | | -| test.cpp:200:25:200:33 | ... / ... | test.cpp:183:34:183:34 | p | provenance | | -| test.cpp:204:19:204:27 | ... / ... | test.cpp:204:19:204:27 | ... / ... | provenance | | -| test.cpp:204:19:204:27 | ... / ... | test.cpp:206:21:206:31 | ... + ... | provenance | Config | -| test.cpp:206:21:206:31 | ... + ... | test.cpp:206:21:206:31 | ... + ... | provenance | | -| test.cpp:206:21:206:31 | ... + ... | test.cpp:208:13:208:21 | middleInf | provenance | | -| test.cpp:206:21:206:31 | ... + ... | test.cpp:210:23:210:31 | middleInf | provenance | | -| test.cpp:208:13:208:21 | middleInf | test.cpp:175:22:175:22 | p | provenance | | -| test.cpp:210:23:210:31 | middleInf | test.cpp:189:32:189:32 | p | provenance | | +| test.cpp:9:14:9:16 | - ... | test.cpp:30:19:30:20 | l3 | provenance | | +| test.cpp:33:14:34:15 | ... / ... | test.cpp:33:14:34:15 | ... / ... | provenance | | +| test.cpp:33:14:34:15 | ... / ... | test.cpp:40:3:40:22 | l7 | provenance | | +| test.cpp:81:15:81:21 | ... / ... | test.cpp:81:15:81:21 | ... / ... | provenance | | +| test.cpp:81:15:81:21 | ... / ... | test.cpp:83:5:83:25 | l12 | provenance | | +| test.cpp:81:15:81:21 | ... / ... | test.cpp:91:5:91:25 | l12 | provenance | | +| test.cpp:81:15:81:21 | ... / ... | test.cpp:95:5:95:25 | l12 | provenance | | +| test.cpp:81:15:81:21 | ... / ... | test.cpp:97:5:97:25 | l12 | provenance | | +| test.cpp:81:15:81:21 | ... / ... | test.cpp:103:5:103:25 | l12 | provenance | | +| test.cpp:81:15:81:21 | ... / ... | test.cpp:109:5:109:25 | l12 | provenance | | +| test.cpp:81:15:81:21 | ... / ... | test.cpp:115:5:115:25 | l12 | provenance | | +| test.cpp:81:15:81:21 | ... / ... | test.cpp:118:21:118:41 | l12 | provenance | | +| test.cpp:81:15:81:21 | ... / ... | test.cpp:127:9:127:29 | l12 | provenance | | +| test.cpp:81:15:81:21 | ... / ... | test.cpp:133:9:133:29 | l12 | provenance | | +| test.cpp:202:22:202:22 | p | test.cpp:202:27:202:45 | p | provenance | | +| test.cpp:210:34:210:34 | p | test.cpp:212:13:212:31 | p | provenance | | +| test.cpp:216:32:216:32 | p | test.cpp:216:47:216:59 | ... + ... | provenance | Config | +| test.cpp:216:47:216:59 | ... + ... | test.cpp:202:22:202:22 | p | provenance | | +| test.cpp:216:47:216:59 | ... + ... | test.cpp:202:22:202:22 | p | provenance | | +| test.cpp:216:51:216:59 | ... / ... | test.cpp:216:47:216:59 | ... + ... | provenance | Config | +| test.cpp:220:13:221:15 | ... / ... | test.cpp:202:22:202:22 | p | provenance | | +| test.cpp:227:25:227:33 | ... / ... | test.cpp:210:34:210:34 | p | provenance | | +| test.cpp:231:19:231:27 | ... / ... | test.cpp:231:19:231:27 | ... / ... | provenance | | +| test.cpp:231:19:231:27 | ... / ... | test.cpp:233:21:233:31 | ... + ... | provenance | Config | +| test.cpp:233:21:233:31 | ... + ... | test.cpp:233:21:233:31 | ... + ... | provenance | | +| test.cpp:233:21:233:31 | ... + ... | test.cpp:235:13:235:21 | middleInf | provenance | | +| test.cpp:233:21:233:31 | ... + ... | test.cpp:237:23:237:31 | middleInf | provenance | | +| test.cpp:235:13:235:21 | middleInf | test.cpp:202:22:202:22 | p | provenance | | +| test.cpp:237:23:237:31 | middleInf | test.cpp:216:32:216:32 | p | provenance | | nodes | test.cpp:8:14:8:20 | ... / ... | semmle.label | ... / ... | | test.cpp:8:14:8:20 | ... / ... | semmle.label | ... / ... | @@ -72,42 +72,42 @@ nodes | test.cpp:13:8:13:9 | l3 | semmle.label | l3 | | test.cpp:18:3:18:22 | l2 | semmle.label | l2 | | test.cpp:19:3:19:22 | l3 | semmle.label | l3 | -| test.cpp:27:19:27:20 | l2 | semmle.label | l2 | -| test.cpp:28:19:28:20 | l3 | semmle.label | l3 | -| test.cpp:31:14:32:15 | ... / ... | semmle.label | ... / ... | -| test.cpp:31:14:32:15 | ... / ... | semmle.label | ... / ... | -| test.cpp:38:3:38:22 | l7 | semmle.label | l7 | -| test.cpp:61:5:61:29 | ... / ... | semmle.label | ... / ... | -| test.cpp:66:5:66:31 | ... / ... | semmle.label | ... / ... | -| test.cpp:72:14:72:40 | ... / ... | semmle.label | ... / ... | -| test.cpp:75:18:75:44 | ... / ... | semmle.label | ... / ... | -| test.cpp:77:15:77:21 | ... / ... | semmle.label | ... / ... | -| test.cpp:77:15:77:21 | ... / ... | semmle.label | ... / ... | -| test.cpp:79:5:79:25 | l12 | semmle.label | l12 | -| test.cpp:87:5:87:25 | l12 | semmle.label | l12 | +| test.cpp:29:19:29:20 | l2 | semmle.label | l2 | +| test.cpp:30:19:30:20 | l3 | semmle.label | l3 | +| test.cpp:33:14:34:15 | ... / ... | semmle.label | ... / ... | +| test.cpp:33:14:34:15 | ... / ... | semmle.label | ... / ... | +| test.cpp:40:3:40:22 | l7 | semmle.label | l7 | +| test.cpp:63:5:64:16 | ... / ... | semmle.label | ... / ... | +| test.cpp:69:5:70:18 | ... / ... | semmle.label | ... / ... | +| test.cpp:76:14:76:40 | ... / ... | semmle.label | ... / ... | +| test.cpp:79:18:79:44 | ... / ... | semmle.label | ... / ... | +| test.cpp:81:15:81:21 | ... / ... | semmle.label | ... / ... | +| test.cpp:81:15:81:21 | ... / ... | semmle.label | ... / ... | +| test.cpp:83:5:83:25 | l12 | semmle.label | l12 | | test.cpp:91:5:91:25 | l12 | semmle.label | l12 | -| test.cpp:93:5:93:25 | l12 | semmle.label | l12 | -| test.cpp:99:5:99:25 | l12 | semmle.label | l12 | -| test.cpp:105:5:105:25 | l12 | semmle.label | l12 | -| test.cpp:111:5:111:25 | l12 | semmle.label | l12 | -| test.cpp:114:21:114:41 | l12 | semmle.label | l12 | -| test.cpp:117:28:117:48 | l12 | semmle.label | l12 | -| test.cpp:120:25:120:45 | l12 | semmle.label | l12 | -| test.cpp:163:3:164:21 | ... / ... | semmle.label | ... / ... | -| test.cpp:175:22:175:22 | p | semmle.label | p | -| test.cpp:175:27:175:45 | p | semmle.label | p | -| test.cpp:183:34:183:34 | p | semmle.label | p | -| test.cpp:185:13:185:31 | p | semmle.label | p | -| test.cpp:189:32:189:32 | p | semmle.label | p | -| test.cpp:189:47:189:59 | ... + ... | semmle.label | ... + ... | -| test.cpp:189:47:189:59 | ... + ... | semmle.label | ... + ... | -| test.cpp:189:51:189:59 | ... / ... | semmle.label | ... / ... | -| test.cpp:193:13:194:15 | ... / ... | semmle.label | ... / ... | -| test.cpp:200:25:200:33 | ... / ... | semmle.label | ... / ... | -| test.cpp:204:19:204:27 | ... / ... | semmle.label | ... / ... | -| test.cpp:204:19:204:27 | ... / ... | semmle.label | ... / ... | -| test.cpp:206:21:206:31 | ... + ... | semmle.label | ... + ... | -| test.cpp:206:21:206:31 | ... + ... | semmle.label | ... + ... | -| test.cpp:208:13:208:21 | middleInf | semmle.label | middleInf | -| test.cpp:210:23:210:31 | middleInf | semmle.label | middleInf | +| test.cpp:95:5:95:25 | l12 | semmle.label | l12 | +| test.cpp:97:5:97:25 | l12 | semmle.label | l12 | +| test.cpp:103:5:103:25 | l12 | semmle.label | l12 | +| test.cpp:109:5:109:25 | l12 | semmle.label | l12 | +| test.cpp:115:5:115:25 | l12 | semmle.label | l12 | +| test.cpp:118:21:118:41 | l12 | semmle.label | l12 | +| test.cpp:127:9:127:29 | l12 | semmle.label | l12 | +| test.cpp:133:9:133:29 | l12 | semmle.label | l12 | +| test.cpp:187:3:189:18 | ... / ... | semmle.label | ... / ... | +| test.cpp:202:22:202:22 | p | semmle.label | p | +| test.cpp:202:27:202:45 | p | semmle.label | p | +| test.cpp:210:34:210:34 | p | semmle.label | p | +| test.cpp:212:13:212:31 | p | semmle.label | p | +| test.cpp:216:32:216:32 | p | semmle.label | p | +| test.cpp:216:47:216:59 | ... + ... | semmle.label | ... + ... | +| test.cpp:216:47:216:59 | ... + ... | semmle.label | ... + ... | +| test.cpp:216:51:216:59 | ... / ... | semmle.label | ... / ... | +| test.cpp:220:13:221:15 | ... / ... | semmle.label | ... / ... | +| test.cpp:227:25:227:33 | ... / ... | semmle.label | ... / ... | +| test.cpp:231:19:231:27 | ... / ... | semmle.label | ... / ... | +| test.cpp:231:19:231:27 | ... / ... | semmle.label | ... / ... | +| test.cpp:233:21:233:31 | ... + ... | semmle.label | ... + ... | +| test.cpp:233:21:233:31 | ... + ... | semmle.label | ... + ... | +| test.cpp:235:13:235:21 | middleInf | semmle.label | middleInf | +| test.cpp:237:23:237:31 | middleInf | semmle.label | middleInf | subpaths diff --git a/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/test.cpp b/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/test.cpp index e9067d8ce7..a0624ccbf3 100644 --- a/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/test.cpp +++ b/cpp/common/test/rules/misuseofinfinitefloatingpointvalue/test.cpp @@ -14,11 +14,13 @@ void f1(float p1) { 10 / p1; // COMPLIANT: Reduce false positives by assuming not infinity 10 / getFloat(); // COMPLIANT: Reduce false positives by assuming not infinity - static_cast(l1); // COMPLIANT - static_cast(l2); // NON_COMPLIANT - static_cast(l3); // NON_COMPLIANT - static_cast(p1); // COMPLIANT: Reduce false positives by assuming not infinity - static_cast(getFloat()); // COMPLIANT: Reduce false positives by assuming not infinity + static_cast(l1); // COMPLIANT + static_cast(l2); // NON_COMPLIANT + static_cast(l3); // NON_COMPLIANT + static_cast( + p1); // COMPLIANT: Reduce false positives by assuming not infinity + static_cast( + getFloat()); // COMPLIANT: Reduce false positives by assuming not infinity // Not NaN: float l4 = l1 / l1; // COMPLIANT @@ -58,12 +60,14 @@ void f1(float p1) { if (l9 != 0) { static_cast(l9 / l9); // COMPLIANT: l9 is not zero } else { - static_cast(l9 / l9); // NON_COMPLIANT[False positive]: Guarded to not be NaN + static_cast( + l9 / l9); // NON_COMPLIANT[False positive]: Guarded to not be NaN } float l10 = 0; if (l10 == 0) { - static_cast(l10 / l10); // NON_COMPLIANT[False positive]: Casting NaN to integer + static_cast( + l10 / l10); // NON_COMPLIANT[False positive]: Casting NaN to integer } else { static_cast(l10 / l10); // COMPLIANT: Guarded to not be NaN } @@ -111,13 +115,22 @@ void f1(float p1) { static_cast(l12); // NON_COMPLIANT: Casting Infinity to integer } - std::isinf(l12) ? static_cast(l12) : 0; // NON_COMPLIANT: Check on wrong branch - std::isinf(l12) ? 0 : static_cast(l12); // COMPLIANT: Checked not infinite before use - std::isfinite(l12) ? static_cast(l12) : 0; // COMPLIANT: Checked finite before use - std::isfinite(l12) ? 0 : static_cast(l12); // NON_COMPLIANT: Checked on wrong branch - std::isnan(l12) ? static_cast(l12) - : 0; // COMPLIANT: Checked NaN, therefore not infinite, before use - std::isnan(l12) ? 0 : static_cast(l12); // NON_COMPLIANT: Check on wrong branch + std::isinf(l12) ? static_cast(l12) + : 0; // NON_COMPLIANT: Check on wrong branch + std::isinf(l12) + ? 0 + : static_cast(l12); // COMPLIANT: Checked not infinite before use + std::isfinite(l12) ? static_cast(l12) + : 0; // COMPLIANT: Checked finite before use + std::isfinite(l12) + ? 0 + : static_cast(l12); // NON_COMPLIANT: Checked on wrong branch + std::isnan(l12) + ? static_cast(l12) + : 0; // COMPLIANT: Checked NaN, therefore not infinite, before use + std::isnan(l12) + ? 0 + : static_cast(l12); // NON_COMPLIANT: Check on wrong branch float l13 = 0.0 / 0; if (std::isinf(l13)) { @@ -127,7 +140,8 @@ void f1(float p1) { } if (std::isinf(l13) == 1) { - static_cast(l13); // COMPLIANT: Guarded not to be NaN (must be +Infinity) + static_cast( + l13); // COMPLIANT: Guarded not to be NaN (must be +Infinity) } else { static_cast(l13); // COMPLIANT: Casting NaN to integer } @@ -150,26 +164,39 @@ void f1(float p1) { static_cast(l13); // COMPLIANT: Guarded not to be NaN } - std::isinf(l13) ? static_cast(l13) - : 0; // COMPLIANT: Checked infinite, therefore not NaN, before use - std::isinf(l13) ? 0 : static_cast(l13); // COMPLIANT: Check on wrong branch - std::isfinite(l13) ? static_cast(l13) : 0; // COMPLIANT: Checked finite before use - std::isfinite(l13) ? 0 : static_cast(l13); // COMPLIANT: Checked on wrong branch - std::isnan(l13) ? static_cast(l13) : 0; // COMPLIANT: Check on wrong branch - std::isnan(l13) ? 0 : static_cast(l13); // COMPLIANT: Checked not NaN before use - - static_cast(std::pow(2, p1)); // NON_COMPLIANT[False negative]: likely to be Infinity - static_cast(std::pow(2, std::sin(p1))); // COMPLIANT: not likely to be Infinity + std::isinf(l13) + ? static_cast(l13) + : 0; // COMPLIANT: Checked infinite, therefore not NaN, before use + std::isinf(l13) ? 0 + : static_cast(l13); // COMPLIANT: Check on wrong branch + std::isfinite(l13) ? static_cast(l13) + : 0; // COMPLIANT: Checked finite before use + std::isfinite(l13) + ? 0 + : static_cast(l13); // COMPLIANT: Checked on wrong branch + std::isnan(l13) ? static_cast(l13) + : 0; // COMPLIANT: Check on wrong branch + std::isnan(l13) + ? 0 + : static_cast(l13); // COMPLIANT: Checked not NaN before use + + static_cast( + std::pow(2, p1)); // NON_COMPLIANT[False negative]: likely to be Infinity + static_cast( + std::pow(2, std::sin(p1))); // COMPLIANT: not likely to be Infinity + static_cast( + 1 / std::sin( + p1)); // NON_COMPLIANT: possible infinity from zero in denominator static_cast(1 / - std::sin(p1)); // NON_COMPLIANT: possible infinity from zero in denominator - static_cast(1 / std::log(p1)); // COMPLIANT: not possibly zero in denominator - static_cast(std::pow(p1, p1)); // COMPLIANT: NaN if p1 is zero + std::log(p1)); // COMPLIANT: not possibly zero in denominator + static_cast(std::pow(p1, p1)); // COMPLIANT: NaN if p1 is zero if (p1 != 0) { static_cast(std::pow(p1, p1)); // COMPLIANT: p1 is not zero } - static_cast(std::acos(p1)); // COMPLIANT: NaN if p1 is not within -1..1 - static_cast(std::acos(std::cos(p1))); // COMPLIANT: cos(p1) is within -1..1 + static_cast(std::acos(p1)); // COMPLIANT: NaN if p1 is not within -1..1 + static_cast( + std::acos(std::cos(p1))); // COMPLIANT: cos(p1) is within -1..1 } void castToInt(float p) { static_cast(p); } @@ -192,7 +219,7 @@ void addNaNThenCastToInt(float p) { castToInt(p + 0.0 / 0.0); } void f2() { castToInt(1.0 / 0.0); // NON_COMPLIANT: Infinity flows to denominator in division - castToInt(0.0 / 0.0); // COMPLIANT + castToInt(0.0 / 0.0); // COMPLIANT checkBeforeCastToInt(1.0 / 0.0); // COMPLIANT checkBeforeCastToInt(0.0 / 0.0); // COMPLIANT addOneThenCastToInt(1.0 / 0.0); // NON_COMPLIANT[False negative] diff --git a/cpp/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected b/cpp/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected index 576327fb21..5e4d3cacd7 100644 --- a/cpp/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected +++ b/cpp/common/test/rules/misuseofnanfloatingpointvalue/MisuseOfNaNFloatingPointValue.expected @@ -16,21 +16,21 @@ problems | test.cpp:66:11:66:19 | ... / ... | test.cpp:66:5:66:20 | ... / ... | test.cpp:66:5:66:20 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.cpp:66:11:66:19 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | | test.cpp:72:20:72:28 | ... / ... | test.cpp:72:14:72:29 | ... / ... | test.cpp:72:14:72:29 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.cpp:72:20:72:28 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | | test.cpp:75:24:75:32 | ... / ... | test.cpp:75:18:75:33 | ... / ... | test.cpp:75:18:75:33 | ... / ... | Possible NaN value $@ flows to a cast to integer. | test.cpp:75:24:75:32 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:126:10:126:12 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:126:5:126:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:132:10:132:12 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:132:5:132:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:138:10:138:12 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:138:5:138:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:144:10:144:12 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:144:5:144:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:148:10:148:12 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:148:5:148:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:155:30:155:32 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:155:25:155:32 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:157:33:157:35 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:157:28:157:35 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:158:26:158:28 | l13 | test.cpp:122:15:122:21 | ... / ... | test.cpp:158:21:158:28 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:122:15:122:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:166:8:166:15 | call to pow | test.cpp:166:3:166:23 | call to pow | test.cpp:166:3:166:23 | call to pow | Possible NaN value $@ flows to a cast to integer. | test.cpp:166:8:166:15 | call to pow | both arguments are equal to zero | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:171:8:171:16 | call to acos | test.cpp:171:3:171:20 | call to acos | test.cpp:171:3:171:20 | call to acos | Possible NaN value $@ flows to a cast to integer. | test.cpp:171:8:171:16 | call to acos | the argument has a range -1000000000000000...1000000000000000 which is outside the domain of this function (-1.0...1.0) | test.cpp:6:6:6:7 | f1 | f1 | -| test.cpp:175:32:175:32 | p | test.cpp:190:51:190:59 | ... / ... | test.cpp:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.cpp:190:51:190:59 | ... / ... | from division of zero by zero | test.cpp:190:6:190:24 | addNaNThenCastToInt | addNaNThenCastToInt | -| test.cpp:175:32:175:32 | p | test.cpp:195:13:195:21 | ... / ... | test.cpp:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.cpp:195:13:195:21 | ... / ... | from division of zero by zero | test.cpp:192:6:192:7 | f2 | f2 | -| test.cpp:175:32:175:32 | p | test.cpp:199:23:199:31 | ... / ... | test.cpp:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.cpp:199:23:199:31 | ... / ... | from division of zero by zero | test.cpp:192:6:192:7 | f2 | f2 | -| test.cpp:175:32:175:32 | p | test.cpp:205:19:205:27 | ... / ... | test.cpp:175:27:175:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.cpp:205:19:205:27 | ... / ... | from division of zero by zero | test.cpp:192:6:192:7 | f2 | f2 | -| test.cpp:185:18:185:18 | p | test.cpp:201:25:201:33 | ... / ... | test.cpp:185:13:185:18 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.cpp:201:25:201:33 | ... / ... | from division of zero by zero | test.cpp:192:6:192:7 | f2 | f2 | +| test.cpp:127:10:127:12 | l13 | test.cpp:123:15:123:21 | ... / ... | test.cpp:127:5:127:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:123:15:123:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:133:10:133:12 | l13 | test.cpp:123:15:123:21 | ... / ... | test.cpp:133:5:133:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:123:15:123:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:139:10:139:12 | l13 | test.cpp:123:15:123:21 | ... / ... | test.cpp:139:5:139:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:123:15:123:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:145:10:145:12 | l13 | test.cpp:123:15:123:21 | ... / ... | test.cpp:145:5:145:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:123:15:123:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:149:10:149:12 | l13 | test.cpp:123:15:123:21 | ... / ... | test.cpp:149:5:149:12 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:123:15:123:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:157:30:157:32 | l13 | test.cpp:123:15:123:21 | ... / ... | test.cpp:157:25:157:32 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:123:15:123:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:159:33:159:35 | l13 | test.cpp:123:15:123:21 | ... / ... | test.cpp:159:28:159:35 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:123:15:123:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:160:26:160:28 | l13 | test.cpp:123:15:123:21 | ... / ... | test.cpp:160:21:160:28 | l13 | Possible NaN value $@ flows to a cast to integer. | test.cpp:123:15:123:21 | ... / ... | from division of zero by zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:168:8:168:15 | call to pow | test.cpp:168:3:168:23 | call to pow | test.cpp:168:3:168:23 | call to pow | Possible NaN value $@ flows to a cast to integer. | test.cpp:168:8:168:15 | call to pow | both arguments are equal to zero | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:173:8:173:16 | call to acos | test.cpp:173:3:173:20 | call to acos | test.cpp:173:3:173:20 | call to acos | Possible NaN value $@ flows to a cast to integer. | test.cpp:173:8:173:16 | call to acos | the argument has a range -1000000000000000...1000000000000000 which is outside the domain of this function (-1.0...1.0) | test.cpp:6:6:6:7 | f1 | f1 | +| test.cpp:177:32:177:32 | p | test.cpp:192:51:192:59 | ... / ... | test.cpp:177:27:177:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.cpp:192:51:192:59 | ... / ... | from division of zero by zero | test.cpp:192:6:192:24 | addNaNThenCastToInt | addNaNThenCastToInt | +| test.cpp:177:32:177:32 | p | test.cpp:196:13:196:21 | ... / ... | test.cpp:177:27:177:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.cpp:196:13:196:21 | ... / ... | from division of zero by zero | test.cpp:194:6:194:7 | f2 | f2 | +| test.cpp:177:32:177:32 | p | test.cpp:200:23:200:31 | ... / ... | test.cpp:177:27:177:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.cpp:200:23:200:31 | ... / ... | from division of zero by zero | test.cpp:194:6:194:7 | f2 | f2 | +| test.cpp:177:32:177:32 | p | test.cpp:206:19:206:27 | ... / ... | test.cpp:177:27:177:32 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.cpp:206:19:206:27 | ... / ... | from division of zero by zero | test.cpp:194:6:194:7 | f2 | f2 | +| test.cpp:187:18:187:18 | p | test.cpp:202:25:202:33 | ... / ... | test.cpp:187:13:187:18 | p | Possible NaN value $@ computed in function $@ flows to a cast to integer. | test.cpp:202:25:202:33 | ... / ... | from division of zero by zero | test.cpp:194:6:194:7 | f2 | f2 | edges | test.cpp:27:14:27:20 | ... / ... | test.cpp:27:14:27:20 | ... / ... | provenance | | | test.cpp:27:14:27:20 | ... / ... | test.cpp:36:3:36:9 | l5 | provenance | | @@ -49,33 +49,33 @@ edges | test.cpp:33:14:33:22 | ... / ... | test.cpp:33:14:33:22 | ... / ... | provenance | | | test.cpp:33:14:33:22 | ... / ... | test.cpp:39:3:39:9 | l8 | provenance | | | test.cpp:33:14:33:22 | ... / ... | test.cpp:54:3:54:4 | l8 | provenance | | -| test.cpp:122:15:122:21 | ... / ... | test.cpp:122:15:122:21 | ... / ... | provenance | | -| test.cpp:122:15:122:21 | ... / ... | test.cpp:126:5:126:12 | l13 | provenance | | -| test.cpp:122:15:122:21 | ... / ... | test.cpp:132:5:132:12 | l13 | provenance | | -| test.cpp:122:15:122:21 | ... / ... | test.cpp:138:5:138:12 | l13 | provenance | | -| test.cpp:122:15:122:21 | ... / ... | test.cpp:144:5:144:12 | l13 | provenance | | -| test.cpp:122:15:122:21 | ... / ... | test.cpp:148:5:148:12 | l13 | provenance | | -| test.cpp:122:15:122:21 | ... / ... | test.cpp:155:25:155:32 | l13 | provenance | | -| test.cpp:122:15:122:21 | ... / ... | test.cpp:157:28:157:35 | l13 | provenance | | -| test.cpp:122:15:122:21 | ... / ... | test.cpp:158:21:158:28 | l13 | provenance | | -| test.cpp:175:22:175:22 | p | test.cpp:175:27:175:32 | p | provenance | | -| test.cpp:183:34:183:34 | p | test.cpp:185:13:185:18 | p | provenance | | -| test.cpp:188:32:188:32 | p | test.cpp:188:47:188:51 | ... + ... | provenance | Config | -| test.cpp:188:47:188:51 | ... + ... | test.cpp:175:22:175:22 | p | provenance | | -| test.cpp:190:32:190:32 | p | test.cpp:190:47:190:59 | ... + ... | provenance | Config | -| test.cpp:190:47:190:59 | ... + ... | test.cpp:175:22:175:22 | p | provenance | | -| test.cpp:190:47:190:59 | ... + ... | test.cpp:175:22:175:22 | p | provenance | | -| test.cpp:190:51:190:59 | ... / ... | test.cpp:190:47:190:59 | ... + ... | provenance | Config | -| test.cpp:195:13:195:21 | ... / ... | test.cpp:175:22:175:22 | p | provenance | | -| test.cpp:199:23:199:31 | ... / ... | test.cpp:188:32:188:32 | p | provenance | | -| test.cpp:201:25:201:33 | ... / ... | test.cpp:183:34:183:34 | p | provenance | | -| test.cpp:205:19:205:27 | ... / ... | test.cpp:205:19:205:27 | ... / ... | provenance | | -| test.cpp:205:19:205:27 | ... / ... | test.cpp:207:21:207:31 | ... + ... | provenance | Config | -| test.cpp:207:21:207:31 | ... + ... | test.cpp:207:21:207:31 | ... + ... | provenance | | -| test.cpp:207:21:207:31 | ... + ... | test.cpp:209:13:209:21 | middleNaN | provenance | | -| test.cpp:207:21:207:31 | ... + ... | test.cpp:211:23:211:31 | middleNaN | provenance | | -| test.cpp:209:13:209:21 | middleNaN | test.cpp:175:22:175:22 | p | provenance | | -| test.cpp:211:23:211:31 | middleNaN | test.cpp:190:32:190:32 | p | provenance | | +| test.cpp:123:15:123:21 | ... / ... | test.cpp:123:15:123:21 | ... / ... | provenance | | +| test.cpp:123:15:123:21 | ... / ... | test.cpp:127:5:127:12 | l13 | provenance | | +| test.cpp:123:15:123:21 | ... / ... | test.cpp:133:5:133:12 | l13 | provenance | | +| test.cpp:123:15:123:21 | ... / ... | test.cpp:139:5:139:12 | l13 | provenance | | +| test.cpp:123:15:123:21 | ... / ... | test.cpp:145:5:145:12 | l13 | provenance | | +| test.cpp:123:15:123:21 | ... / ... | test.cpp:149:5:149:12 | l13 | provenance | | +| test.cpp:123:15:123:21 | ... / ... | test.cpp:157:25:157:32 | l13 | provenance | | +| test.cpp:123:15:123:21 | ... / ... | test.cpp:159:28:159:35 | l13 | provenance | | +| test.cpp:123:15:123:21 | ... / ... | test.cpp:160:21:160:28 | l13 | provenance | | +| test.cpp:177:22:177:22 | p | test.cpp:177:27:177:32 | p | provenance | | +| test.cpp:185:34:185:34 | p | test.cpp:187:13:187:18 | p | provenance | | +| test.cpp:190:32:190:32 | p | test.cpp:190:47:190:51 | ... + ... | provenance | Config | +| test.cpp:190:47:190:51 | ... + ... | test.cpp:177:22:177:22 | p | provenance | | +| test.cpp:192:32:192:32 | p | test.cpp:192:47:192:59 | ... + ... | provenance | Config | +| test.cpp:192:47:192:59 | ... + ... | test.cpp:177:22:177:22 | p | provenance | | +| test.cpp:192:47:192:59 | ... + ... | test.cpp:177:22:177:22 | p | provenance | | +| test.cpp:192:51:192:59 | ... / ... | test.cpp:192:47:192:59 | ... + ... | provenance | Config | +| test.cpp:196:13:196:21 | ... / ... | test.cpp:177:22:177:22 | p | provenance | | +| test.cpp:200:23:200:31 | ... / ... | test.cpp:190:32:190:32 | p | provenance | | +| test.cpp:202:25:202:33 | ... / ... | test.cpp:185:34:185:34 | p | provenance | | +| test.cpp:206:19:206:27 | ... / ... | test.cpp:206:19:206:27 | ... / ... | provenance | | +| test.cpp:206:19:206:27 | ... / ... | test.cpp:208:21:208:31 | ... + ... | provenance | Config | +| test.cpp:208:21:208:31 | ... + ... | test.cpp:208:21:208:31 | ... + ... | provenance | | +| test.cpp:208:21:208:31 | ... + ... | test.cpp:210:13:210:21 | middleNaN | provenance | | +| test.cpp:208:21:208:31 | ... + ... | test.cpp:212:23:212:31 | middleNaN | provenance | | +| test.cpp:210:13:210:21 | middleNaN | test.cpp:177:22:177:22 | p | provenance | | +| test.cpp:212:23:212:31 | middleNaN | test.cpp:192:32:192:32 | p | provenance | | nodes | test.cpp:27:14:27:20 | ... / ... | semmle.label | ... / ... | | test.cpp:27:14:27:20 | ... / ... | semmle.label | ... / ... | @@ -102,35 +102,35 @@ nodes | test.cpp:66:5:66:20 | ... / ... | semmle.label | ... / ... | | test.cpp:72:14:72:29 | ... / ... | semmle.label | ... / ... | | test.cpp:75:18:75:33 | ... / ... | semmle.label | ... / ... | -| test.cpp:122:15:122:21 | ... / ... | semmle.label | ... / ... | -| test.cpp:122:15:122:21 | ... / ... | semmle.label | ... / ... | -| test.cpp:126:5:126:12 | l13 | semmle.label | l13 | -| test.cpp:132:5:132:12 | l13 | semmle.label | l13 | -| test.cpp:138:5:138:12 | l13 | semmle.label | l13 | -| test.cpp:144:5:144:12 | l13 | semmle.label | l13 | -| test.cpp:148:5:148:12 | l13 | semmle.label | l13 | -| test.cpp:155:25:155:32 | l13 | semmle.label | l13 | -| test.cpp:157:28:157:35 | l13 | semmle.label | l13 | -| test.cpp:158:21:158:28 | l13 | semmle.label | l13 | -| test.cpp:166:3:166:23 | call to pow | semmle.label | call to pow | -| test.cpp:171:3:171:20 | call to acos | semmle.label | call to acos | -| test.cpp:175:22:175:22 | p | semmle.label | p | -| test.cpp:175:27:175:32 | p | semmle.label | p | -| test.cpp:183:34:183:34 | p | semmle.label | p | -| test.cpp:185:13:185:18 | p | semmle.label | p | -| test.cpp:188:32:188:32 | p | semmle.label | p | -| test.cpp:188:47:188:51 | ... + ... | semmle.label | ... + ... | +| test.cpp:123:15:123:21 | ... / ... | semmle.label | ... / ... | +| test.cpp:123:15:123:21 | ... / ... | semmle.label | ... / ... | +| test.cpp:127:5:127:12 | l13 | semmle.label | l13 | +| test.cpp:133:5:133:12 | l13 | semmle.label | l13 | +| test.cpp:139:5:139:12 | l13 | semmle.label | l13 | +| test.cpp:145:5:145:12 | l13 | semmle.label | l13 | +| test.cpp:149:5:149:12 | l13 | semmle.label | l13 | +| test.cpp:157:25:157:32 | l13 | semmle.label | l13 | +| test.cpp:159:28:159:35 | l13 | semmle.label | l13 | +| test.cpp:160:21:160:28 | l13 | semmle.label | l13 | +| test.cpp:168:3:168:23 | call to pow | semmle.label | call to pow | +| test.cpp:173:3:173:20 | call to acos | semmle.label | call to acos | +| test.cpp:177:22:177:22 | p | semmle.label | p | +| test.cpp:177:27:177:32 | p | semmle.label | p | +| test.cpp:185:34:185:34 | p | semmle.label | p | +| test.cpp:187:13:187:18 | p | semmle.label | p | | test.cpp:190:32:190:32 | p | semmle.label | p | -| test.cpp:190:47:190:59 | ... + ... | semmle.label | ... + ... | -| test.cpp:190:47:190:59 | ... + ... | semmle.label | ... + ... | -| test.cpp:190:51:190:59 | ... / ... | semmle.label | ... / ... | -| test.cpp:195:13:195:21 | ... / ... | semmle.label | ... / ... | -| test.cpp:199:23:199:31 | ... / ... | semmle.label | ... / ... | -| test.cpp:201:25:201:33 | ... / ... | semmle.label | ... / ... | -| test.cpp:205:19:205:27 | ... / ... | semmle.label | ... / ... | -| test.cpp:205:19:205:27 | ... / ... | semmle.label | ... / ... | -| test.cpp:207:21:207:31 | ... + ... | semmle.label | ... + ... | -| test.cpp:207:21:207:31 | ... + ... | semmle.label | ... + ... | -| test.cpp:209:13:209:21 | middleNaN | semmle.label | middleNaN | -| test.cpp:211:23:211:31 | middleNaN | semmle.label | middleNaN | +| test.cpp:190:47:190:51 | ... + ... | semmle.label | ... + ... | +| test.cpp:192:32:192:32 | p | semmle.label | p | +| test.cpp:192:47:192:59 | ... + ... | semmle.label | ... + ... | +| test.cpp:192:47:192:59 | ... + ... | semmle.label | ... + ... | +| test.cpp:192:51:192:59 | ... / ... | semmle.label | ... / ... | +| test.cpp:196:13:196:21 | ... / ... | semmle.label | ... / ... | +| test.cpp:200:23:200:31 | ... / ... | semmle.label | ... / ... | +| test.cpp:202:25:202:33 | ... / ... | semmle.label | ... / ... | +| test.cpp:206:19:206:27 | ... / ... | semmle.label | ... / ... | +| test.cpp:206:19:206:27 | ... / ... | semmle.label | ... / ... | +| test.cpp:208:21:208:31 | ... + ... | semmle.label | ... + ... | +| test.cpp:208:21:208:31 | ... + ... | semmle.label | ... + ... | +| test.cpp:210:13:210:21 | middleNaN | semmle.label | middleNaN | +| test.cpp:212:23:212:31 | middleNaN | semmle.label | middleNaN | subpaths diff --git a/cpp/common/test/rules/misuseofnanfloatingpointvalue/test.cpp b/cpp/common/test/rules/misuseofnanfloatingpointvalue/test.cpp index 51540bc3a1..a68a47daf7 100644 --- a/cpp/common/test/rules/misuseofnanfloatingpointvalue/test.cpp +++ b/cpp/common/test/rules/misuseofnanfloatingpointvalue/test.cpp @@ -111,12 +111,13 @@ void f1(float p1) { (int)l12; // COMPLIANT: Casting Infinity to integer } - std::isinf(l12) ? (int)l12 : 0; // COMPLIANT: Check on wrong branch - std::isinf(l12) ? 0 : (int)l12; // COMPLIANT: Checked not infinite before use + std::isinf(l12) ? (int)l12 : 0; // COMPLIANT: Check on wrong branch + std::isinf(l12) ? 0 : (int)l12; // COMPLIANT: Checked not infinite before use std::isfinite(l12) ? (int)l12 : 0; // COMPLIANT: Checked finite before use std::isfinite(l12) ? 0 : (int)l12; // COMPLIANT: Checked on wrong branch - std::isnan(l12) ? (int)l12 - : 0; // COMPLIANT: Checked NaN, therefore not infinite, before use + std::isnan(l12) + ? (int)l12 + : 0; // COMPLIANT: Checked NaN, therefore not infinite, before use std::isnan(l12) ? 0 : (int)l12; // COMPLIANT: Check on wrong branch float l13 = 0.0 / 0; @@ -150,15 +151,16 @@ void f1(float p1) { (int)l13; // COMPLIANT: Guarded not to be NaN } - std::isinf(l13) ? (int)l13 - : 0; // COMPLIANT: Checked infinite, therefore not NaN, before use + std::isinf(l13) + ? (int)l13 + : 0; // COMPLIANT: Checked infinite, therefore not NaN, before use std::isinf(l13) ? 0 : (int)l13; // NON_COMPLIANT: Check on wrong branch std::isfinite(l13) ? (int)l13 : 0; // COMPLIANT: Checked finite before use std::isfinite(l13) ? 0 : (int)l13; // NON_COMPLIANT: Checked on wrong branch std::isnan(l13) ? (int)l13 : 0; // NON_COMPLIANT: Check on wrong branch std::isnan(l13) ? 0 : (int)l13; // COMPLIANT: Checked not NaN before use - (int)std::pow(2, p1); // COMPLIANT: likely to be Infinity + (int)std::pow(2, p1); // COMPLIANT: likely to be Infinity (int)std::pow(2, std::sin(p1)); // COMPLIANT: not likely to be Infinity (int)(1 / std::sin(p1)); // COMPLIANT: possible infinity from zero in denominator @@ -168,7 +170,7 @@ void f1(float p1) { (int)std::pow(p1, p1); // COMPLIANT: p1 is not zero } - (int)std::acos(p1); // NON_COMPLIANT: NaN if p1 is not within -1..1 + (int)std::acos(p1); // NON_COMPLIANT: NaN if p1 is not within -1..1 (int)std::acos(std::cos(p1)); // COMPLIANT: cos(p1) is within -1..1 } @@ -190,8 +192,7 @@ void addInfThenCastToInt(float p) { castToInt(p + 1.0 / 0.0); } void addNaNThenCastToInt(float p) { castToInt(p + 0.0 / 0.0); } void f2() { - castToInt(1.0 / - 0.0); // COMPLIANT: Infinity flows to denominator in division + castToInt(1.0 / 0.0); // COMPLIANT: Infinity flows to denominator in division castToInt(0.0 / 0.0); // COMPLIANT: NaN flows to denominator in division checkBeforeCastToInt(1.0 / 0.0); // COMPLIANT checkBeforeCastToInt(0.0 / 0.0); // COMPLIANT diff --git a/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.ql b/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.ql index d9810c1135..ee7139543d 100644 --- a/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.ql +++ b/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.ql @@ -15,7 +15,8 @@ import cpp import codingstandards.cpp.misra import codingstandards.cpp.rules.misuseofinfinitefloatingpointvalue.MisuseOfInfiniteFloatingPointValue -class PossibleMisuseOfInfiniteFloatingPointValueQuery extends MisuseOfInfiniteFloatingPointValueSharedQuery { +class PossibleMisuseOfInfiniteFloatingPointValueQuery extends MisuseOfInfiniteFloatingPointValueSharedQuery +{ PossibleMisuseOfInfiniteFloatingPointValueQuery() { this = FloatingPointPackage::possibleMisuseOfInfiniteFloatingPointValueQuery() } diff --git a/rule_packages/cpp/FloatingPoint.json b/rule_packages/cpp/FloatingPoint.json index b085e5b289..672e57acff 100644 --- a/rule_packages/cpp/FloatingPoint.json +++ b/rule_packages/cpp/FloatingPoint.json @@ -14,8 +14,7 @@ "short_name": "PossibleMisuseOfInfiniteFloatingPointValue", "shared_implementation_short_name": "MisuseOfInfiniteFloatingPointValue", "tags": [ - "correctness", - "external/misra/c/2012/amendment3" + "correctness" ] }, { @@ -27,8 +26,7 @@ "short_name": "PossibleMisuseOfNaNFloatingPointValue", "shared_implementation_short_name": "MisuseOfNaNFloatingPointValue", "tags": [ - "correctness", - "external/misra/c/2012/amendment3" + "correctness" ] } ], From 551c2343036c4a7eafa3397d134a91bc4158dff9 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 15 Apr 2025 08:03:15 -0700 Subject: [PATCH 300/370] Missing format, regenerate query metadata --- c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql | 2 +- .../DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.ql | 1 - .../rules/DIR-0-3-1/PossibleMisuseOfNaNFloatingPointValue.ql | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql index 10bfcafeba..9315a4ed4c 100644 --- a/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql +++ b/c/misra/src/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql @@ -20,4 +20,4 @@ class PossibleMisuseOfUndetectedNaNQuery extends MisuseOfNaNFloatingPointValueSh PossibleMisuseOfUndetectedNaNQuery() { this = FloatingTypes2Package::possibleMisuseOfUndetectedNaNQuery() } -} \ No newline at end of file +} diff --git a/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.ql b/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.ql index ee7139543d..0e3363137e 100644 --- a/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.ql +++ b/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfInfiniteFloatingPointValue.ql @@ -7,7 +7,6 @@ * @problem.severity warning * @tags external/misra/id/dir-0-3-1 * correctness - * external/misra/c/2012/amendment3 * external/misra/obligation/advisory */ diff --git a/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfNaNFloatingPointValue.ql b/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfNaNFloatingPointValue.ql index 934ee6d998..035edd85b8 100644 --- a/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfNaNFloatingPointValue.ql +++ b/cpp/misra/src/rules/DIR-0-3-1/PossibleMisuseOfNaNFloatingPointValue.ql @@ -8,7 +8,6 @@ * @problem.severity warning * @tags external/misra/id/dir-0-3-1 * correctness - * external/misra/c/2012/amendment3 * external/misra/obligation/advisory */ From 160db8381893017f0a31290b8501d53d4bcdb1cd Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 15 Apr 2025 10:18:43 -0700 Subject: [PATCH 301/370] Remove deleted test qlrefs --- .../test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.qlref | 1 - c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.qlref | 1 - 2 files changed, 2 deletions(-) delete mode 100644 c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.qlref delete mode 100644 c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.qlref diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.qlref b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.qlref deleted file mode 100644 index dccac37c5f..0000000000 --- a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/DIR-4-15/PossibleMisuseOfUndetectedInfinity.ql \ No newline at end of file diff --git a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.qlref b/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.qlref deleted file mode 100644 index d88c172bd5..0000000000 --- a/c/misra/test/rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/DIR-4-15/PossibleMisuseOfUndetectedNaN.ql \ No newline at end of file From d8ac07f96918e85310d5baa0dcbe34f25b57e163 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 21 Apr 2025 23:07:01 +0100 Subject: [PATCH 302/370] Add missing results --- .../deviations_report_deviated/UnusedReturnValue.expected | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.expected b/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.expected index 7b8860d5a3..ab75d81f6f 100644 --- a/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.expected +++ b/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.expected @@ -1,3 +1,8 @@ | main.cpp:10:3:10:6 | call to getX | Return value from call to $@ is unused. | main.cpp:6:5:6:8 | getX | getX | +| main.cpp:23:3:23:6 | call to getX | Return value from call to $@ is unused. | main.cpp:6:5:6:8 | getX | getX | +| main.cpp:25:3:25:6 | call to getX | Return value from call to $@ is unused. | main.cpp:6:5:6:8 | getX | getX | +| main.cpp:31:3:31:6 | call to getX | Return value from call to $@ is unused. | main.cpp:6:5:6:8 | getX | getX | +| main.cpp:33:3:33:6 | call to getX | Return value from call to $@ is unused. | main.cpp:6:5:6:8 | getX | getX | +| main.cpp:37:3:37:6 | call to getX | Return value from call to $@ is unused. | main.cpp:6:5:6:8 | getX | getX | | nested/nested2/test2.h:5:3:5:6 | call to getZ | Return value from call to $@ is unused. | nested/nested2/test2.h:1:5:1:8 | getZ | getZ | | nested/test.h:5:3:5:6 | call to getY | Return value from call to $@ is unused. | nested/test.h:1:5:1:8 | getY | getY | From 52e64673fee3cf653027a2924b5d3095bf81b457 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 21 Apr 2025 23:17:15 +0100 Subject: [PATCH 303/370] Add comment --- .../cpp/deviations/CodeIdentifierDeviation.qll | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll index 4b2f03cf98..b7a144f429 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll @@ -341,6 +341,11 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation { ) } + /** + * Holds for the region matched by this code identifier deviation. + * + * Note: this is not the location of the marker itself. + */ predicate hasLocationInfo( string filepath, int suppressedLine, int suppressedColumn, int endline, int endcolumn ) { From 184e5d3ed5bde1cd8ae5895cff70254a0ae36104 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 21 Apr 2025 23:22:27 +0100 Subject: [PATCH 304/370] Extract common library for location handling --- .../src/codingstandards/cpp/Locations.qll | 24 ++++++++++++++ .../cpp/deviations/DeviationsSuppression.ql | 31 +++---------------- 2 files changed, 28 insertions(+), 27 deletions(-) create mode 100644 cpp/common/src/codingstandards/cpp/Locations.qll diff --git a/cpp/common/src/codingstandards/cpp/Locations.qll b/cpp/common/src/codingstandards/cpp/Locations.qll new file mode 100644 index 0000000000..83dd0448af --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/Locations.qll @@ -0,0 +1,24 @@ +import cpp + +/** Holds if `lineNumber` is an indexed line number in file `f`. */ +predicate isLineNumber(File f, int lineNumber) { + exists(Location l | l.getFile() = f | + l.getStartLine() = lineNumber + or + l.getEndLine() = lineNumber + ) +} + +/** Gets the last line number in `f`. */ +int getLastLineNumber(File f) { result = max(int lineNumber | isLineNumber(f, lineNumber)) } + +/** Gets the last column number on the last line of `f`. */ +int getLastColumnNumber(File f) { + result = + max(Location l | + l.getFile() = f and + l.getEndLine() = getLastLineNumber(f) + | + l.getEndColumn() + ) +} diff --git a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql index f29c068983..94f45c74b3 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql +++ b/cpp/common/src/codingstandards/cpp/deviations/DeviationsSuppression.ql @@ -7,29 +7,7 @@ import cpp import Deviations - -/** Holds if `lineNumber` is an indexed line number in file `f`. */ -private predicate isLineNumber(File f, int lineNumber) { - exists(Location l | l.getFile() = f | - l.getStartLine() = lineNumber - or - l.getEndLine() = lineNumber - ) -} - -/** Gets the last line number in `f`. */ -private int getLastLineNumber(File f) { result = max(int lineNumber | isLineNumber(f, lineNumber)) } - -/** Gets the last column number on the last line of `f`. */ -int getLastColumnNumber(File f) { - result = - max(Location l | - l.getFile() = f and - l.getEndLine() = getLastLineNumber(f) - | - l.getEndColumn() - ) -} +import codingstandards.cpp.Locations newtype TDeviationScope = TDeviationRecordFileScope(DeviationRecord dr, File file) { @@ -71,10 +49,9 @@ class DeviationRecordFileScope extends DeviationScope, TDeviationRecordFileScope string filepath, int startline, int startcolumn, int endline, int endcolumn ) { // In an ideal world, we would produce a URL here that informed the AlertSuppression code that - // the whole file was suppressed. However, experimentation suggestions the alert suppression - // code only works with locations with lines and columns, so we generate a location that covers - // the whole "indexed" file, by finding the location indexed in the database with the latest - // line and column number. + // the whole file was suppressed. However, the alert suppression code only works with locations + // with lines and columns, so we generate a location that covers the whole "indexed" file, by + // finding the location indexed in the database with the latest line and column number. exists(File f | f = getFile() | f.getLocation().hasLocationInfo(filepath, _, _, _, _) and startline = 1 and From 126ed553e5026853250e3c62e59768eb3abd540b Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 21 Apr 2025 23:30:54 +0100 Subject: [PATCH 305/370] Add getLastColumnNumber to shared library --- cpp/common/src/codingstandards/cpp/Locations.qll | 6 ++++++ .../cpp/deviations/CodeIdentifierDeviation.qll | 9 ++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/Locations.qll b/cpp/common/src/codingstandards/cpp/Locations.qll index 83dd0448af..800f44d18a 100644 --- a/cpp/common/src/codingstandards/cpp/Locations.qll +++ b/cpp/common/src/codingstandards/cpp/Locations.qll @@ -22,3 +22,9 @@ int getLastColumnNumber(File f) { l.getEndColumn() ) } + +/** Gets the last column number on the given line of `filepath`. */ +bindingset[filepath, lineNumber] +int getLastColumnNumber(string filepath, int lineNumber) { + result = max(Location l | l.hasLocationInfo(filepath, _, _, lineNumber, _) | l.getEndColumn()) +} diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll index b7a144f429..137a2a72d7 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll @@ -32,6 +32,7 @@ import cpp import Deviations +import codingstandards.cpp.Locations string supportedStandard() { result = ["misra", "autosar", "cert"] } @@ -358,13 +359,7 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation { then endcolumn = commentMarker.(DeviationEndOfLineMarker).getLocation().getEndColumn() else // Find the last column for a location on the next line - endcolumn = - max(Location l | - l.hasLocationInfo(filepath, _, _, _, _) and - l.getEndLine() = suppressedLine - | - l.getEndColumn() - ) + endcolumn = getLastColumnNumber(filepath, suppressedLine) ) or this = TMultiLineDeviation(_, _, _, filepath, suppressedLine, endline) and From 5ad61ee4e441007828e966df4c61d3ad658a62e8 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 21 Apr 2025 23:42:01 +0100 Subject: [PATCH 306/370] Deviations: Include the final line in ranges The deviated locations now include the line with the _end marker, for any element before the marker. --- .../deviations/CodeIdentifierDeviation.qll | 38 ++++++++++++------- .../DeviationsSuppression.expected | 4 +- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll index 137a2a72d7..e177b84046 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll @@ -295,11 +295,11 @@ newtype TCodeIndentifierDeviation = } or TMultiLineDeviation( DeviationRecord record, DeviationBegin beginComment, DeviationEnd endComment, string filepath, - int suppressedStartLine, int suppressedEndLine + int suppressedStartLine, int suppressedEndLine, int suppressedEndColumn ) { isDeviationRangePaired(record, beginComment, endComment) and beginComment.getLocation().hasLocationInfo(filepath, suppressedStartLine, _, _, _) and - endComment.getLocation().hasLocationInfo(filepath, suppressedEndLine, _, _, _) + endComment.getLocation().hasLocationInfo(filepath, _, _, suppressedEndLine, suppressedEndColumn) } or TCodeIdentifierDeviation(DeviationRecord record, DeviationAttribute attribute) { attribute.getADeviationRecord() = record @@ -310,7 +310,7 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation { DeviationRecord getADeviationRecord() { this = TSingleLineDeviation(result, _, _, _) or - this = TMultiLineDeviation(result, _, _, _, _, _) + this = TMultiLineDeviation(result, _, _, _, _, _, _) or this = TCodeIdentifierDeviation(result, _) } @@ -321,18 +321,27 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation { bindingset[e] pragma[inline_late] predicate isElementMatching(Element e) { - exists(string filepath, int elementLocationStart | - e.getLocation().hasLocationInfo(filepath, elementLocationStart, _, _, _) + exists(string filepath, int elementLocationStart, int elementLocationColumnStart | + e.getLocation() + .hasLocationInfo(filepath, elementLocationStart, elementLocationColumnStart, _, _) | exists(int suppressedLine | this = TSingleLineDeviation(_, _, filepath, suppressedLine) and suppressedLine = elementLocationStart ) or - exists(int suppressedStartLine, int suppressedEndLine | - this = TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine) and - suppressedStartLine < elementLocationStart and + exists(int suppressedStartLine, int suppressedEndLine, int suppressedEndColumn | + this = + TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine, + suppressedEndColumn) and + suppressedStartLine < elementLocationStart + | + // Element starts before the end line of the suppression suppressedEndLine > elementLocationStart + or + // Element exists on the same line as the suppression, and occurs before it + suppressedEndLine = elementLocationStart and + elementLocationColumnStart < suppressedEndColumn ) ) or @@ -362,9 +371,8 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation { endcolumn = getLastColumnNumber(filepath, suppressedLine) ) or - this = TMultiLineDeviation(_, _, _, filepath, suppressedLine, endline) and - suppressedColumn = 1 and - endcolumn = 1 + this = TMultiLineDeviation(_, _, _, filepath, suppressedLine, endline, endcolumn) and + suppressedColumn = 1 or exists(DeviationAttribute attribute | this = TCodeIdentifierDeviation(_, attribute) and @@ -384,11 +392,13 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation { suppressedLine ) or - exists(int suppressedStartLine, int suppressedEndLine | - this = TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine) and + exists(int suppressedStartLine, int suppressedEndLine, int suppressedEndColumn | + this = + TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine, + suppressedEndColumn) and result = "Deviation of " + getADeviationRecord().getQuery() + " applied to " + filepath + " Line " + - suppressedStartLine + ":" + suppressedEndLine + suppressedStartLine + ":" + suppressedEndLine + " (Column " + suppressedEndColumn + ")" ) ) or diff --git a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected index 73f564c13c..2192b36279 100644 --- a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected +++ b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected @@ -1,8 +1,8 @@ | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:12:1:12:58 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 12 | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:14:1:14:65 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 14 | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:18:1:18:40 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 18 | -| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:21:1:27:1 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 21:27 | -| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:29:1:35:1 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 29:35 | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:21:1:27:53 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 21:27 (Column 53) | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:29:1:35:53 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 29:35 (Column 53) | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/unused-return-value] | lgtm[cpp/autosar/unused-return-value] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/unused-return-value for nested/nested2/test2.h. | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | coding-standards.xml:1:1:17:19 | Deviation of cpp/autosar/useless-assignment for coding-standards.xml. | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | main.cpp:1:1:39:1 | Deviation of cpp/autosar/useless-assignment for main.cpp. | From 6a5f0950ec571b46088b0f96e57fa0dbff346cac Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 21 Apr 2025 23:56:29 +0100 Subject: [PATCH 307/370] Deviations: Store start columns for comment ranges --- .../deviations/CodeIdentifierDeviation.qll | 58 ++++++++++++------- .../DeviationsSuppression.expected | 7 ++- .../deviations_report_deviated/main.cpp | 5 ++ 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll index e177b84046..00e02d5712 100644 --- a/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll +++ b/cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll @@ -295,10 +295,13 @@ newtype TCodeIndentifierDeviation = } or TMultiLineDeviation( DeviationRecord record, DeviationBegin beginComment, DeviationEnd endComment, string filepath, - int suppressedStartLine, int suppressedEndLine, int suppressedEndColumn + int suppressedStartLine, int suppressedStartColumn, int suppressedEndLine, + int suppressedEndColumn ) { isDeviationRangePaired(record, beginComment, endComment) and - beginComment.getLocation().hasLocationInfo(filepath, suppressedStartLine, _, _, _) and + beginComment + .getLocation() + .hasLocationInfo(filepath, suppressedStartLine, suppressedStartColumn, _, _) and endComment.getLocation().hasLocationInfo(filepath, _, _, suppressedEndLine, suppressedEndColumn) } or TCodeIdentifierDeviation(DeviationRecord record, DeviationAttribute attribute) { @@ -310,7 +313,7 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation { DeviationRecord getADeviationRecord() { this = TSingleLineDeviation(result, _, _, _) or - this = TMultiLineDeviation(result, _, _, _, _, _, _) + this = TMultiLineDeviation(result, _, _, _, _, _, _, _) or this = TCodeIdentifierDeviation(result, _) } @@ -330,18 +333,29 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation { suppressedLine = elementLocationStart ) or - exists(int suppressedStartLine, int suppressedEndLine, int suppressedEndColumn | - this = - TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine, - suppressedEndColumn) and - suppressedStartLine < elementLocationStart + exists( + int suppressedStartLine, int suppressedStartColumn, int suppressedEndLine, + int suppressedEndColumn | - // Element starts before the end line of the suppression - suppressedEndLine > elementLocationStart - or - // Element exists on the same line as the suppression, and occurs before it - suppressedEndLine = elementLocationStart and - elementLocationColumnStart < suppressedEndColumn + this = + TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedStartColumn, + suppressedEndLine, suppressedEndColumn) and + ( + // Element starts on a line after the begin marker of the suppression + suppressedStartLine < elementLocationStart + or + // Element exists on the same line as the begin marker, and occurs after it + suppressedStartLine = elementLocationStart and + suppressedStartColumn < elementLocationColumnStart + ) and + ( + // Element starts on a line before the end marker of the suppression + suppressedEndLine > elementLocationStart + or + // Element exists on the same line as the end marker of the suppression, and occurs before it + suppressedEndLine = elementLocationStart and + elementLocationColumnStart < suppressedEndColumn + ) ) ) or @@ -371,8 +385,8 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation { endcolumn = getLastColumnNumber(filepath, suppressedLine) ) or - this = TMultiLineDeviation(_, _, _, filepath, suppressedLine, endline, endcolumn) and - suppressedColumn = 1 + this = + TMultiLineDeviation(_, _, _, filepath, suppressedLine, suppressedColumn, endline, endcolumn) or exists(DeviationAttribute attribute | this = TCodeIdentifierDeviation(_, attribute) and @@ -392,13 +406,17 @@ class CodeIdentifierDeviation extends TCodeIndentifierDeviation { suppressedLine ) or - exists(int suppressedStartLine, int suppressedEndLine, int suppressedEndColumn | + exists( + int suppressedStartLine, int suppressedStartColumn, int suppressedEndLine, + int suppressedEndColumn + | this = - TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedEndLine, - suppressedEndColumn) and + TMultiLineDeviation(_, _, _, filepath, suppressedStartLine, suppressedStartColumn, + suppressedEndLine, suppressedEndColumn) and result = "Deviation of " + getADeviationRecord().getQuery() + " applied to " + filepath + " Line " + - suppressedStartLine + ":" + suppressedEndLine + " (Column " + suppressedEndColumn + ")" + suppressedStartLine + ":" + suppressedStartColumn + ":" + suppressedEndLine + ":" + + suppressedEndColumn ) ) or diff --git a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected index 2192b36279..35fca84928 100644 --- a/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected +++ b/cpp/common/test/deviations/deviations_report_deviated/DeviationsSuppression.expected @@ -1,11 +1,12 @@ | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:12:1:12:58 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 12 | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:14:1:14:65 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 14 | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:18:1:18:40 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 18 | -| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:21:1:27:53 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 21:27 (Column 53) | -| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:29:1:35:53 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 29:35 (Column 53) | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:21:3:27:53 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 21:3:27:53 | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:29:3:35:53 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 29:3:35:53 | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/type-long-double-used] | lgtm[cpp/autosar/type-long-double-used] | main.cpp:40:39:41:99 | Deviation of cpp/autosar/type-long-double-used applied to main.cpp Line 40:39:41:99 | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/unused-return-value] | lgtm[cpp/autosar/unused-return-value] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/unused-return-value for nested/nested2/test2.h. | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | coding-standards.xml:1:1:17:19 | Deviation of cpp/autosar/useless-assignment for coding-standards.xml. | -| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | main.cpp:1:1:39:1 | Deviation of cpp/autosar/useless-assignment for main.cpp. | +| file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | main.cpp:1:1:44:1 | Deviation of cpp/autosar/useless-assignment for main.cpp. | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/coding-standards.xml:1:1:13:19 | Deviation of cpp/autosar/useless-assignment for nested/coding-standards.xml. | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/nested2/test2.h:1:1:6:1 | Deviation of cpp/autosar/useless-assignment for nested/nested2/test2.h. | | file://:0:0:0:0 | (no string representation) | // lgtm[cpp/autosar/useless-assignment] | lgtm[cpp/autosar/useless-assignment] | nested/test.h:1:1:6:1 | Deviation of cpp/autosar/useless-assignment for nested/test.h. | diff --git a/cpp/common/test/deviations/deviations_report_deviated/main.cpp b/cpp/common/test/deviations/deviations_report_deviated/main.cpp index 7891faea18..d2f58d9db1 100644 --- a/cpp/common/test/deviations/deviations_report_deviated/main.cpp +++ b/cpp/common/test/deviations/deviations_report_deviated/main.cpp @@ -35,5 +35,10 @@ int main(int argc, char **argv) { // codeql::autosar_deviation_end(a-0-4-2-deviation) long double d14; // NON_COMPLIANT (A0-4-2) getX(); // NON_COMPLIANT (A0-1-2) + + // clang-format off + long double d15; /* NON_COMPLIANT*/ /* codeql::autosar_deviation_begin(a-0-4-2-deviation) */ long double d16; // COMPLIANT[DEVIATED] + long double d17; /* COMPLIANT[DEVIATED] */ /* codeql::autosar_deviation_end(a-0-4-2-deviation) */ long double d18; // NON_COMPLIANT + // clang-format on return 0; } \ No newline at end of file From 8c2da1cd439f6f5df31f1756842b64832da6feae Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 22 Apr 2025 00:01:48 +0100 Subject: [PATCH 308/370] Deviations: Expand testing for ranges Ensure begin/end column code works as expected --- .../TypeLongDoubleUsed.expected | 2 + .../deviations/deviations_basic_test/main.cpp | 5 +++ .../TypeLongDoubleUsed.expected | 18 +++++++++ .../TypeLongDoubleUsed.ql | 38 +++++++++++++++++++ 4 files changed, 63 insertions(+) create mode 100644 cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.expected create mode 100644 cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.ql diff --git a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected index f2cfd03dc6..afc613642a 100644 --- a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected +++ b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.expected @@ -10,3 +10,5 @@ | main.cpp:21:15:21:16 | d6 | Use of long double type. | | main.cpp:30:15:30:17 | d10 | Use of long double type. | | main.cpp:38:15:38:17 | d14 | Use of long double type. | +| main.cpp:42:15:42:17 | d15 | Use of long double type. | +| main.cpp:43:113:43:115 | d18 | Use of long double type. | diff --git a/cpp/common/test/deviations/deviations_basic_test/main.cpp b/cpp/common/test/deviations/deviations_basic_test/main.cpp index aa389ed0ad..17126364f4 100644 --- a/cpp/common/test/deviations/deviations_basic_test/main.cpp +++ b/cpp/common/test/deviations/deviations_basic_test/main.cpp @@ -37,5 +37,10 @@ int main(int argc, char **argv) { // codeql::autosar_deviation_end(a-0-4-2-deviation) long double d14; // NON_COMPLIANT (A0-4-2) getX(); // NON_COMPLIANT (A0-1-2) + + // clang-format off + long double d15; /* NON_COMPLIANT*/ /* codeql::autosar_deviation_begin(a-0-4-2-deviation) */ long double d16; // COMPLIANT[DEVIATED] + long double d17; /* COMPLIANT[DEVIATED] */ /* codeql::autosar_deviation_end(a-0-4-2-deviation) */ long double d18; // NON_COMPLIANT + // clang-format on return 0; } \ No newline at end of file diff --git a/cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.expected b/cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.expected new file mode 100644 index 0000000000..e9099fa64a --- /dev/null +++ b/cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.expected @@ -0,0 +1,18 @@ +| main.cpp:11:15:11:16 | d1 | Use of long double type. | +| main.cpp:12:15:12:16 | d2 | Use of long double type. | +| main.cpp:14:15:14:16 | d3 | Use of long double type. | +| main.cpp:16:15:16:16 | d4 | Use of long double type. | +| main.cpp:18:15:18:16 | d5 | Use of long double type. | +| main.cpp:19:15:19:16 | d6 | Use of long double type. | +| main.cpp:22:15:22:16 | d7 | Use of long double type. | +| main.cpp:24:15:24:16 | d8 | Use of long double type. | +| main.cpp:26:15:26:16 | d9 | Use of long double type. | +| main.cpp:28:15:28:17 | d10 | Use of long double type. | +| main.cpp:30:15:30:17 | d11 | Use of long double type. | +| main.cpp:32:15:32:17 | d12 | Use of long double type. | +| main.cpp:34:15:34:17 | d13 | Use of long double type. | +| main.cpp:36:15:36:17 | d14 | Use of long double type. | +| main.cpp:40:15:40:17 | d15 | Use of long double type. | +| main.cpp:40:108:40:110 | d16 | Use of long double type. | +| main.cpp:41:15:41:17 | d17 | Use of long double type. | +| main.cpp:41:113:41:115 | d18 | Use of long double type. | diff --git a/cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.ql b/cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.ql new file mode 100644 index 0000000000..0ff7b93251 --- /dev/null +++ b/cpp/common/test/deviations/deviations_report_deviated/TypeLongDoubleUsed.ql @@ -0,0 +1,38 @@ +/** + * @id cpp/autosar/type-long-double-used + * @name A0-4-2: Type long double shall not be used + * @description The type long double has an implementation-defined width and therefore shall not be + * used. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/autosar/id/a0-4-2 + * correctness + * readability + * external/autosar/allocated-target/implementation + * external/autosar/enforcement/automated + * external/autosar/obligation/required + */ + +import cpp +import codingstandards.cpp.CodingStandards +import codingstandards.cpp.exclusions.cpp.RuleMetadata + +predicate isUsingLongDouble(ClassTemplateInstantiation c) { + c.getATemplateArgument() instanceof LongDoubleType or + isUsingLongDouble(c.getATemplateArgument()) +} + +from Variable v +where + not isExcluded(v, BannedTypesPackage::typeLongDoubleUsedQuery()) and + ( + v.getUnderlyingType() instanceof LongDoubleType and + not v.isFromTemplateInstantiation(_) + or + exists(ClassTemplateInstantiation c | + c = v.getType() and + isUsingLongDouble(c) + ) + ) +select v, "Use of long double type." From ed088be3717f0722f83e37f52e68c69300b5e2a9 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 25 Apr 2025 08:12:40 -0700 Subject: [PATCH 309/370] Fix performance regression from Compatible.qll --- cpp/common/src/codingstandards/cpp/types/Compatible.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/common/src/codingstandards/cpp/types/Compatible.qll b/cpp/common/src/codingstandards/cpp/types/Compatible.qll index d6f65126e8..7ea58d766d 100644 --- a/cpp/common/src/codingstandards/cpp/types/Compatible.qll +++ b/cpp/common/src/codingstandards/cpp/types/Compatible.qll @@ -69,6 +69,7 @@ module TypesCompatibleConfig implements TypeEquivalenceSig { /** * Utilize QlBuiltins::InternSets to efficiently compare the sets of specifiers on two types. */ +bindingset[t1, t2] private predicate specifiersMatchExactly(Type t1, Type t2) { t1 = t2 or From 472c93a89b47f0b7c8492c6ea12edd7fe70e616a Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 25 Apr 2025 16:29:32 -0700 Subject: [PATCH 310/370] Add changes to join order and prevent cartesian product through rewrite --- .../codingstandards/cpp/types/Compatible.qll | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/types/Compatible.qll b/cpp/common/src/codingstandards/cpp/types/Compatible.qll index 7ea58d766d..33b2830827 100644 --- a/cpp/common/src/codingstandards/cpp/types/Compatible.qll +++ b/cpp/common/src/codingstandards/cpp/types/Compatible.qll @@ -53,8 +53,11 @@ module TypesCompatibleConfig implements TypeEquivalenceSig { or // Enum types are compatible with one of char, int, or signed int, but the implementation // decides. - [t1, t2] instanceof Enum and - ([t1, t2] instanceof CharType or [t1, t2] instanceof IntType) + t1 instanceof Enum and + (t2 instanceof CharType or t2 instanceof IntType) + or + t2 instanceof Enum and + (t1 instanceof CharType or t1 instanceof IntType) } bindingset[t1, t2] @@ -348,8 +351,15 @@ module FunctionDeclarationTypeEquivalence { predicate equalParameterTypes(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { f1.getDeclaration() = f2.getDeclaration() and forall(int i | exists([f1, f2].getParameterDeclarationEntry(i)) | - TypeEquivalence::equalTypes(f1.getParameterDeclarationEntry(i) - .getType(), f2.getParameterDeclarationEntry(i).getType()) + equalParameterTypesAt(f1, f2, pragma[only_bind_into](i)) + ) + } + + predicate equalParameterTypesAt(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2, int i) { + pragma[only_bind_out](f1.getDeclaration()) = pragma[only_bind_out](f2.getDeclaration()) and + TypeEquivalence::equalTypes( + f1.getParameterDeclarationEntry(i).getType(), + f2.getParameterDeclarationEntry(i).getType() ) } } From 7f6b32d4c14035cc9eaf1bbb18fd12a3ff3c816c Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 27 Apr 2025 00:44:21 -0700 Subject: [PATCH 311/370] Try new approach to reduce search set in type equivalence, some new join orders. More pragmas added to encourage the join ordering pipeline to make function comparisons more efficient. New approach in type equivalence assumes that all types are trivially equivalent to themselves. Therefore, only type comparisons between non-identical types need to be considered as interesting roots. The types that are reachable in the type graph from these roots are the ones considered by the recursive type equivalence predicate. --- ...rousDefaultSelectionForPointerInGeneric.ql | 20 ++- .../DeclarationsOfAFunctionSameNameAndType.ql | 10 +- .../DeclarationsOfAnObjectSameNameAndType.ql | 19 ++- .../CompatibleDeclarationFunctionDefined.ql | 16 ++- .../CompatibleDeclarationObjectDefined.ql | 16 +-- ...-25-improve-type-comparison-performance.md | 6 + .../codingstandards/cpp/types/Compatible.qll | 127 ++++++++++++++---- .../cpp/types/SimpleAssignment.qll | 65 ++++++--- 8 files changed, 199 insertions(+), 80 deletions(-) create mode 100644 change_notes/2025-04-25-improve-type-comparison-performance.md diff --git a/c/misra/src/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.ql b/c/misra/src/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.ql index a009ba1b2a..f2961e2638 100644 --- a/c/misra/src/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.ql +++ b/c/misra/src/rules/RULE-23-5/DangerousDefaultSelectionForPointerInGeneric.ql @@ -20,18 +20,14 @@ import codingstandards.cpp.types.LvalueConversion import codingstandards.cpp.types.SimpleAssignment predicate typesCompatible(Type t1, Type t2) { - TypeEquivalence::equalTypes(t1, t2) + TypeEquivalence::equalTypes(t1, t2) } -class TypeFromGeneric extends Type { - TypeFromGeneric() { - exists(C11GenericExpr g | - ( - this = g.getAssociationType(_) or - this = g.getControllingExpr().getFullyConverted().getType() - ) - ) - } +predicate relevantTypes(Type a, Type b) { + exists(C11GenericExpr g | + a = g.getAnAssociationType() and + b = getLvalueConverted(g.getControllingExpr().getFullyConverted().getType()) + ) } predicate missesOnPointerConversion(Type provided, Type expected) { @@ -40,11 +36,11 @@ predicate missesOnPointerConversion(Type provided, Type expected) { // But 6.5.16.1 simple assignment constraints would have been satisfied: ( // Check as if the controlling expr is assigned to the expected type: - SimpleAssignment::satisfiesSimplePointerAssignment(expected, provided) + SimpleAssignment::satisfiesSimplePointerAssignment(expected, provided) or // Since developers typically rely on the compiler to catch const/non-const assignment // errors, don't assume a const-to-non-const generic selection miss was intentional. - SimpleAssignment::satisfiesSimplePointerAssignment(provided, expected) + SimpleAssignment::satisfiesSimplePointerAssignment(provided, expected) ) } diff --git a/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql index 2de2e4fd0a..0be6347840 100644 --- a/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql +++ b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql @@ -16,6 +16,12 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.types.Compatible +predicate interestedInFunctions(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { + f1.getDeclaration() = f2.getDeclaration() and + not f1 = f2 and + f1.getDeclaration() = f2.getDeclaration() +} + from FunctionDeclarationEntry f1, FunctionDeclarationEntry f2, string case, string pluralDo where not isExcluded(f1, Declarations4Package::declarationsOfAFunctionSameNameAndTypeQuery()) and @@ -24,12 +30,12 @@ where f1.getDeclaration() = f2.getDeclaration() and //return type check ( - not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, f2) and + not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, f2) and case = "return type" and pluralDo = "does" or //parameter type check - not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, f2) and + not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, f2) and case = "parameter types" and pluralDo = "do" or diff --git a/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql b/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql index 12ff583b6b..36a84b3b9c 100644 --- a/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql +++ b/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql @@ -16,15 +16,6 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.types.Compatible -class RelevantType extends Type { - RelevantType() { - exists(VariableDeclarationEntry decl | - (relevantPair(decl, _) or relevantPair(_, decl)) and - decl.getType() = this - ) - } -} - predicate relevantPair(VariableDeclarationEntry decl1, VariableDeclarationEntry decl2) { not decl1 = decl2 and not decl1.getVariable().getDeclaringType().isAnonymous() and @@ -43,12 +34,20 @@ predicate relevantPair(VariableDeclarationEntry decl1, VariableDeclarationEntry ) } +predicate relevantTypes(Type a, Type b) { + exists(VariableDeclarationEntry varA, VariableDeclarationEntry varB | + a = varA.getType() and + b = varB.getType() and + relevantPair(varA, varB) + ) +} + from VariableDeclarationEntry decl1, VariableDeclarationEntry decl2 where not isExcluded(decl1, Declarations4Package::declarationsOfAnObjectSameNameAndTypeQuery()) and not isExcluded(decl2, Declarations4Package::declarationsOfAnObjectSameNameAndTypeQuery()) and relevantPair(decl1, decl2) and - not TypeEquivalence::equalTypes(decl1.getType(), + not TypeEquivalence::equalTypes(decl1.getType(), decl2.getType()) select decl1, "The object $@ of type " + decl1.getType().toString() + diff --git a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql index 98876ad1bd..2f17dd5086 100644 --- a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql +++ b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql @@ -19,6 +19,16 @@ import codingstandards.c.misra import codingstandards.cpp.Identifiers import codingstandards.cpp.types.Compatible +predicate interestedInFunctions(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { + f1.getDeclaration() instanceof ExternalIdentifiers and + f1.isDefinition() and + f1.getName() = f2.getName() and + f1.getDeclaration() = f2.getDeclaration() and + not f2.isDefinition() and + not f1.isFromTemplateInstantiation(_) and + not f2.isFromTemplateInstantiation(_) +} + from FunctionDeclarationEntry f1 where not isExcluded(f1, Declarations4Package::compatibleDeclarationFunctionDefinedQuery()) and @@ -38,10 +48,12 @@ where f2.getDeclaration() = f1.getDeclaration() and ( //return types differ - not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, f2) + not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, + f2) or //parameter types differ - not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, f2) + not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, + f2) or //parameter names differ parameterNamesUnmatched(f1, f2) diff --git a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationObjectDefined.ql b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationObjectDefined.ql index 613ce56806..bed30d673c 100644 --- a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationObjectDefined.ql +++ b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationObjectDefined.ql @@ -19,13 +19,13 @@ import codingstandards.c.misra import codingstandards.cpp.Identifiers import codingstandards.cpp.types.Compatible -class RelevantType extends Type { - RelevantType() { - exists(VariableDeclarationEntry decl | - count(VariableDeclarationEntry others | others.getDeclaration() = decl.getDeclaration()) > 1 and - decl.getType() = this - ) - } +predicate relevantTypes(Type a, Type b) { + exists(VariableDeclarationEntry varA, VariableDeclarationEntry varB | + not varA = varB and + varA.getDeclaration() = varB.getDeclaration() and + a = varA.getType() and + b = varB.getType() + ) } from VariableDeclarationEntry decl1 @@ -37,7 +37,7 @@ where not exists(VariableDeclarationEntry decl2 | not decl2.isDefinition() and decl1.getDeclaration() = decl2.getDeclaration() and - TypeEquivalence::equalTypes(decl1.getType(), + TypeEquivalence::equalTypes(decl1.getType(), decl2.getType()) ) select decl1, "No separate compatible declaration found for this definition." diff --git a/change_notes/2025-04-25-improve-type-comparison-performance.md b/change_notes/2025-04-25-improve-type-comparison-performance.md new file mode 100644 index 0000000000..91a019bdf2 --- /dev/null +++ b/change_notes/2025-04-25-improve-type-comparison-performance.md @@ -0,0 +1,6 @@ + - `RULE-8-3`, `RULE-8-4`, `DCL40-C`, `RULE-23-5`: `DeclarationsOfAFunctionSameNameAndType.ql`, `DeclarationsOfAnObjectSameNameAndType.ql`, `CompatibleDeclarationOfFunctionDefined.ql`, `CompatibleDeclarationObjectDefined.ql`, `IncompatibleFunctionDeclarations.ql`, `DangerousDefaultSelectionForPointerInGeneric.ql`: + - Added pragmas to alter join order on function parameter equivalence (names and types). + - Refactored expression which the optimizer was confused by, and compiled into a cartesian product. + - Altered the module `Compatible.qll` to only perform expensive equality checks on types that are compared to a non identical other type, and those reachable from those types in the type graph. Types that are identical will trivially be considered equivalent. + - `RULE-23-5`: `DangerousDefaultSelectionForPointerInGeneric.ql`: + - Altered the module `SimpleAssignment.qll` in accordance with the changes to `Compatible.qll`. \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/types/Compatible.qll b/cpp/common/src/codingstandards/cpp/types/Compatible.qll index 33b2830827..db77765b5a 100644 --- a/cpp/common/src/codingstandards/cpp/types/Compatible.qll +++ b/cpp/common/src/codingstandards/cpp/types/Compatible.qll @@ -25,7 +25,7 @@ class VariableType extends Type { } predicate parameterNamesUnmatched(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { - f1.getDeclaration() = f2.getDeclaration() and + pragma[only_bind_into](f1).getDeclaration() = pragma[only_bind_into](f2).getDeclaration() and exists(string p1Name, string p2Name, int i | p1Name = f1.getParameterDeclarationEntry(i).getName() and p2Name = f2.getParameterDeclarationEntry(i).getName() @@ -208,34 +208,64 @@ signature module TypeEquivalenceSig { module DefaultEquivalence implements TypeEquivalenceSig { } /** - * A signature class used to restrict the set of types considered by `TypeEquivalence`, for + * A signature predicate used to restrict the set of types considered by `TypeEquivalence`, for * performance reasons. */ -signature class TypeSubset extends Type; +signature predicate interestedInEquality(Type a, Type b); /** * A module to check the equivalence of two types, as defined by the provided `TypeEquivalenceSig`. * - * For performance reasons, this module is designed to be used with a `TypeSubset` that restricts - * the set of considered types. All types reachable (in the type graph) from a type in the subset - * will be considered. (See `RelevantType`.) + * For performance reasons, this module is designed to be used with a predicate + * `interestedInEquality` that restricts the set of considered types. * * To use this module, define a `TypeEquivalenceSig` module and implement a subset of `Type` that * selects the relevant root types to be considered. Then use the predicate `equalTypes(a, b)`. + * Note that `equalTypes(a, b)` only holds if `interestedIn(a, b)` holds. A type is always + * considered to be equal to itself, and this module does not support configurations that declare + * otherwise. + * + * Further, `interestedInEquality(a, a)` is treated differently from `interestedInEquality(a, b)`, + * assuming that `a` and `b` are not identical. This is so that we can construct a set of types + * that are not identical, but still may be equivalent by the specified configuration. We also must + * consider all types that are reachable from these types, as the equivalence relation is + * recursive. Therefore, this module is more performant when most comparisons are identical, and + * only a few are not. */ -module TypeEquivalence { +module TypeEquivalence { /** * Check whether two types are equivalent, as defined by the `TypeEquivalenceSig` module. + * + * This only holds if the specified predicate `interestedIn` holds for the types, and always + * holds if `t1` and `t2` are identical. */ - predicate equalTypes(RelevantType t1, RelevantType t2) { + predicate equalTypes(Type t1, Type t2) { + interestedInUnordered(t1, t2) and + ( + // If the types are identical, they are trivially equal. + t1 = t2 + or + not t1 = t2 and + equalTypesImpl(t1, t2) + ) + } + + /** + * This implementation handles only the slow and complex cases of type equivalence, where the + * types are not identical. + * + * Assuming that types a, b must be compared where `a` and `b` are not identical, we wish to + * search only the smallest set of possible relevant types. See `RelevantType` for more. + */ + private predicate equalTypesImpl(RelevantType t1, RelevantType t2) { if Config::overrideTypeComparison(t1, t2, _) then Config::overrideTypeComparison(t1, t2, true) else if t1 instanceof TypedefType and Config::resolveTypedefs() - then equalTypes(t1.(TypedefType).getBaseType(), t2) + then equalTypesImpl(t1.(TypedefType).getBaseType(), t2) else if t2 instanceof TypedefType and Config::resolveTypedefs() - then equalTypes(t1, t2.(TypedefType).getBaseType()) + then equalTypesImpl(t1, t2.(TypedefType).getBaseType()) else ( not t1 instanceof DerivedType and not t2 instanceof DerivedType and @@ -251,13 +281,36 @@ module TypeEquivalence { ) } + /** Whether two types will be compared, regardless of order (a, b) or (b, a). */ + private predicate interestedInUnordered(Type t1, Type t2) { + interestedIn(t1, t2) or + interestedIn(t2, t1) } + + final private class FinalType = Type; + /** - * A type that is either part of the type subset, or that is reachable from a type in the subset. + * A type that is compared to another type that is not identical. This is the set of types that + * form the roots of our more expensive type equivalence analysis. */ - private class RelevantType instanceof Type { - RelevantType() { exists(T t | typeGraph*(t, this)) } + private class InterestingType extends FinalType { + InterestingType() { + exists(Type inexactCompare | + interestedInUnordered(this, _) and + not inexactCompare = this + ) + } + } - string toString() { result = this.(Type).toString() } + /** + * A type that is reachable from an `InterestingType` (a type that is compared to a non-identical + * type). + * + * Since type equivalence is recursive, CodeQL will consider the equality of these types in a + * bottom-up evaluation, with leaf nodes first. Therefore, this set must be as small as possible + * in order to be efficient. + */ + private class RelevantType extends FinalType { + RelevantType() { exists(InterestingType t | typeGraph*(t, this)) } } private class RelevantDerivedType extends RelevantType instanceof DerivedType { @@ -296,7 +349,7 @@ module TypeEquivalence { bindingset[t1, t2] private predicate equalDerivedTypes(RelevantDerivedType t1, RelevantDerivedType t2) { exists(Boolean baseTypesEqual | - (baseTypesEqual = true implies equalTypes(t1.getBaseType(), t2.getBaseType())) and + (baseTypesEqual = true implies equalTypesImpl(t1.getBaseType(), t2.getBaseType())) and ( Config::equalPointerTypes(t1, t2, baseTypesEqual) or @@ -310,7 +363,7 @@ module TypeEquivalence { // Note that this case is different from the above, in that we don't merely get the base // type (as that could be a TypedefType that points to another SpecifiedType). We need to // unspecify the type to see if the base types are equal. - (unspecifiedTypesEqual = true implies equalTypes(unspecify(t1), unspecify(t2))) and + (unspecifiedTypesEqual = true implies equalTypesImpl(unspecify(t1), unspecify(t2))) and Config::equalSpecifiedTypes(t1, t2, unspecifiedTypesEqual) ) } @@ -318,12 +371,12 @@ module TypeEquivalence { bindingset[t1, t2] private predicate equalFunctionTypes(RelevantFunctionType t1, RelevantFunctionType t2) { exists(Boolean returnTypeEqual, Boolean parameterTypesEqual | - (returnTypeEqual = true implies equalTypes(t1.getReturnType(), t2.getReturnType())) and + (returnTypeEqual = true implies equalTypesImpl(t1.getReturnType(), t2.getReturnType())) and ( parameterTypesEqual = true implies forall(int i | exists([t1, t2].getParameterType(i)) | - equalTypes(t1.getParameterType(i), t2.getParameterType(i)) + equalTypesImpl(t1.getParameterType(i), t2.getParameterType(i)) ) ) and ( @@ -337,18 +390,41 @@ module TypeEquivalence { bindingset[t1, t2] private predicate equalTypedefTypes(RelevantTypedefType t1, RelevantTypedefType t2) { exists(Boolean baseTypesEqual | - (baseTypesEqual = true implies equalTypes(t1.getBaseType(), t2.getBaseType())) and + (baseTypesEqual = true implies equalTypesImpl(t1.getBaseType(), t2.getBaseType())) and Config::equalTypedefTypes(t1, t2, baseTypesEqual) ) } } -module FunctionDeclarationTypeEquivalence { +signature predicate interestedInFunctionDeclarations( + FunctionDeclarationEntry f1, FunctionDeclarationEntry f2 +); + +module FunctionDeclarationTypeEquivalence< + TypeEquivalenceSig Config, interestedInFunctionDeclarations/2 interestedInFunctions> +{ + private predicate interestedInReturnTypes(Type a, Type b) { + exists(FunctionDeclarationEntry aFun, FunctionDeclarationEntry bFun | + interestedInFunctions(aFun, bFun) and + a = aFun.getType() and + b = bFun.getType() + ) + } + + private predicate interestedInParameterTypes(Type a, Type b) { + exists(FunctionDeclarationEntry aFun, FunctionDeclarationEntry bFun, int i | + interestedInFunctions(pragma[only_bind_into](aFun), pragma[only_bind_into](bFun)) and + a = aFun.getParameterDeclarationEntry(i).getType() and + b = bFun.getParameterDeclarationEntry(i).getType() + ) + } + predicate equalReturnTypes(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { - TypeEquivalence::equalTypes(f1.getType(), f2.getType()) + TypeEquivalence::equalTypes(f1.getType(), f2.getType()) } predicate equalParameterTypes(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { + interestedInFunctions(f1, f2) and f1.getDeclaration() = f2.getDeclaration() and forall(int i | exists([f1, f2].getParameterDeclarationEntry(i)) | equalParameterTypesAt(f1, f2, pragma[only_bind_into](i)) @@ -356,11 +432,10 @@ module FunctionDeclarationTypeEquivalence { } predicate equalParameterTypesAt(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2, int i) { - pragma[only_bind_out](f1.getDeclaration()) = pragma[only_bind_out](f2.getDeclaration()) and - TypeEquivalence::equalTypes( - f1.getParameterDeclarationEntry(i).getType(), - f2.getParameterDeclarationEntry(i).getType() - ) + interestedInFunctions(f1, f2) and + f1.getDeclaration() = f2.getDeclaration() and + TypeEquivalence::equalTypes(f1.getParameterDeclarationEntry(pragma[only_bind_into](i)) + .getType(), f2.getParameterDeclarationEntry(pragma[only_bind_into](i)).getType()) } } diff --git a/cpp/common/src/codingstandards/cpp/types/SimpleAssignment.qll b/cpp/common/src/codingstandards/cpp/types/SimpleAssignment.qll index 4f7a85c80a..a31400a340 100644 --- a/cpp/common/src/codingstandards/cpp/types/SimpleAssignment.qll +++ b/cpp/common/src/codingstandards/cpp/types/SimpleAssignment.qll @@ -8,42 +8,67 @@ import codingstandards.cpp.types.LvalueConversion import codingstandards.cpp.types.Compatible -module SimpleAssignment { - final private class FinalType = Type; - - private class RelevantType extends FinalType { - RelevantType() { exists(T t | typeGraph*(t, this) or typeGraph(getLvalueConverted(t), this)) } - - string toString() { result = "relevant type" } - } - +module SimpleAssignment { /** * Whether a pair of qualified or unqualified pointer types satisfy the simple assignment * constraints from 6.5.16.1. * * There are additional constraints not implemented here involving one or more arithmetic types. */ - predicate satisfiesSimplePointerAssignment(RelevantType left, RelevantType right) { + predicate satisfiesSimplePointerAssignment(Type left, Type right) { + checksAssignment(left, right) and simplePointerAssignmentImpl(getLvalueConverted(left), right) } + private predicate satisfiedWhenTypesCompatible(Type left, Type right, Type checkA, Type checkB) { + interestedInTypes(left, right) and + exists(Type leftBase, Type rightBase | + // The left operand has atomic, qualified, or unqualified pointer type: + leftBase = left.stripTopLevelSpecifiers().(PointerType).getBaseType() and + rightBase = right.stripTopLevelSpecifiers().(PointerType).getBaseType() and + ( + // and both operands are pointers to qualified or unqualified versions of compatible types: + checkA = leftBase.stripTopLevelSpecifiers() and + checkB = rightBase.stripTopLevelSpecifiers() + ) and + // and the type pointed to by the left has all the qualifiers of the type pointed to by the + // right: + forall(Specifier s | s = rightBase.getASpecifier() | s = leftBase.getASpecifier()) + ) + } + + predicate interestedInTypes(Type left, Type right) { + exists(Type unconverted | + left = getLvalueConverted(unconverted) and + checksAssignment(unconverted, right) + ) + } + + predicate checksCompatibility(Type left, Type right) { + // Check if the types are compatible + exists(Type assignA, Type assignB | + checksAssignment(assignA, assignB) and + satisfiedWhenTypesCompatible(assignA, assignB, left, right) + ) + } + /** * Implementation of 6.5.16.1 for a pair of pointer types, that assumes lvalue conversion has been * performed on the left operand. */ - private predicate simplePointerAssignmentImpl(RelevantType left, RelevantType right) { - exists(RelevantType leftBase, RelevantType rightBase | + bindingset[left, right] + private predicate simplePointerAssignmentImpl(Type left, Type right) { + exists(Type checkA, Type checkB | + satisfiedWhenTypesCompatible(left, right, checkA, checkB) and + TypeEquivalence::equalTypes(checkA, checkB) + ) + or + exists(Type leftBase, Type rightBase | // The left operand has atomic, qualified, or unqualified pointer type: leftBase = left.stripTopLevelSpecifiers().(PointerType).getBaseType() and rightBase = right.stripTopLevelSpecifiers().(PointerType).getBaseType() and - ( - // and both operands are pointers to qualified or unqualified versions of compatible types: - TypeEquivalence::equalTypes(leftBase - .stripTopLevelSpecifiers(), rightBase.stripTopLevelSpecifiers()) - or - // or one operand is a pointer to a qualified or unqualified version of void - [leftBase, rightBase].stripTopLevelSpecifiers() instanceof VoidType - ) and + // or one operand is a pointer to a qualified or unqualified version of void + [leftBase, rightBase].stripTopLevelSpecifiers() instanceof VoidType and // and the type pointed to by the left has all the qualifiers of the type pointed to by the // right: forall(Specifier s | s = rightBase.getASpecifier() | s = leftBase.getASpecifier()) From 48257745c8e553c125aa876e9755f959888bfc4a Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 27 Apr 2025 01:49:42 -0700 Subject: [PATCH 312/370] Add missing file changed --- .../DCL40-C/IncompatibleFunctionDeclarations.ql | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql b/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql index 95ef0fd682..8cab442e54 100644 --- a/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql +++ b/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql @@ -19,6 +19,12 @@ import codingstandards.c.cert import codingstandards.cpp.types.Compatible import ExternalIdentifiers +predicate interestedInFunctions(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { + not f1 = f2 and + f1.getDeclaration() = f2.getDeclaration() and + f1.getName() = f2.getName() +} + from ExternalIdentifiers d, FunctionDeclarationEntry f1, FunctionDeclarationEntry f2 where not isExcluded(f1, Declarations2Package::incompatibleFunctionDeclarationsQuery()) and @@ -29,10 +35,12 @@ where f1.getName() = f2.getName() and ( //return type check - not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, f2) + not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, + f2) or //parameter type check - not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, f2) + not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, + f2) ) and // Apply ordering on start line, trying to avoid the optimiser applying this join too early // in the pipeline From 06351f52f176b55a5e3396dd8f5aa3a445d70a01 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 27 Apr 2025 01:48:55 -0700 Subject: [PATCH 313/370] Try forcing top-down pairwise comparison --- .../codingstandards/cpp/types/Compatible.qll | 138 ++++++++---------- 1 file changed, 63 insertions(+), 75 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/types/Compatible.qll b/cpp/common/src/codingstandards/cpp/types/Compatible.qll index db77765b5a..53b0076c7c 100644 --- a/cpp/common/src/codingstandards/cpp/types/Compatible.qll +++ b/cpp/common/src/codingstandards/cpp/types/Compatible.qll @@ -224,7 +224,7 @@ signature predicate interestedInEquality(Type a, Type b); * Note that `equalTypes(a, b)` only holds if `interestedIn(a, b)` holds. A type is always * considered to be equal to itself, and this module does not support configurations that declare * otherwise. - * + * * Further, `interestedInEquality(a, a)` is treated differently from `interestedInEquality(a, b)`, * assuming that `a` and `b` are not identical. This is so that we can construct a set of types * that are not identical, but still may be equivalent by the specified configuration. We also must @@ -233,45 +233,75 @@ signature predicate interestedInEquality(Type a, Type b); * only a few are not. */ module TypeEquivalence { + /** - * Check whether two types are equivalent, as defined by the `TypeEquivalenceSig` module. - * - * This only holds if the specified predicate `interestedIn` holds for the types, and always - * holds if `t1` and `t2` are identical. + * Performance related predicate to force top down rather than bottom up evaluation of type + * equivalence. */ - predicate equalTypes(Type t1, Type t2) { - interestedInUnordered(t1, t2) and - ( - // If the types are identical, they are trivially equal. - t1 = t2 + predicate compares(Type t1, Type t2) { + interestedIn(t1, t2) + or + exists(DerivedType t1Derived, DerivedType t2Derived | + not t1Derived instanceof SpecifiedType and + not t2Derived instanceof SpecifiedType and + compares(pragma[only_bind_into](t1Derived), pragma[only_bind_into](t2Derived)) and + t1 = t1Derived.getBaseType() and + t2 = t2Derived.getBaseType() + ) + or + exists(SpecifiedType t1Spec, SpecifiedType t2Spec | + compares(pragma[only_bind_into](t1Spec), pragma[only_bind_into](t2Spec)) and + ( + t1 = unspecify(t1Spec) and + t2 = unspecify(t2Spec) + ) + ) + or + exists(FunctionType t1Func, FunctionType t2Func | + compares(pragma[only_bind_into](t1Func), pragma[only_bind_into](t2Func)) and + ( + t1 = t1Func.getReturnType() and + t2 = t2Func.getReturnType() + or + exists(int i | + t1 = t1Func.getParameterType(pragma[only_bind_out](i)) and + t2 = t2Func.getParameterType(i) + ) + ) + ) + or + Config::resolveTypedefs() and + exists(TypedefType tdtype | + tdtype.getBaseType() = t1 and + compares(pragma[only_bind_into](tdtype), t2) or - not t1 = t2 and - equalTypesImpl(t1, t2) + tdtype.getBaseType() = t2 and + compares(t1, pragma[only_bind_into](tdtype)) ) } /** - * This implementation handles only the slow and complex cases of type equivalence, where the - * types are not identical. + * Check whether two types are equivalent, as defined by the `TypeEquivalenceSig` module. * - * Assuming that types a, b must be compared where `a` and `b` are not identical, we wish to - * search only the smallest set of possible relevant types. See `RelevantType` for more. + * This only holds if the specified predicate `interestedIn` holds for the types, and always + * holds if `t1` and `t2` are identical. */ - private predicate equalTypesImpl(RelevantType t1, RelevantType t2) { + private predicate equalTypes(Type t1, Type t2) { + compares(pragma[only_bind_into](t1), pragma[only_bind_into](t2)) and if Config::overrideTypeComparison(t1, t2, _) then Config::overrideTypeComparison(t1, t2, true) else if t1 instanceof TypedefType and Config::resolveTypedefs() - then equalTypesImpl(t1.(TypedefType).getBaseType(), t2) + then equalTypes(t1.(TypedefType).getBaseType(), t2) else if t2 instanceof TypedefType and Config::resolveTypedefs() - then equalTypesImpl(t1, t2.(TypedefType).getBaseType()) + then equalTypes(t1, t2.(TypedefType).getBaseType()) else ( not t1 instanceof DerivedType and not t2 instanceof DerivedType and not t1 instanceof TypedefType and not t2 instanceof TypedefType and - LeafEquiv::getEquivalenceClass(t1) = LeafEquiv::getEquivalenceClass(t2) + equalLeafRelation(t1, t2) or equalDerivedTypes(t1, t2) or @@ -284,56 +314,14 @@ module TypeEquivalence; - - private predicate equalLeafRelation(RelevantType t1, RelevantType t2) { - Config::equalLeafTypes(t1, t2) - } + bindingset[t1, t2] + private predicate equalLeafRelation(Type t1, Type t2) { Config::equalLeafTypes(t1, t2) } - private RelevantType unspecify(SpecifiedType t) { + bindingset[t] + private Type unspecify(SpecifiedType t) { // This subtly and importantly handles the complicated cases of typedefs. Under most scenarios, // if we see a typedef in `equalTypes()` we can simply get the base type and continue. However, // there is an exception if we have a specified type that points to a typedef that points to @@ -347,9 +335,9 @@ module TypeEquivalence Date: Sun, 27 Apr 2025 12:22:21 -0700 Subject: [PATCH 314/370] Fix private predicate --- cpp/common/src/codingstandards/cpp/types/Compatible.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/types/Compatible.qll b/cpp/common/src/codingstandards/cpp/types/Compatible.qll index 53b0076c7c..da2b175a0d 100644 --- a/cpp/common/src/codingstandards/cpp/types/Compatible.qll +++ b/cpp/common/src/codingstandards/cpp/types/Compatible.qll @@ -286,7 +286,7 @@ module TypeEquivalence Date: Mon, 28 Apr 2025 10:51:11 -0700 Subject: [PATCH 315/370] Address feedback, separate `compares` from `recurses`, format. --- .../DeclarationsOfAFunctionSameNameAndType.ql | 6 +- ...-25-improve-type-comparison-performance.md | 2 +- .../codingstandards/cpp/types/Compatible.qll | 155 ++++++++++++++---- 3 files changed, 125 insertions(+), 38 deletions(-) diff --git a/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql index 0be6347840..9ae62a7be0 100644 --- a/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql +++ b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql @@ -30,12 +30,14 @@ where f1.getDeclaration() = f2.getDeclaration() and //return type check ( - not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, f2) and + not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, + f2) and case = "return type" and pluralDo = "does" or //parameter type check - not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, f2) and + not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, + f2) and case = "parameter types" and pluralDo = "do" or diff --git a/change_notes/2025-04-25-improve-type-comparison-performance.md b/change_notes/2025-04-25-improve-type-comparison-performance.md index 91a019bdf2..39c462fbf2 100644 --- a/change_notes/2025-04-25-improve-type-comparison-performance.md +++ b/change_notes/2025-04-25-improve-type-comparison-performance.md @@ -1,6 +1,6 @@ - `RULE-8-3`, `RULE-8-4`, `DCL40-C`, `RULE-23-5`: `DeclarationsOfAFunctionSameNameAndType.ql`, `DeclarationsOfAnObjectSameNameAndType.ql`, `CompatibleDeclarationOfFunctionDefined.ql`, `CompatibleDeclarationObjectDefined.ql`, `IncompatibleFunctionDeclarations.ql`, `DangerousDefaultSelectionForPointerInGeneric.ql`: - Added pragmas to alter join order on function parameter equivalence (names and types). - Refactored expression which the optimizer was confused by, and compiled into a cartesian product. - - Altered the module `Compatible.qll` to only perform expensive equality checks on types that are compared to a non identical other type, and those reachable from those types in the type graph. Types that are identical will trivially be considered equivalent. + - Altered the module `Compatible.qll` to compute equality in two stages. Firstly, all pairs of possible type comparisons (including recursive comparisons) are found, then those pairwise comparisons are evaluated in a second stage. This greatly reduces the number of comparisons and greatly improves performance. - `RULE-23-5`: `DangerousDefaultSelectionForPointerInGeneric.ql`: - Altered the module `SimpleAssignment.qll` in accordance with the changes to `Compatible.qll`. \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/types/Compatible.qll b/cpp/common/src/codingstandards/cpp/types/Compatible.qll index da2b175a0d..c222cd77ba 100644 --- a/cpp/common/src/codingstandards/cpp/types/Compatible.qll +++ b/cpp/common/src/codingstandards/cpp/types/Compatible.qll @@ -217,48 +217,61 @@ signature predicate interestedInEquality(Type a, Type b); * A module to check the equivalence of two types, as defined by the provided `TypeEquivalenceSig`. * * For performance reasons, this module is designed to be used with a predicate - * `interestedInEquality` that restricts the set of considered types. + * `interestedInEquality` that restricts the set of considered pairwise comparisons. * * To use this module, define a `TypeEquivalenceSig` module and implement a subset of `Type` that * selects the relevant root types to be considered. Then use the predicate `equalTypes(a, b)`. * Note that `equalTypes(a, b)` only holds if `interestedIn(a, b)` holds. A type is always * considered to be equal to itself, and this module does not support configurations that declare - * otherwise. + * otherwise. Additionally, `interestedIn(a, b)` implies `interestedIn(b, a)`. * - * Further, `interestedInEquality(a, a)` is treated differently from `interestedInEquality(a, b)`, - * assuming that `a` and `b` are not identical. This is so that we can construct a set of types - * that are not identical, but still may be equivalent by the specified configuration. We also must - * consider all types that are reachable from these types, as the equivalence relation is - * recursive. Therefore, this module is more performant when most comparisons are identical, and - * only a few are not. + * This module will recursively select pairs of types to be compared. For instance, if + * `interestedInEquality(a, b)` holds, then types `a` and `b` will be compared. If + * `Config::equalPointerTypes(a, b, true)` holds, then the pointed-to types of `a` and `b` will be + * compared. However, if `Config::equalPointerTypes(a, b, false)` holds, then `a` and `b` will be + * compared, but their pointed-to types will not. Similarly, inner types will not be compared if + * `Config::overrideTypeComparison(a, b, _)` holds. For detail, see the module predicates + * `recurses` and `compares`. */ module TypeEquivalence { - /** * Performance related predicate to force top down rather than bottom up evaluation of type * equivalence. + * + * This interoperates with the predicate `recurses` to find types that will be compared, along + * with the inner types of those types that will be compared. See `recurses` for cases where this + * algorithm will or will not recurse. We still need to know which types are compared, even if + * we do not recurse on them, in order to properly constrain `equalTypes(x, y)` to hold for types + * such as leaf types, where we do not recurse during comparison. + * + * At each stage of recursion, we specify `pragma[only_bind_into]` to ensure that the + * prior `recurses` results are considered first in the pipeline. */ predicate compares(Type t1, Type t2) { - interestedIn(t1, t2) + // Base case: config specifies that these root types will be compared. + interestedInUnordered(t1, t2) or + // If derived types are compared, their base types must be compared. exists(DerivedType t1Derived, DerivedType t2Derived | not t1Derived instanceof SpecifiedType and not t2Derived instanceof SpecifiedType and - compares(pragma[only_bind_into](t1Derived), pragma[only_bind_into](t2Derived)) and + recurses(pragma[only_bind_into](t1Derived), pragma[only_bind_into](t2Derived)) and t1 = t1Derived.getBaseType() and t2 = t2Derived.getBaseType() ) or + // If specified types are compared, their unspecified types must be compared. exists(SpecifiedType t1Spec, SpecifiedType t2Spec | - compares(pragma[only_bind_into](t1Spec), pragma[only_bind_into](t2Spec)) and + recurses(pragma[only_bind_into](t1Spec), pragma[only_bind_into](t2Spec)) and ( t1 = unspecify(t1Spec) and t2 = unspecify(t2Spec) ) ) or + // If function types are compared, their return types and parameter types must be compared. exists(FunctionType t1Func, FunctionType t2Func | - compares(pragma[only_bind_into](t1Func), pragma[only_bind_into](t2Func)) and + recurses(pragma[only_bind_into](t1Func), pragma[only_bind_into](t2Func)) and ( t1 = t1Func.getReturnType() and t2 = t2Func.getReturnType() @@ -270,13 +283,79 @@ module TypeEquivalence::equalTypes(f1.getType(), f2.getType()) } From 6c14eebefbe9c9b3a23f6d234417c82adbe7a7e5 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 28 Apr 2025 10:53:10 -0700 Subject: [PATCH 316/370] Remove redundant condition --- .../src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql | 1 - 1 file changed, 1 deletion(-) diff --git a/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql index 9ae62a7be0..fe0ae81ab1 100644 --- a/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql +++ b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql @@ -17,7 +17,6 @@ import codingstandards.c.misra import codingstandards.cpp.types.Compatible predicate interestedInFunctions(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { - f1.getDeclaration() = f2.getDeclaration() and not f1 = f2 and f1.getDeclaration() = f2.getDeclaration() } From 4b8cdd339caa9329eac90143f8534406f1935a20 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 28 Apr 2025 18:47:07 -0700 Subject: [PATCH 317/370] Address next round of feedback --- .../CompatibleDeclarationFunctionDefined.ql | 5 +- .../codingstandards/cpp/types/Compatible.qll | 109 ++++++++++-------- 2 files changed, 67 insertions(+), 47 deletions(-) diff --git a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql index 2f17dd5086..9631b02839 100644 --- a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql +++ b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql @@ -22,8 +22,9 @@ import codingstandards.cpp.types.Compatible predicate interestedInFunctions(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { f1.getDeclaration() instanceof ExternalIdentifiers and f1.isDefinition() and - f1.getName() = f2.getName() and f1.getDeclaration() = f2.getDeclaration() and + // This condition should always hold, but removing it affects join order performance. + f1.getName() = f2.getName() and not f2.isDefinition() and not f1.isFromTemplateInstantiation(_) and not f2.isFromTemplateInstantiation(_) @@ -51,10 +52,12 @@ where not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, f2) or + //not compatibleReturns(f1, f2) //parameter types differ not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, f2) or + //not compatibleParams(f1, f2) //parameter names differ parameterNamesUnmatched(f1, f2) ) diff --git a/cpp/common/src/codingstandards/cpp/types/Compatible.qll b/cpp/common/src/codingstandards/cpp/types/Compatible.qll index c222cd77ba..ded3794658 100644 --- a/cpp/common/src/codingstandards/cpp/types/Compatible.qll +++ b/cpp/common/src/codingstandards/cpp/types/Compatible.qll @@ -231,23 +231,31 @@ signature predicate interestedInEquality(Type a, Type b); * compared. However, if `Config::equalPointerTypes(a, b, false)` holds, then `a` and `b` will be * compared, but their pointed-to types will not. Similarly, inner types will not be compared if * `Config::overrideTypeComparison(a, b, _)` holds. For detail, see the module predicates - * `recurses` and `compares`. + * `shouldRecurseOn` and `interestedInNestedTypes`. */ module TypeEquivalence { /** - * Performance related predicate to force top down rather than bottom up evaluation of type - * equivalence. + * Performance-related predicate that holds for a pair of types `(a, b)` such that + * `interestedIn(a, b)` holds, or there exists a pair of types `(c, d)` such that + * `interestedIn(c, d)` holds, and computing `equalTypes(a, b)` requires computing + * `equalTypes(c, d)`. + * + * The goal of this predicate is to force top down rather than bottom up evaluation of type + * equivalence. That is to say, if we compare array types `int[]` and `int[]`, we to compare that + * both types are arrays first, and then compare that their base types are equal. Naively, CodeQL + * is liable to compute this kind of recursive equality in a bottom up fashion, where the cross + * product of all types is considered in computing `equalTypes(a, b)`. * - * This interoperates with the predicate `recurses` to find types that will be compared, along - * with the inner types of those types that will be compared. See `recurses` for cases where this - * algorithm will or will not recurse. We still need to know which types are compared, even if - * we do not recurse on them, in order to properly constrain `equalTypes(x, y)` to hold for types - * such as leaf types, where we do not recurse during comparison. + * This interoperates with the predicate `shouldRecurseOn` to find types that will be compared, + * along with the inner types of those types that will be compared. See `shouldRecurseOn` for + * cases where this algorithm will or will not recurse. We still need to know which types are + * compared, even if we do not recurse on them, in order to properly constrain `equalTypes(x, y)` + * to hold for types such as leaf types, where we do not recurse during comparison. * * At each stage of recursion, we specify `pragma[only_bind_into]` to ensure that the - * prior `recurses` results are considered first in the pipeline. + * prior `shouldRecurseOn` results are considered first in the pipeline. */ - predicate compares(Type t1, Type t2) { + private predicate interestedInNestedTypes(Type t1, Type t2) { // Base case: config specifies that these root types will be compared. interestedInUnordered(t1, t2) or @@ -255,14 +263,14 @@ module TypeEquivalence Date: Tue, 29 Apr 2025 09:09:58 -0700 Subject: [PATCH 318/370] Ensure Config::resolvesTypedefs() enforced, remove comments --- .../rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql | 2 -- cpp/common/src/codingstandards/cpp/types/Compatible.qll | 5 +++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql index 9631b02839..73abc1e048 100644 --- a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql +++ b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql @@ -52,12 +52,10 @@ where not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, f2) or - //not compatibleReturns(f1, f2) //parameter types differ not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, f2) or - //not compatibleParams(f1, f2) //parameter names differ parameterNamesUnmatched(f1, f2) ) diff --git a/cpp/common/src/codingstandards/cpp/types/Compatible.qll b/cpp/common/src/codingstandards/cpp/types/Compatible.qll index ded3794658..c4ee9a22e3 100644 --- a/cpp/common/src/codingstandards/cpp/types/Compatible.qll +++ b/cpp/common/src/codingstandards/cpp/types/Compatible.qll @@ -390,8 +390,6 @@ module TypeEquivalence Date: Wed, 30 Apr 2025 15:05:55 +0000 Subject: [PATCH 319/370] Bump version to 2.45.0-dev --- c/cert/src/qlpack.yml | 2 +- c/cert/test/qlpack.yml | 2 +- c/common/src/qlpack.yml | 2 +- c/common/test/qlpack.yml | 2 +- c/misra/src/qlpack.yml | 2 +- c/misra/test/qlpack.yml | 2 +- cpp/autosar/src/qlpack.yml | 2 +- cpp/autosar/test/qlpack.yml | 2 +- cpp/cert/src/qlpack.yml | 2 +- cpp/cert/test/qlpack.yml | 2 +- cpp/common/src/qlpack.yml | 2 +- cpp/common/test/qlpack.yml | 2 +- cpp/misra/src/qlpack.yml | 2 +- cpp/misra/test/qlpack.yml | 2 +- cpp/report/src/qlpack.yml | 2 +- docs/user_manual.md | 12 ++++++------ 16 files changed, 21 insertions(+), 21 deletions(-) diff --git a/c/cert/src/qlpack.yml b/c/cert/src/qlpack.yml index 631639301e..b79fbf3cbb 100644 --- a/c/cert/src/qlpack.yml +++ b/c/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards -version: 2.44.0-dev +version: 2.45.0-dev description: CERT C 2016 suites: codeql-suites license: MIT diff --git a/c/cert/test/qlpack.yml b/c/cert/test/qlpack.yml index 6eaaba1e91..f7fe527dab 100644 --- a/c/cert/test/qlpack.yml +++ b/c/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards-tests -version: 2.44.0-dev +version: 2.45.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/common/src/qlpack.yml b/c/common/src/qlpack.yml index 4c21dc9b18..ad3f825a4b 100644 --- a/c/common/src/qlpack.yml +++ b/c/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards -version: 2.44.0-dev +version: 2.45.0-dev license: MIT dependencies: codeql/common-cpp-coding-standards: '*' diff --git a/c/common/test/qlpack.yml b/c/common/test/qlpack.yml index 1dbb59b4fd..cbadd7f238 100644 --- a/c/common/test/qlpack.yml +++ b/c/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards-tests -version: 2.44.0-dev +version: 2.45.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/misra/src/qlpack.yml b/c/misra/src/qlpack.yml index 54cda2c1cc..b5d16e9974 100644 --- a/c/misra/src/qlpack.yml +++ b/c/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards -version: 2.44.0-dev +version: 2.45.0-dev description: MISRA C 2012 suites: codeql-suites license: MIT diff --git a/c/misra/test/qlpack.yml b/c/misra/test/qlpack.yml index 9148e26b59..e6932cc894 100644 --- a/c/misra/test/qlpack.yml +++ b/c/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards-tests -version: 2.44.0-dev +version: 2.45.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/autosar/src/qlpack.yml b/cpp/autosar/src/qlpack.yml index 6d31398b2c..b9cd9b72a8 100644 --- a/cpp/autosar/src/qlpack.yml +++ b/cpp/autosar/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards -version: 2.44.0-dev +version: 2.45.0-dev description: AUTOSAR C++14 Guidelines R22-11, R21-11, R20-11, R19-11 and R19-03 suites: codeql-suites license: MIT diff --git a/cpp/autosar/test/qlpack.yml b/cpp/autosar/test/qlpack.yml index ff7621c9d1..0b92541fdf 100644 --- a/cpp/autosar/test/qlpack.yml +++ b/cpp/autosar/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards-tests -version: 2.44.0-dev +version: 2.45.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/cert/src/qlpack.yml b/cpp/cert/src/qlpack.yml index f44646cdbe..a3b60a7e07 100644 --- a/cpp/cert/src/qlpack.yml +++ b/cpp/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards -version: 2.44.0-dev +version: 2.45.0-dev description: CERT C++ 2016 suites: codeql-suites license: MIT diff --git a/cpp/cert/test/qlpack.yml b/cpp/cert/test/qlpack.yml index c6d57b0d33..1baf2b3fc3 100644 --- a/cpp/cert/test/qlpack.yml +++ b/cpp/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards-tests -version: 2.44.0-dev +version: 2.45.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/common/src/qlpack.yml b/cpp/common/src/qlpack.yml index 302955fc78..47a116582c 100644 --- a/cpp/common/src/qlpack.yml +++ b/cpp/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards -version: 2.44.0-dev +version: 2.45.0-dev license: MIT dependencies: codeql/cpp-all: 2.1.1 diff --git a/cpp/common/test/qlpack.yml b/cpp/common/test/qlpack.yml index 1f0b830de8..a636b824dc 100644 --- a/cpp/common/test/qlpack.yml +++ b/cpp/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards-tests -version: 2.44.0-dev +version: 2.45.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/misra/src/qlpack.yml b/cpp/misra/src/qlpack.yml index 27e0893ed6..a98ccfa757 100644 --- a/cpp/misra/src/qlpack.yml +++ b/cpp/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards -version: 2.44.0-dev +version: 2.45.0-dev description: MISRA C++ 2023 default-suite: codeql-suites/misra-cpp-default.qls license: MIT diff --git a/cpp/misra/test/qlpack.yml b/cpp/misra/test/qlpack.yml index cdf6cbcdea..aad59493fe 100644 --- a/cpp/misra/test/qlpack.yml +++ b/cpp/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards-tests -version: 2.44.0-dev +version: 2.45.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/report/src/qlpack.yml b/cpp/report/src/qlpack.yml index 83188c2748..731d68dd29 100644 --- a/cpp/report/src/qlpack.yml +++ b/cpp/report/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/report-cpp-coding-standards -version: 2.44.0-dev +version: 2.45.0-dev license: MIT dependencies: codeql/cpp-all: 2.1.1 diff --git a/docs/user_manual.md b/docs/user_manual.md index 1e14744f80..2920e024a6 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -35,14 +35,14 @@ ## Release information -This user manual documents release `2.44.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). +This user manual documents release `2.45.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). The release page documents the release notes and contains the following artifacts part of the release: - `coding-standards-codeql-packs-2.37.0-dev.zip`: CodeQL packs that can be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `code-scanning-cpp-query-pack-2.44.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `supported_rules_list_2.44.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. -- `supported_rules_list_2.44.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. -- `user_manual_2.44.0-dev.md`: This user manual. +- `code-scanning-cpp-query-pack-2.45.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. +- `supported_rules_list_2.45.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. +- `supported_rules_list_2.45.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. +- `user_manual_2.45.0-dev.md`: This user manual. - `Source Code (zip)`: A zip archive containing the contents of https://github.com/github/codeql-coding-standards - `Source Code (tar.gz)`: A GZip compressed tar archive containing the contents of https://github.com/github/codeql-coding-standards - `checksums.txt`: A text file containing sha256 checksums for the aforementioned artifacts. @@ -667,7 +667,7 @@ This section describes known failure modes for "CodeQL Coding Standards" and des | | Out of space | Less output. Some files may be only be partially analyzed, or not analyzed at all. | Error reported on the command line. | Increase space. If it remains an issue report space consumption issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False positives | More output. Results are reported which are not violations of the guidelines. | All reported results must be reviewed. | Report false positive issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False negatives | Less output. Violations of the guidelines are not reported. | Other validation and verification processes during software development should be used to complement the analysis performed by CodeQL Coding Standards. | Report false negative issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.44.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | +| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.45.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | | | Incorrect deviation record specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation records with a reason. Ensure that all deviation records are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Incorrect deviation permit specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation permits with a reason. Ensure that all deviation permits are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Unapproved use of a deviation record | Less output. Results for guideline violations are not reported. | Validate that the deviation record use is approved by verifying the approved-by attribute of the deviation record specification. | Ensure that each raised deviation record is approved by an independent approver through an auditable process. | From a1f45ff00ee89988bd1ad0121a2ad7ceed2ece1f Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 1 May 2025 23:39:39 +0100 Subject: [PATCH 320/370] Add a script to lift CERT risk assessment tags from help files --- scripts/add_risk_assessment_tags.py | 160 ++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 scripts/add_risk_assessment_tags.py diff --git a/scripts/add_risk_assessment_tags.py b/scripts/add_risk_assessment_tags.py new file mode 100644 index 0000000000..f2ed9a5a73 --- /dev/null +++ b/scripts/add_risk_assessment_tags.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python3 +""" +Add risk assessment tags to rule package JSON files. + +This script: +1. Iterates through each JSON file in rule_packages directory +2. Looks for CERT-C or CERT-CPP sections +3. For each rule, finds the corresponding markdown file +4. Extracts risk assessment data from the markdown file +5. Adds risk assessment data as tags to each query in the JSON file +""" + +import os +import json +import re +import glob +from bs4 import BeautifulSoup +import logging + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') +logger = logging.getLogger(__name__) + +def find_rule_packages(): + """Find all JSON rule package files in the rule_packages directory.""" + repo_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + rule_packages_dir = os.path.join(repo_root, "rule_packages") + return glob.glob(os.path.join(rule_packages_dir, "**", "*.json"), recursive=True) + +def extract_risk_assessment_from_md(md_file_path): + """Extract risk assessment data from the markdown file.""" + risk_data = {} + + try: + with open(md_file_path, 'r', encoding='utf-8') as f: + content = f.read() + + # Find the Risk Assessment section + risk_section_match = re.search(r'## Risk Assessment(.*?)##', content, re.DOTALL) + if not risk_section_match: + # Try to find it as the last section + risk_section_match = re.search(r'## Risk Assessment(.*?)$', content, re.DOTALL) + if not risk_section_match: + logger.warning(f"No Risk Assessment section found in {md_file_path}") + return risk_data + + risk_section = risk_section_match.group(1) + + # Look for the table with risk assessment data + table_match = re.search(r'(.*?)
    ', risk_section, re.DOTALL) + if not table_match: + logger.warning(f"No risk assessment table found in {md_file_path}") + return risk_data + + table_html = table_match.group(0) + soup = BeautifulSoup(table_html, 'html.parser') + + # Find all rows in the table + rows = soup.find_all('tr') + if len(rows) < 2: # Need at least header and data row + logger.warning(f"Incomplete risk assessment table in {md_file_path}") + return risk_data + + # Extract headers and values + headers = [th.get_text().strip() for th in rows[0].find_all('th')] + values = [td.get_text().strip() for td in rows[1].find_all('td')] + + # Create a dictionary of headers and values + if len(headers) == len(values): + for i, header in enumerate(headers): + risk_data[header] = values[i] + else: + logger.warning(f"Header and value count mismatch in {md_file_path}") + + except Exception as e: + logger.error(f"Error extracting risk assessment from {md_file_path}: {e}") + + return risk_data + +def find_md_file(rule_id, short_name, language): + """Find the markdown file for the given rule ID and short name.""" + repo_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + md_path = os.path.join(repo_root, language, "cert", "src", "rules", rule_id, f"{short_name}.md") + + if os.path.exists(md_path): + return md_path + else: + # Try without short name (sometimes the file is named after the rule ID) + md_path = os.path.join(repo_root, language, "cert", "src", "rules", rule_id, f"{rule_id}.md") + if os.path.exists(md_path): + return md_path + else: + logger.warning(f"Could not find markdown file for {language} rule {rule_id} ({short_name})") + return None + +def process_rule_package(rule_package_file): + """Process a single rule package JSON file.""" + try: + with open(rule_package_file, 'r', encoding='utf-8') as f: + data = json.load(f) + + modified = False + + # Look for CERT-C and CERT-CPP sections + for cert_key in ["CERT-C", "CERT-C++"]: + if cert_key in data: + language = "c" if cert_key == "CERT-C" else "cpp" + + # Process each rule in the CERT section + for rule_id, rule_data in data[cert_key].items(): + if "queries" in rule_data: + for query in rule_data["queries"]: + if "short_name" in query: + md_file = find_md_file(rule_id, query["short_name"], language) + + if md_file: + risk_data = extract_risk_assessment_from_md(md_file) + + if risk_data: + # Add risk assessment data as tags + if "tags" not in query: + query["tags"] = [] + + # Add each risk assessment property as a tag + for key, value in risk_data.items(): + key_sanitized = key.lower().replace(" ", "-") + if key_sanitized == "rule": + # skip rule, as that is already in the rule ID + continue + tag = f"external/cert/{key_sanitized}/{value.lower()}" + if tag not in query["tags"]: + query["tags"].append(tag) + modified = True + logger.info(f"Added tag {tag} to {rule_id} ({query['short_name']})") + + # Save the modified data back to the file if any changes were made + if modified: + with open(rule_package_file, 'w', encoding='utf-8') as f: + json.dump(data, f, indent=2) + logger.info(f"Updated {rule_package_file}") + else: + logger.info(f"No changes made to {rule_package_file}") + + except Exception as e: + logger.error(f"Error processing {rule_package_file}: {e}") + +def main(): + """Main function to process all rule packages.""" + logger.info("Starting risk assessment tag addition process") + + rule_packages = find_rule_packages() + logger.info(f"Found {len(rule_packages)} rule package files") + + for rule_package in rule_packages: + logger.info(f"Processing {rule_package}") + process_rule_package(rule_package) + + logger.info("Completed risk assessment tag addition process") + +if __name__ == "__main__": + main() \ No newline at end of file From 242744c7e2f68f5af63feab8af20a6a2d1d14140 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 1 May 2025 23:41:37 +0100 Subject: [PATCH 321/370] Add additional CERT risk assessment tags --- rule_packages/c/Banned.json | 7 ++- rule_packages/c/Concurrency1.json | 21 ++++++- rule_packages/c/Concurrency2.json | 14 ++++- rule_packages/c/Concurrency3.json | 28 +++++++-- rule_packages/c/Concurrency4.json | 23 ++++++- rule_packages/c/Concurrency5.json | 14 ++++- rule_packages/c/Contracts.json | 7 ++- rule_packages/c/Contracts1.json | 14 ++++- rule_packages/c/Contracts2.json | 21 ++++++- rule_packages/c/Contracts4.json | 28 +++++++-- rule_packages/c/Contracts5.json | 14 ++++- rule_packages/c/Contracts6.json | 7 ++- rule_packages/c/Contracts7.json | 14 ++++- rule_packages/c/Declarations1.json | 14 ++++- rule_packages/c/Declarations2.json | 35 +++++++++-- rule_packages/c/Declarations7.json | 7 ++- rule_packages/c/Declarations8.json | 14 ++++- rule_packages/c/Expressions.json | 28 +++++++-- rule_packages/c/FloatingTypes.json | 28 +++++++-- rule_packages/c/IO1.json | 42 +++++++++++-- rule_packages/c/IO2.json | 28 +++++++-- rule_packages/c/IO3.json | 14 ++++- rule_packages/c/IO4.json | 28 +++++++-- rule_packages/c/IntegerOverflow.json | 35 +++++++++-- rule_packages/c/InvalidMemory1.json | 21 ++++++- rule_packages/c/InvalidMemory2.json | 21 ++++++- rule_packages/c/Memory2.json | 57 ++++++++++++++--- rule_packages/c/Memory3.json | 7 ++- rule_packages/c/Misc.json | 21 ++++++- rule_packages/c/OutOfBounds.json | 14 ++++- rule_packages/c/Pointers2.json | 7 ++- rule_packages/c/Pointers3.json | 36 +++++++++-- rule_packages/c/Preprocessor5.json | 14 ++++- rule_packages/c/SideEffects1.json | 29 +++++++-- rule_packages/c/SideEffects4.json | 7 ++- rule_packages/c/SignalHandlers.json | 28 +++++++-- rule_packages/c/Statements4.json | 7 ++- rule_packages/c/Strings1.json | 21 ++++++- rule_packages/c/Strings2.json | 7 ++- rule_packages/c/Strings3.json | 14 ++++- rule_packages/c/Types1.json | 16 ++++- rule_packages/cpp/Allocations.json | 77 +++++++++++++++++++---- rule_packages/cpp/BannedFunctions.json | 21 ++++++- rule_packages/cpp/BannedSyntax.json | 7 ++- rule_packages/cpp/Classes.json | 7 ++- rule_packages/cpp/Concurrency.json | 63 ++++++++++++++++--- rule_packages/cpp/Const.json | 7 ++- rule_packages/cpp/ExceptionSafety.json | 14 ++++- rule_packages/cpp/Exceptions1.json | 77 +++++++++++++++++++---- rule_packages/cpp/Exceptions2.json | 14 ++++- rule_packages/cpp/Expressions.json | 23 +++++-- rule_packages/cpp/Freed.json | 28 +++++++-- rule_packages/cpp/Functions.json | 21 ++++++- rule_packages/cpp/IO.json | 14 ++++- rule_packages/cpp/Inheritance.json | 24 ++++++- rule_packages/cpp/Initialization.json | 21 ++++++- rule_packages/cpp/Invariants.json | 28 +++++++-- rule_packages/cpp/Iterators.json | 35 +++++++++-- rule_packages/cpp/Lambdas.json | 14 ++++- rule_packages/cpp/MoveForward.json | 7 ++- rule_packages/cpp/Naming.json | 56 ++++++++++++++--- rule_packages/cpp/Null.json | 7 ++- rule_packages/cpp/OperatorInvariants.json | 14 ++++- rule_packages/cpp/OutOfBounds.json | 21 ++++++- rule_packages/cpp/Pointers.json | 42 +++++++++++-- rule_packages/cpp/Representation.json | 21 ++++++- rule_packages/cpp/Scope.json | 42 +++++++++++-- rule_packages/cpp/SideEffects1.json | 49 ++++++++++++--- rule_packages/cpp/SideEffects2.json | 7 ++- rule_packages/cpp/SmartPointers2.json | 15 ++++- rule_packages/cpp/Strings.json | 16 ++++- rule_packages/cpp/TrustBoundaries.json | 14 ++++- rule_packages/cpp/TypeRanges.json | 14 ++++- rule_packages/cpp/Uninitialized.json | 14 ++++- 74 files changed, 1411 insertions(+), 235 deletions(-) diff --git a/rule_packages/c/Banned.json b/rule_packages/c/Banned.json index 4decbae6f2..265a41de51 100644 --- a/rule_packages/c/Banned.json +++ b/rule_packages/c/Banned.json @@ -13,7 +13,12 @@ "severity": "error", "short_name": "DoNotCallSystem", "tags": [ - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p12", + "external/cert/level/l1" ] } ], diff --git a/rule_packages/c/Concurrency1.json b/rule_packages/c/Concurrency1.json index 15e38e941d..9daa2a83be 100644 --- a/rule_packages/c/Concurrency1.json +++ b/rule_packages/c/Concurrency1.json @@ -15,7 +15,12 @@ "shared_implementation_short_name": "GuardAccessToBitFields", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] } ], @@ -35,7 +40,12 @@ "short_name": "RaceConditionsWhenUsingLibraryFunctions", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -55,7 +65,12 @@ "short_name": "DoNotCallSignalInMultithreadedProgram", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/low", + "external/cert/priority/p6", + "external/cert/level/l2" ], "implementation_scope": { "description": "This implementation does not consider threads created function pointers." diff --git a/rule_packages/c/Concurrency2.json b/rule_packages/c/Concurrency2.json index d9102a07df..d9e364d046 100644 --- a/rule_packages/c/Concurrency2.json +++ b/rule_packages/c/Concurrency2.json @@ -15,7 +15,12 @@ "shared_implementation_short_name": "PreventDeadlockByLockingInPredefinedOrder", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -36,7 +41,12 @@ "shared_implementation_short_name": "WrapSpuriousFunctionInLoop", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/c/Concurrency3.json b/rule_packages/c/Concurrency3.json index a57b73f034..6328f6b43c 100644 --- a/rule_packages/c/Concurrency3.json +++ b/rule_packages/c/Concurrency3.json @@ -15,7 +15,12 @@ "shared_implementation_short_name": "DoNotAllowAMutexToGoOutOfScopeWhileLocked", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p4", + "external/cert/level/l3" ], "implementation_scope": { "description": "This implementation does not allow for thread synchronization to be performed in subroutines. All synchronization must be performed within the context of the other thread management functions." @@ -31,7 +36,12 @@ "shared_implementation_short_name": "DoNotDestroyAMutexWhileItIsLocked", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -52,7 +62,12 @@ "shared_implementation_short_name": "PreserveSafetyWhenUsingConditionVariables", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ], "implementation_scope": { "description": "This implementation does not attempt to identify unique condition variables and instead advocates for the usage of `cnd_broadcast`." @@ -75,7 +90,12 @@ "short_name": "WrapFunctionsThatCanFailSpuriouslyInLoop", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ], "implementation_scope": { "description": "This implementation does not attempt to identify a relationship between the condition variable and the atomic operation." diff --git a/rule_packages/c/Concurrency4.json b/rule_packages/c/Concurrency4.json index d537ee713e..45f4b495fc 100644 --- a/rule_packages/c/Concurrency4.json +++ b/rule_packages/c/Concurrency4.json @@ -14,7 +14,12 @@ "short_name": "CleanUpThreadSpecificStorage", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ], "implementation_scope": { "description": "This query does not attempt to ensure that the deallocation function in fact deallocates memory and instead assumes the contract is valid. Additionally, this query requires that all `tss_create` calls are bookended by calls to `tss_delete`, even if a thread is not created." @@ -37,7 +42,13 @@ "short_name": "AppropriateThreadObjectStorageDurations", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/recommendation/con34-c", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p4", + "external/cert/level/l3" ], "implementation_scope": { "description": "This query does not consider Windows implementations or OpenMP implementations. This query is primarily about excluding cases wherein the storage duration of a variable is appropriate. As such, this query is not concerned if the appropriate synchronization mechanisms are used, such as sequencing calls to `thrd_join` and `free`. An audit query is supplied to handle some of those cases." @@ -53,7 +64,13 @@ "tags": [ "external/cert/audit", "correctness", - "concurrency" + "concurrency", + "external/cert/recommendation/con34-c", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/c/Concurrency5.json b/rule_packages/c/Concurrency5.json index 0cef2d8b3a..d1a685dd34 100644 --- a/rule_packages/c/Concurrency5.json +++ b/rule_packages/c/Concurrency5.json @@ -15,7 +15,12 @@ "shared_implementation_short_name": "JoinOrDetachThreadOnlyOnce", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/low", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p6", + "external/cert/level/l2" ], "implementation_scope": { "description": "This query considers problematic usages of join and detach irrespective of the execution of the program and other synchronization and interprocess communication mechanisms that may be used." @@ -38,7 +43,12 @@ "short_name": "AtomicVariableTwiceInExpression", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/c/Contracts.json b/rule_packages/c/Contracts.json index e7db6fff86..0d2e0a97bd 100644 --- a/rule_packages/c/Contracts.json +++ b/rule_packages/c/Contracts.json @@ -13,7 +13,12 @@ "severity": "error", "short_name": "DoNotViolateInLineLinkageConstraints", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ], "implementation_scope": { "description": "This query only considers the constraints related to inline extern functions." diff --git a/rule_packages/c/Contracts1.json b/rule_packages/c/Contracts1.json index 21641922af..65ffdc5e71 100644 --- a/rule_packages/c/Contracts1.json +++ b/rule_packages/c/Contracts1.json @@ -14,7 +14,12 @@ "short_name": "DoNotModifyTheReturnValueOfCertainFunctions", "shared_implementation_short_name": "ConstLikeReturnValue", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -33,7 +38,12 @@ "severity": "error", "short_name": "EnvPointerIsInvalidAfterCertainOperations", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ], "implementation_scope": { "description": "The rule is enforced in the context of a single function." diff --git a/rule_packages/c/Contracts2.json b/rule_packages/c/Contracts2.json index b07f8f0503..6c1bf77de2 100644 --- a/rule_packages/c/Contracts2.json +++ b/rule_packages/c/Contracts2.json @@ -13,7 +13,12 @@ "severity": "error", "short_name": "ExitHandlersMustReturnNormally", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p12", + "external/cert/level/l1" ] } ], @@ -33,7 +38,12 @@ "short_name": "DoNotStorePointersReturnedByEnvFunctions", "shared_implementation_short_name": "InvalidatedEnvStringPointers", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] }, { @@ -45,7 +55,12 @@ "short_name": "DoNotStorePointersReturnedByEnvironmentFunWarn", "shared_implementation_short_name": "InvalidatedEnvStringPointersWarn", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/c/Contracts4.json b/rule_packages/c/Contracts4.json index 8ba25ab32b..a62e9d1762 100644 --- a/rule_packages/c/Contracts4.json +++ b/rule_packages/c/Contracts4.json @@ -13,7 +13,12 @@ "severity": "error", "short_name": "SetlocaleMightSetErrno", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] }, { @@ -24,7 +29,12 @@ "severity": "error", "short_name": "ErrnoReadBeforeReturn", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] }, { @@ -35,7 +45,12 @@ "severity": "error", "short_name": "FunctionCallBeforeErrnoCheck", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] }, { @@ -46,7 +61,12 @@ "severity": "error", "short_name": "ErrnoNotSetToZero", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/c/Contracts5.json b/rule_packages/c/Contracts5.json index 9f62ce9255..d4b38b5756 100644 --- a/rule_packages/c/Contracts5.json +++ b/rule_packages/c/Contracts5.json @@ -13,7 +13,12 @@ "severity": "error", "short_name": "DoNotRelyOnIndeterminateValuesOfErrno", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ], "implementation_scope": { "description": "The rule is enforced in the context of a single function." @@ -35,7 +40,12 @@ "severity": "error", "short_name": "DetectAndHandleStandardLibraryErrors", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ], "implementation_scope": { "description": "The rule is enforced in the context of a single function." diff --git a/rule_packages/c/Contracts6.json b/rule_packages/c/Contracts6.json index c46ef2f710..d89617d6dc 100644 --- a/rule_packages/c/Contracts6.json +++ b/rule_packages/c/Contracts6.json @@ -13,7 +13,12 @@ "severity": "error", "short_name": "DoNotModifyConstantObjects", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ], "implementation_scope": { "description": "The implementation does not consider pointer aliasing via multiple indirection." diff --git a/rule_packages/c/Contracts7.json b/rule_packages/c/Contracts7.json index f76b737db1..95df01ca32 100644 --- a/rule_packages/c/Contracts7.json +++ b/rule_packages/c/Contracts7.json @@ -14,7 +14,12 @@ "short_name": "DoNotPassInvalidDataToTheAsctimeFunction", "tags": [ "security", - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/low", + "external/cert/priority/p27", + "external/cert/level/l1" ] } ], @@ -33,7 +38,12 @@ "severity": "error", "short_name": "DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/c/Declarations1.json b/rule_packages/c/Declarations1.json index 90202a5b52..dba6a07eeb 100644 --- a/rule_packages/c/Declarations1.json +++ b/rule_packages/c/Declarations1.json @@ -15,7 +15,12 @@ "shared_implementation_short_name": "TypeOmitted", "tags": [ "correctness", - "readability" + "readability", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ], "implementation_scope": { "description": "This query does not check for implicitly typed parameters, typedefs or member declarations as this is partially compiler checked.", @@ -41,7 +46,12 @@ "tags": [ "correctness", "maintainability", - "readability" + "readability", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ], "implementation_scope": { "description": "This query does not consider identifiers described in the future library directions section of the standard. This query also checks for any reserved identifier as declared regardless of whether its header file is included or not.", diff --git a/rule_packages/c/Declarations2.json b/rule_packages/c/Declarations2.json index 9acb117d1e..c5b827e682 100644 --- a/rule_packages/c/Declarations2.json +++ b/rule_packages/c/Declarations2.json @@ -15,7 +15,12 @@ "tags": [ "correctness", "maintainability", - "readability" + "readability", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] } ], @@ -37,7 +42,12 @@ "tags": [ "correctness", "maintainability", - "readability" + "readability", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ], "implementation_scope": { "description": "This query considers the first 31 characters of identifiers as significant, as per C99 and reports the case when names are longer than 31 characters and differ in those characters past the 31 first only. This query does not consider universal or extended source characters.", @@ -54,7 +64,12 @@ "tags": [ "correctness", "maintainability", - "readability" + "readability", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ] }, { @@ -67,7 +82,12 @@ "tags": [ "correctness", "maintainability", - "readability" + "readability", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], @@ -88,7 +108,12 @@ "tags": [ "correctness", "maintainability", - "readability" + "readability", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/c/Declarations7.json b/rule_packages/c/Declarations7.json index cdb74123b1..86818cdcb5 100644 --- a/rule_packages/c/Declarations7.json +++ b/rule_packages/c/Declarations7.json @@ -14,7 +14,12 @@ "short_name": "InformationLeakageAcrossTrustBoundariesC", "shared_implementation_short_name": "InformationLeakageAcrossBoundaries", "tags": [ - "security" + "security", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/high", + "external/cert/priority/p1", + "external/cert/level/l3" ], "implementation_scope": { "description": "The rule does not detect cases where fields may have uninitialized padding but are initialized via an initializer." diff --git a/rule_packages/c/Declarations8.json b/rule_packages/c/Declarations8.json index a70523b72f..6275e32595 100644 --- a/rule_packages/c/Declarations8.json +++ b/rule_packages/c/Declarations8.json @@ -14,7 +14,12 @@ "short_name": "AppropriateStorageDurationsStackAdressEscape", "shared_implementation_short_name": "DoNotCopyAddressOfAutoStorageObjectToOtherObject", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ], "implementation_scope": { "description": "The rule checks specifically for pointers to objects with automatic storage duration that are assigned to static storage duration variables." @@ -28,7 +33,12 @@ "severity": "error", "short_name": "AppropriateStorageDurationsFunctionReturn", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ], "implementation_scope": { "description": "The rule checks specifically for pointers to objects with automatic storage duration that are returned by functions or assigned to function output parameters." diff --git a/rule_packages/c/Expressions.json b/rule_packages/c/Expressions.json index 9d1f8b16a7..9be722b761 100644 --- a/rule_packages/c/Expressions.json +++ b/rule_packages/c/Expressions.json @@ -13,7 +13,12 @@ "severity": "error", "short_name": "DoNotCallFunctionPointerWithIncompatibleType", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p4", + "external/cert/level/l3" ], "implementation_scope": { "description": "This query raises a result for a function assigned to a function pointer of an incompatible type even if the function pointer is never eventually called." @@ -27,7 +32,12 @@ "severity": "error", "short_name": "DoNotCallFunctionsWithIncompatibleArguments", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p4", + "external/cert/level/l3" ] }, { @@ -39,7 +49,12 @@ "short_name": "CallPOSIXOpenWithCorrectArgumentCount", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p4", + "external/cert/level/l3" ], "implementation_scope": { "description": "The analysis of invalid parameter count passed to POSIX open calls only applies when the value of the flags argument is computed locally." @@ -62,7 +77,12 @@ "short_name": "DoNotUseABitwiseOperatorWithABooleanLikeOperand", "tags": [ "maintainability", - "readability" + "readability", + "external/cert/severity/low", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/low", + "external/cert/priority/p9", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/c/FloatingTypes.json b/rule_packages/c/FloatingTypes.json index 7df2298ad1..17690574e5 100644 --- a/rule_packages/c/FloatingTypes.json +++ b/rule_packages/c/FloatingTypes.json @@ -14,7 +14,12 @@ "short_name": "UncheckedRangeDomainPoleErrors", "shared_implementation_short_name": "UncheckedRangeDomainPoleErrors", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ], "implementation_scope": { "description": "This query identifies possible domain, pole and range errors on a selection of C standard library fuctions from math.h." @@ -36,7 +41,12 @@ "severity": "error", "short_name": "UncheckedFloatingPointConversion", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] } ], @@ -55,7 +65,12 @@ "severity": "error", "short_name": "IntToFloatPreservePrecision", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], @@ -74,7 +89,12 @@ "severity": "error", "short_name": "MemcmpUsedToCompareFloats", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/c/IO1.json b/rule_packages/c/IO1.json index f5b9ec8b0e..8a42c4e52a 100644 --- a/rule_packages/c/IO1.json +++ b/rule_packages/c/IO1.json @@ -15,7 +15,12 @@ "shared_implementation_short_name": "NonConstantFormat", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], @@ -35,7 +40,12 @@ "short_name": "DistinguishBetweenCharReadFromAFileAndEofOrWeof", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p12", + "external/cert/level/l1" ], "implementation_scope": { "description": "The rule is enforced in the context of a single function. The query does not validate if the FILE status is handled correctly after being read." @@ -50,7 +60,12 @@ "short_name": "EndOfFileCheckPortability", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p12", + "external/cert/level/l1" ], "implementation_scope": { "description": "The rule is enforced in the context of a single function. The query does not validate if the FILE status is handled correctly after being read." @@ -73,7 +88,12 @@ "short_name": "DoNotAlternatelyIOFromAStreamWithoutPositioning", "shared_implementation_short_name": "IOFstreamMissingPositioning", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p6", + "external/cert/level/l2" ], "implementation_scope": { "description": "The rule is enforced in the context of a single function." @@ -97,7 +117,12 @@ "shared_implementation_short_name": "CloseFileHandleWhenNoLongerNeededShared", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ], "implementation_scope": { "description": "The rule is enforced in the context of a single function." @@ -120,7 +145,12 @@ "short_name": "UndefinedBehaviorAccessingAClosedFile", "shared_implementation_short_name": "DoNotAccessAClosedFile", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ], "implementation_scope": { "description": "The rule is enforced in the context of a single function." diff --git a/rule_packages/c/IO2.json b/rule_packages/c/IO2.json index 41c14a0d0e..69c12d7723 100644 --- a/rule_packages/c/IO2.json +++ b/rule_packages/c/IO2.json @@ -14,7 +14,12 @@ "short_name": "DoNotCopyAFileObject", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -34,7 +39,12 @@ "short_name": "ResetStringsOnFgetsOrFgetwsFailure", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -53,7 +63,12 @@ "severity": "error", "short_name": "DoNotCallGetcAndPutcWithSideEffects", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], @@ -72,7 +87,12 @@ "severity": "error", "short_name": "OnlyUseValuesForFsetposThatAreReturnedFromFgetpos", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/c/IO3.json b/rule_packages/c/IO3.json index 52276eb05c..af6e9da732 100644 --- a/rule_packages/c/IO3.json +++ b/rule_packages/c/IO3.json @@ -14,7 +14,12 @@ "short_name": "DoNotPerformFileOperationsOnDevices", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ], "implementation_scope": { "description": "The rule checks that filenames are not tainted. It does not verify that appropriate OS-specific checks are in place to exclude that the opened file is a device." @@ -36,7 +41,12 @@ "severity": "error", "short_name": "SuccessfulFgetsOrFgetwsMayReturnAnEmptyString", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p12", + "external/cert/level/l1" ], "implementation_scope": { "description": "The rule checks that access to a string returned by fgets() or fgetws() if protected by a guard condition. The rule is enforced in the context of a single function." diff --git a/rule_packages/c/IO4.json b/rule_packages/c/IO4.json index 1303f9b50f..8d9c150335 100644 --- a/rule_packages/c/IO4.json +++ b/rule_packages/c/IO4.json @@ -14,7 +14,12 @@ "short_name": "ToctouRaceConditionsWhileAccessingFiles", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ], "implementation_scope": { "description": "The query is limited to the specific class of TOCTOU race conditions that derives from the incorrectuse of `fopen` to check the existence of a file." @@ -37,7 +42,12 @@ "short_name": "UseValidSpecifiers", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p6", + "external/cert/level/l2" ] }, { @@ -49,7 +59,12 @@ "short_name": "WrongNumberOfFormatArguments", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p6", + "external/cert/level/l2" ] }, { @@ -61,7 +76,12 @@ "short_name": "WrongTypeFormatArguments", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/c/IntegerOverflow.json b/rule_packages/c/IntegerOverflow.json index a7897fad9e..f528d3d542 100644 --- a/rule_packages/c/IntegerOverflow.json +++ b/rule_packages/c/IntegerOverflow.json @@ -15,7 +15,12 @@ "shared_implementation_short_name": "UnsignedOperationWithConstantOperandsWraps", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/high", + "external/cert/priority/p9", + "external/cert/level/l2" ] } ], @@ -34,7 +39,12 @@ "severity": "error", "short_name": "IntegerConversionCausesDataLoss", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], @@ -54,7 +64,12 @@ "short_name": "SignedIntegerOverflow", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/high", + "external/cert/priority/p9", + "external/cert/level/l2" ] } ], @@ -73,7 +88,12 @@ "severity": "error", "short_name": "DivOrRemByZero", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], @@ -92,7 +112,12 @@ "severity": "error", "short_name": "UseCorrectIntegerPrecisions", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/c/InvalidMemory1.json b/rule_packages/c/InvalidMemory1.json index 227ec37558..3b0a6bb40c 100644 --- a/rule_packages/c/InvalidMemory1.json +++ b/rule_packages/c/InvalidMemory1.json @@ -15,7 +15,12 @@ "short_name": "DoNotReadUninitializedMemory", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p12", + "external/cert/level/l1" ] } ], @@ -35,7 +40,12 @@ "shared_implementation_short_name": "DereferenceOfNullPointer", "short_name": "DoNotDereferenceNullPointers", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], @@ -55,7 +65,12 @@ "short_name": "DoNotAccessFreedMemory", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], diff --git a/rule_packages/c/InvalidMemory2.json b/rule_packages/c/InvalidMemory2.json index cb7d380159..025a5d246c 100644 --- a/rule_packages/c/InvalidMemory2.json +++ b/rule_packages/c/InvalidMemory2.json @@ -14,7 +14,12 @@ "short_name": "VariableLengthArraySizeNotInValidRange", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], @@ -33,7 +38,12 @@ "severity": "error", "short_name": "DoNotUsePointerArithmeticOnNonArrayObjectPointers", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] } ], @@ -52,7 +62,12 @@ "severity": "error", "short_name": "DoNotModifyObjectsWithTemporaryLifetime", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ], "implementation_scope": { "description": "This implementation also always reports non-modifying accesses of objects with temporary lifetime, which are only compliant in C11." diff --git a/rule_packages/c/Memory2.json b/rule_packages/c/Memory2.json index 358d482194..9f475e4df8 100644 --- a/rule_packages/c/Memory2.json +++ b/rule_packages/c/Memory2.json @@ -14,7 +14,12 @@ "short_name": "DoNotSubtractPointersThatDoNotReferToTheSameArray", "shared_implementation_short_name": "DoNotSubtractPointersAddressingDifferentArrays", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] }, { @@ -26,7 +31,12 @@ "short_name": "DoNotRelatePointersThatDoNotReferToTheSameArray", "shared_implementation_short_name": "DoNotUseRelationalOperatorsWithDifferingArrays", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] } ], @@ -46,7 +56,12 @@ "short_name": "DoNotComparePaddingData", "shared_implementation_short_name": "MemcmpUsedToComparePaddingData", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] } ], @@ -67,7 +82,12 @@ "shared_implementation_short_name": "FreeMemoryWhenNoLongerNeededShared", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ], "implementation_scope": { "description": "The rule is enforced in the context of a single function." @@ -89,7 +109,12 @@ "severity": "error", "short_name": "AllocStructsWithAFlexibleArrayMemberDynamically", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] }, { @@ -100,7 +125,12 @@ "severity": "error", "short_name": "CopyStructsWithAFlexibleArrayMemberDynamically", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] } ], @@ -121,7 +151,12 @@ "shared_implementation_short_name": "OnlyFreeMemoryAllocatedDynamicallyShared", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], @@ -141,7 +176,13 @@ "short_name": "DoNotModifyAlignmentOfMemoryWithRealloc", "tags": [ "correctness", - "security" + "security", + "external/cert/recommendation/mem36-c", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/c/Memory3.json b/rule_packages/c/Memory3.json index 6eafcc6509..e1ed7382e0 100644 --- a/rule_packages/c/Memory3.json +++ b/rule_packages/c/Memory3.json @@ -14,7 +14,12 @@ "short_name": "InsufficientMemoryAllocatedForObject", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/c/Misc.json b/rule_packages/c/Misc.json index bba96db85c..183c05988b 100644 --- a/rule_packages/c/Misc.json +++ b/rule_packages/c/Misc.json @@ -14,7 +14,12 @@ "short_name": "RandUsedForGeneratingPseudorandomNumbers", "shared_implementation_short_name": "DoNotUseRandForGeneratingPseudorandomNumbers", "tags": [ - "security" + "security", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], @@ -33,7 +38,12 @@ "severity": "error", "short_name": "ProperlySeedPseudorandomNumberGenerators", "tags": [ - "security" + "security", + "external/cert/severity/medium", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/low", + "external/cert/priority/p18", + "external/cert/level/l1" ], "implementation_scope": { "description": "This rule will be checked by looking for calls to random that are no preceded by a call to srandom(). We perform a simple check for the argument to srandom() and verify it is not a literal (or a value easily deduced to be a literal)." @@ -56,7 +66,12 @@ "short_name": "ControlFlowReachesTheEndOfANonVoidFunction", "shared_implementation_short_name": "NonVoidFunctionDoesNotReturn", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p9", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/c/OutOfBounds.json b/rule_packages/c/OutOfBounds.json index 759b68e294..3354348230 100644 --- a/rule_packages/c/OutOfBounds.json +++ b/rule_packages/c/OutOfBounds.json @@ -14,7 +14,12 @@ "short_name": "DoNotFormOutOfBoundsPointersOrArraySubscripts", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/high", + "external/cert/priority/p9", + "external/cert/level/l2" ] } ], @@ -34,7 +39,12 @@ "short_name": "LibraryFunctionArgumentOutOfBounds", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], diff --git a/rule_packages/c/Pointers2.json b/rule_packages/c/Pointers2.json index 9abf4c98ce..fcfd9356e6 100644 --- a/rule_packages/c/Pointers2.json +++ b/rule_packages/c/Pointers2.json @@ -13,7 +13,12 @@ "severity": "error", "short_name": "DoNotAddOrSubtractAScaledIntegerToAPointer", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/c/Pointers3.json b/rule_packages/c/Pointers3.json index f35f5b7bd1..f00018b1ad 100644 --- a/rule_packages/c/Pointers3.json +++ b/rule_packages/c/Pointers3.json @@ -13,7 +13,12 @@ "severity": "error", "short_name": "DoNotAccessVolatileObjectWithNonVolatileReference", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p6", + "external/cert/level/l2" ], "implementation_scope": { "description": "In limited cases, this query can raise false-positives for assignment of volatile objects and subsequent accesses of those objects via non-volatile pointers." @@ -35,7 +40,12 @@ "severity": "error", "short_name": "DoNotCastPointerToMoreStrictlyAlignedPointerType", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -54,7 +64,13 @@ "severity": "error", "short_name": "DoNotAccessVariableViaPointerOfIncompatibleType", "tags": [ - "correctness" + "correctness", + "external/cert/recommendation/exp39-c", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/high", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], @@ -74,7 +90,12 @@ "short_name": "DoNotPassAliasedPointerToRestrictQualifiedParam", "shared_implementation_short_name": "DoNotPassAliasedPointerToRestrictQualifiedParamShared", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p4", + "external/cert/level/l3" ] }, { @@ -85,7 +106,12 @@ "severity": "error", "short_name": "RestrictPointerReferencesOverlappingObject", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/c/Preprocessor5.json b/rule_packages/c/Preprocessor5.json index ef17b83c00..60a1752e73 100644 --- a/rule_packages/c/Preprocessor5.json +++ b/rule_packages/c/Preprocessor5.json @@ -14,7 +14,12 @@ "short_name": "DoNotTreatAPredefinedIdentifierAsObject", "tags": [ "correctness", - "readability" + "readability", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ], "implementation_scope": { "description": "This query reports locations corresponding to both redefinitions of those standard library macros as well as locations where the identifiers used for accesses.", @@ -38,7 +43,12 @@ "short_name": "MacroOrFunctionArgsContainHashToken", "tags": [ "correctness", - "readability" + "readability", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ], "implementation_scope": { "description": "This query defines end of function call as the next node in the control flow graph.", diff --git a/rule_packages/c/SideEffects1.json b/rule_packages/c/SideEffects1.json index 9d91fce671..7e0ab9c90b 100644 --- a/rule_packages/c/SideEffects1.json +++ b/rule_packages/c/SideEffects1.json @@ -13,7 +13,12 @@ "severity": "warning", "short_name": "DependenceOnOrderOfScalarEvaluationForSideEffects", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] }, { @@ -24,7 +29,12 @@ "severity": "warning", "short_name": "DependenceOnOrderOfFunctionArgumentsForSideEffects", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] } ], @@ -43,7 +53,12 @@ "severity": "error", "short_name": "UnevaluatedOperandWithSideEffect", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] } ], @@ -62,7 +77,13 @@ "severity": "error", "short_name": "AssignmentsInSelectionStatements", "tags": [ - "correctness" + "correctness", + "external/cert/recommendation/exp45-c", + "external/cert/severity/low", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/c/SideEffects4.json b/rule_packages/c/SideEffects4.json index 77121019de..5b0c6da3f5 100644 --- a/rule_packages/c/SideEffects4.json +++ b/rule_packages/c/SideEffects4.json @@ -13,7 +13,12 @@ "severity": "error", "short_name": "SideEffectsInArgumentsToUnsafeMacros", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ], "implementation_scope": { "description": "This implementation only considers ++ and function call side effects. Due to the textual nature of macro expansion it is not always possible to determine accurately whether a side-effect was produced by a particular argument, and this may cause both false positives and false negatives. The query does not consider the case where a macro argument including a side-effect is never evaluated." diff --git a/rule_packages/c/SignalHandlers.json b/rule_packages/c/SignalHandlers.json index 0ceaa5914d..ae9045a64d 100644 --- a/rule_packages/c/SignalHandlers.json +++ b/rule_packages/c/SignalHandlers.json @@ -14,7 +14,12 @@ "short_name": "CallOnlyAsyncSafeFunctionsWithinSignalHandlers", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], @@ -34,7 +39,12 @@ "short_name": "DoNotAccessSharedObjectsInSignalHandlers", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/high", + "external/cert/priority/p9", + "external/cert/level/l2" ], "implementation_scope": { "description": "The implementation does not verify the correct usage of `atomic_is_lock_free`." @@ -57,7 +67,12 @@ "short_name": "DoNotCallSignalFromInterruptibleSignalHandlers", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] } ], @@ -77,7 +92,12 @@ "short_name": "DoNotReturnFromAComputationalExceptionHandler", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/high", + "external/cert/priority/p1", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/c/Statements4.json b/rule_packages/c/Statements4.json index 5b0cc9be26..e770fe032a 100644 --- a/rule_packages/c/Statements4.json +++ b/rule_packages/c/Statements4.json @@ -15,7 +15,12 @@ "tags": [ "maintainability", "readability", - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/low", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/c/Strings1.json b/rule_packages/c/Strings1.json index 39529df3cc..c4565fc898 100644 --- a/rule_packages/c/Strings1.json +++ b/rule_packages/c/Strings1.json @@ -14,7 +14,12 @@ "short_name": "DoNotAttemptToModifyStringLiterals", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/low", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/low", + "external/cert/priority/p9", + "external/cert/level/l2" ] } ], @@ -34,7 +39,12 @@ "short_name": "StringsHasSufficientSpaceForTheNullTerminator", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ], "implementation_scope": { "description": "The enforcement of this rule does not try to approximate the effects of loops and as such may not find cases where a loop operation on a string fails to null terminate a string (or causes an overflow)." @@ -57,7 +67,12 @@ "short_name": "NonNullTerminatedToFunctionThatExpectsAString", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p12", + "external/cert/level/l1" ], "implementation_scope": { "description": "Wide character types are not handled correctly on the `aarch64le` architecture. This can lead to false negative alerts." diff --git a/rule_packages/c/Strings2.json b/rule_packages/c/Strings2.json index 99f5e240d7..a32b1b4c28 100644 --- a/rule_packages/c/Strings2.json +++ b/rule_packages/c/Strings2.json @@ -14,7 +14,12 @@ "short_name": "ToCharacterHandlingFunctionsRepresentableAsUChar", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/c/Strings3.json b/rule_packages/c/Strings3.json index 1cecf390ec..c9003f2ff8 100644 --- a/rule_packages/c/Strings3.json +++ b/rule_packages/c/Strings3.json @@ -15,7 +15,12 @@ "shared_implementation_short_name": "CastCharBeforeConvertingToLargerSizes", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] } ], @@ -35,7 +40,12 @@ "short_name": "DoNotConfuseNarrowAndWideFunctions", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/low", + "external/cert/priority/p27", + "external/cert/level/l1" ], "implementation_scope": { "description": "Wide character types are not handled correctly on the `aarch64le` architecture. This can lead to false negative alerts." diff --git a/rule_packages/c/Types1.json b/rule_packages/c/Types1.json index cbf7f0b632..bb451eba70 100644 --- a/rule_packages/c/Types1.json +++ b/rule_packages/c/Types1.json @@ -12,7 +12,13 @@ "precision": "very-high", "severity": "error", "short_name": "ExprShiftedbyNegativeOrGreaterPrecisionOperand", - "tags": [] + "tags": [ + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" + ] } ], "title": "Do not shift an expression by a negative number of bits or by greater than or equal to the number of bits that exist in the operand" @@ -29,7 +35,13 @@ "precision": "very-high", "severity": "error", "short_name": "ConvertingAPointerToIntegerOrIntegerToPointer", - "tags": [] + "tags": [ + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p2", + "external/cert/level/l3" + ] } ], "title": "Converting a pointer to integer or integer to pointer" diff --git a/rule_packages/cpp/Allocations.json b/rule_packages/cpp/Allocations.json index 6b40523e16..416cd3b567 100644 --- a/rule_packages/cpp/Allocations.json +++ b/rule_packages/cpp/Allocations.json @@ -197,7 +197,12 @@ "short_name": "ProperlyDeallocateDynamicallyAllocatedResources", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], @@ -216,7 +221,12 @@ "severity": "error", "short_name": "DetectAndHandleMemoryAllocationErrors", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], @@ -235,7 +245,12 @@ "severity": "error", "short_name": "MissingConstructorCallForManuallyManagedObject", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] }, { @@ -246,7 +261,12 @@ "severity": "error", "short_name": "MissingDestructorCallForManuallyManagedObject", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], @@ -267,7 +287,12 @@ "shared_implementation_short_name": "PlacementNewNotProperlyAligned", "tags": [ "security", - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] }, { @@ -280,7 +305,12 @@ "shared_implementation_short_name": "PlacementNewInsufficientStorage", "tags": [ "security", - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], @@ -300,7 +330,12 @@ "short_name": "ThrowingOperatorNewReturnsNullCert", "shared_implementation_short_name": "ThrowingOperatorNewReturnsNull", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] }, { @@ -312,7 +347,12 @@ "short_name": "ThrowingOperatorNewThrowsInvalidExceptionCert", "shared_implementation_short_name": "ThrowingOperatorNewThrowsInvalidException", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] }, { @@ -324,7 +364,12 @@ "short_name": "ThrowingNoThrowOperatorNewDeleteCert", "shared_implementation_short_name": "ThrowingNoThrowOperatorNewDelete", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] }, { @@ -336,7 +381,12 @@ "short_name": "OperatorDeleteMissingPartnerCert", "shared_implementation_short_name": "OperatorDeleteMissingPartner", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], @@ -356,7 +406,12 @@ "short_name": "UsingDefaultOperatorNewForOverAlignedTypes", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/cpp/BannedFunctions.json b/rule_packages/cpp/BannedFunctions.json index 8ef93db1a0..6cdb019ace 100644 --- a/rule_packages/cpp/BannedFunctions.json +++ b/rule_packages/cpp/BannedFunctions.json @@ -215,7 +215,12 @@ "shared_implementation_short_name": "DoNotUseSetjmpOrLongjmpShared", "tags": [ "correctness", - "scope/single-translation-unit" + "scope/single-translation-unit", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -236,7 +241,12 @@ "shared_implementation_short_name": "DoNotUseRandForGeneratingPseudorandomNumbers", "tags": [ "security", - "scope/single-translation-unit" + "scope/single-translation-unit", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], @@ -256,7 +266,12 @@ "short_name": "PreferSpecialMemberFunctionsAndOverloadedOperatorsToCStandardLibraryFunctions", "tags": [ "correctness", - "scope/single-translation-unit" + "scope/single-translation-unit", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/cpp/BannedSyntax.json b/rule_packages/cpp/BannedSyntax.json index 8e307c02db..8f739145f7 100644 --- a/rule_packages/cpp/BannedSyntax.json +++ b/rule_packages/cpp/BannedSyntax.json @@ -417,7 +417,12 @@ "tags": [ "correctness", "security", - "scope/single-translation-unit" + "scope/single-translation-unit", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p12", + "external/cert/level/l1" ] } ], diff --git a/rule_packages/cpp/Classes.json b/rule_packages/cpp/Classes.json index 59eb9a0418..e7c8a10d92 100644 --- a/rule_packages/cpp/Classes.json +++ b/rule_packages/cpp/Classes.json @@ -315,7 +315,12 @@ "severity": "recommendation", "short_name": "OffsetUsedOnInvalidTypeOrMember", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/cpp/Concurrency.json b/rule_packages/cpp/Concurrency.json index 6e5898ecd8..3bba2f409f 100644 --- a/rule_packages/cpp/Concurrency.json +++ b/rule_packages/cpp/Concurrency.json @@ -15,7 +15,12 @@ "shared_implementation_short_name": "DoNotAllowAMutexToGoOutOfScopeWhileLocked", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p4", + "external/cert/level/l3" ] }, { @@ -28,7 +33,12 @@ "shared_implementation_short_name": "DoNotDestroyAMutexWhileItIsLocked", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -48,7 +58,12 @@ "short_name": "EnsureActivelyHeldLocksAreReleasedOnExceptionalConditions", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/low", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], @@ -69,7 +84,12 @@ "shared_implementation_short_name": "GuardAccessToBitFields", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] } ], @@ -90,7 +110,12 @@ "shared_implementation_short_name": "PreventDeadlockByLockingInPredefinedOrder", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -111,7 +136,12 @@ "shared_implementation_short_name": "WrapSpuriousFunctionInLoop", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], @@ -132,7 +162,12 @@ "shared_implementation_short_name": "PreserveSafetyWhenUsingConditionVariables", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], @@ -152,7 +187,12 @@ "short_name": "DoNotSpeculativelyLockALockedNonRecursiveMutex", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/high", + "external/cert/priority/p1", + "external/cert/level/l3" ] }, { @@ -164,7 +204,12 @@ "short_name": "LockedALockedNonRecursiveMutexAudit", "tags": [ "correctness", - "concurrency" + "concurrency", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/high", + "external/cert/priority/p1", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/cpp/Const.json b/rule_packages/cpp/Const.json index 55c5ed6f90..6f76b7f5b8 100644 --- a/rule_packages/cpp/Const.json +++ b/rule_packages/cpp/Const.json @@ -251,7 +251,12 @@ "shared_implementation_short_name": "RemoveConstOrVolatileQualification", "short_name": "RemoveConstOrVolatileQualificationCert", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/cpp/ExceptionSafety.json b/rule_packages/cpp/ExceptionSafety.json index 07e97ae328..73b84edde4 100644 --- a/rule_packages/cpp/ExceptionSafety.json +++ b/rule_packages/cpp/ExceptionSafety.json @@ -90,7 +90,12 @@ "short_name": "GuaranteeExceptionSafety", "shared_implementation_short_name": "ExceptionSafetyGuarantees", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/high", + "external/cert/priority/p9", + "external/cert/level/l2" ] } ], @@ -111,7 +116,12 @@ "shared_implementation_short_name": "ExceptionSafetyValidState", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/cpp/Exceptions1.json b/rule_packages/cpp/Exceptions1.json index 23b37778db..7c3a2a708a 100644 --- a/rule_packages/cpp/Exceptions1.json +++ b/rule_packages/cpp/Exceptions1.json @@ -502,7 +502,12 @@ "shared_implementation_short_name": "ConditionVariablePostConditionFailed", "tags": [ "correctness", - "external/cert/audit" + "external/cert/audit", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] }, { @@ -513,7 +518,12 @@ "short_name": "JoinableThreadCopiedOrDestroyedCert", "shared_implementation_short_name": "JoinableThreadCopiedOrDestroyed", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] }, { @@ -525,7 +535,12 @@ "short_name": "RethrowNestedWithoutCaptureCert", "shared_implementation_short_name": "RethrowNestedWithoutCapture", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] }, { @@ -537,7 +552,12 @@ "short_name": "ExplicitAbruptTerminationCert", "shared_implementation_short_name": "ExplicitAbruptTermination", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] }, { @@ -549,7 +569,12 @@ "short_name": "ExitHandlerThrowsExceptionCert", "shared_implementation_short_name": "ExitHandlerThrowsException", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -568,7 +593,12 @@ "kind": "path-problem", "short_name": "HandleAllExceptions", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -587,7 +617,12 @@ "shared_implementation_short_name": "DestroyedValueReferencedInDestructorCatchBlock", "short_name": "DestroyedValueReferencedInConstructorDestructorCatchBlock", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], @@ -606,7 +641,12 @@ "kind": "path-problem", "short_name": "HonorExceptionSpecifications", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/low", + "external/cert/priority/p9", + "external/cert/level/l2" ] } ], @@ -626,7 +666,12 @@ "shared_implementation_short_name": "HandleAllExceptionsDuringStartup", "short_name": "HandleAllExceptionsThrownBeforeMainBeginsExecuting", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/low", + "external/cert/priority/p9", + "external/cert/level/l2" ] } ], @@ -644,7 +689,12 @@ "severity": "error", "short_name": "ExceptionObjectsMustBeNothrowCopyConstructible", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -663,7 +713,12 @@ "shared_implementation_short_name": "CatchExceptionsByLvalueReference", "short_name": "CatchExceptionsByLvalueReference", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/cpp/Exceptions2.json b/rule_packages/cpp/Exceptions2.json index ece305a04a..2e2f2dfba6 100644 --- a/rule_packages/cpp/Exceptions2.json +++ b/rule_packages/cpp/Exceptions2.json @@ -295,7 +295,12 @@ "severity": "error", "short_name": "DoNotLetExceptionsEscapeFromDestructorsOrDeallocationFunctions", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], @@ -315,7 +320,12 @@ "shared_implementation_short_name": "CatchBlockShadowing", "short_name": "CatchBlockShadowingCert", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/low", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], diff --git a/rule_packages/cpp/Expressions.json b/rule_packages/cpp/Expressions.json index 935c3fa6f1..10f85237de 100644 --- a/rule_packages/cpp/Expressions.json +++ b/rule_packages/cpp/Expressions.json @@ -130,7 +130,7 @@ }, "queries": [ { - "description": "Expressions with type (plain) char and wchar_t shall not be used as operands to built-in operators other than the assignment operator =, the equality operators == and ! =, and the unary & operator. Manipulation of character data may generate results that are contrary to developer expectations. For example, ISO/IEC 14882:2003 [1] §2.2(3) only requires that the digits \"0\" to \"9\" have consecutive numerical values.", + "description": "Expressions with type (plain) char and wchar_t shall not be used as operands to built-in operators other than the assignment operator =, the equality operators == and ! =, and the unary & operator. Manipulation of character data may generate results that are contrary to developer expectations. For example, ISO/IEC 14882:2003 [1] \u00a72.2(3) only requires that the digits \"0\" to \"9\" have consecutive numerical values.", "kind": "problem", "name": "Expressions with type (plain) char and wchar_t shall only be used as operands to =, ==, !=, &", "precision": "very-high", @@ -323,7 +323,12 @@ "severity": "error", "short_name": "PassPromotablePrimitiveTypeToVaStart", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] }, { @@ -334,7 +339,12 @@ "severity": "error", "short_name": "PassReferenceTypeToVaStart", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] }, { @@ -345,7 +355,12 @@ "severity": "warning", "short_name": "PassNonTrivialObjectToVaStart", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/cpp/Freed.json b/rule_packages/cpp/Freed.json index 36b9b31c3d..30ab6982b2 100644 --- a/rule_packages/cpp/Freed.json +++ b/rule_packages/cpp/Freed.json @@ -111,7 +111,12 @@ "severity": "error", "short_name": "DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], @@ -132,7 +137,12 @@ "short_name": "ObjectAccessedBeforeLifetimeCert", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] }, { @@ -145,7 +155,12 @@ "short_name": "ObjectAccessedAfterLifetimeCert", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], @@ -166,7 +181,12 @@ "short_name": "UseAfterFree", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], diff --git a/rule_packages/cpp/Functions.json b/rule_packages/cpp/Functions.json index 367ab67437..b650b0937c 100644 --- a/rule_packages/cpp/Functions.json +++ b/rule_packages/cpp/Functions.json @@ -281,7 +281,12 @@ "severity": "error", "short_name": "FunctionWithMismatchedLanguageLinkage", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], @@ -301,7 +306,12 @@ "short_name": "NonVoidFunctionDoesNotReturnCert", "shared_implementation_short_name": "NonVoidFunctionDoesNotReturn", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] } ], @@ -321,7 +331,12 @@ "short_name": "FunctionNoReturnAttributeConditionCert", "shared_implementation_short_name": "FunctionNoReturnAttributeCondition", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/cpp/IO.json b/rule_packages/cpp/IO.json index 9ad0650e62..3d1012232c 100644 --- a/rule_packages/cpp/IO.json +++ b/rule_packages/cpp/IO.json @@ -43,7 +43,12 @@ "short_name": "InterleavedInputOutputWithoutPosition", "shared_implementation_short_name": "IOFstreamMissingPositioning", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], @@ -63,7 +68,12 @@ "short_name": "CloseFilesWhenTheyAreNoLongerNeeded", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/cpp/Inheritance.json b/rule_packages/cpp/Inheritance.json index efc241a8e6..fc4805fc21 100644 --- a/rule_packages/cpp/Inheritance.json +++ b/rule_packages/cpp/Inheritance.json @@ -229,7 +229,13 @@ "precision": "very-high", "severity": "error", "short_name": "DoNotInvokeVirtualFunctionsFromConstructorsOrDestructors", - "tags": [] + "tags": [ + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" + ] } ], "title": "Do not invoke virtual functions from constructors or destructors" @@ -246,7 +252,13 @@ "precision": "very-high", "severity": "error", "short_name": "DoNotSliceDerivedObjects", - "tags": [] + "tags": [ + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" + ] } ], "title": "Do not slice derived objects" @@ -263,7 +275,13 @@ "precision": "very-high", "severity": "warning", "short_name": "DoNotDeleteAPolymorphicObjectWithoutAVirtualDestructor", - "tags": [] + "tags": [ + "external/cert/severity/low", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/low", + "external/cert/priority/p9", + "external/cert/level/l2" + ] } ], "title": "Do not delete a polymorphic object without a virtual destructor" diff --git a/rule_packages/cpp/Initialization.json b/rule_packages/cpp/Initialization.json index 3ca901a865..e81160a273 100644 --- a/rule_packages/cpp/Initialization.json +++ b/rule_packages/cpp/Initialization.json @@ -417,7 +417,12 @@ "short_name": "CyclesDuringStaticObjectInit", "tags": [ "correctness", - "maintainability" + "maintainability", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], @@ -437,7 +442,12 @@ "short_name": "BadlySeededRandomNumberGenerator", "tags": [ "security", - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/low", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], @@ -460,7 +470,12 @@ "correctness", "security", "maintainability", - "readability" + "readability", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/cpp/Invariants.json b/rule_packages/cpp/Invariants.json index b473fb499d..215e4edff4 100644 --- a/rule_packages/cpp/Invariants.json +++ b/rule_packages/cpp/Invariants.json @@ -63,7 +63,12 @@ "shared_implementation_short_name": "OrderingPredicateMustBeStrictlyWeak", "short_name": "ProvideAValidOrderingPredicate", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], @@ -82,7 +87,12 @@ "severity": "error", "short_name": "SignalHandlerMustBeAPlainOldFunction", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], @@ -101,7 +111,12 @@ "severity": "error", "short_name": "HonorTerminationReplacementHandlerRequirements", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p2", + "external/cert/level/l3" ] }, { @@ -112,7 +127,12 @@ "severity": "error", "short_name": "HonorNewReplacementHandlerRequirements", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/cpp/Iterators.json b/rule_packages/cpp/Iterators.json index a43740f7e7..c345adb371 100644 --- a/rule_packages/cpp/Iterators.json +++ b/rule_packages/cpp/Iterators.json @@ -61,7 +61,12 @@ "severity": "error", "short_name": "UsesValidContainerElementAccess", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], @@ -80,7 +85,12 @@ "severity": "error", "short_name": "UseValidIteratorRanges", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], @@ -99,7 +109,12 @@ "severity": "error", "short_name": "DoNotSubtractIteratorsForDifferentContainers", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] } ], @@ -118,7 +133,12 @@ "severity": "error", "short_name": "DoNotUseAnAdditiveOperatorOnAnIterator", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], @@ -138,7 +158,12 @@ "severity": "error", "short_name": "UseValidReferencesForElementsOfString", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/cpp/Lambdas.json b/rule_packages/cpp/Lambdas.json index ea43fa0231..8f973c361f 100644 --- a/rule_packages/cpp/Lambdas.json +++ b/rule_packages/cpp/Lambdas.json @@ -205,7 +205,12 @@ "shared_implementation_short_name": "DanglingCaptureWhenReturningLambdaObject", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] }, { @@ -218,7 +223,12 @@ "shared_implementation_short_name": "DanglingCaptureWhenMovingLambdaObject", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/cpp/MoveForward.json b/rule_packages/cpp/MoveForward.json index b7e47116f1..6f071a6f53 100644 --- a/rule_packages/cpp/MoveForward.json +++ b/rule_packages/cpp/MoveForward.json @@ -154,7 +154,12 @@ "short_name": "DoNotRelyOnTheValueOfAMovedFromObject", "shared_implementation_short_name": "MovedFromObjectsUnspecifiedState", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/cpp/Naming.json b/rule_packages/cpp/Naming.json index 441979c3c9..34a9f2c66e 100644 --- a/rule_packages/cpp/Naming.json +++ b/rule_packages/cpp/Naming.json @@ -382,7 +382,12 @@ "severity": "error", "short_name": "RedefiningOfStandardLibraryName", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] }, { @@ -392,7 +397,12 @@ "severity": "error", "short_name": "ReuseOfReservedIdentifier", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] }, { @@ -403,7 +413,12 @@ "short_name": "UseOfSingleUnderscoreReservedPrefix", "tags": [ "maintainability", - "readability" + "readability", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] }, { @@ -414,7 +429,12 @@ "short_name": "UseOfDoubleUnderscoreReservedPrefix", "tags": [ "maintainability", - "readability" + "readability", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] }, { @@ -426,7 +446,12 @@ "tags": [ "maintainability", "readability", - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] }, { @@ -438,7 +463,12 @@ "tags": [ "maintainability", "readability", - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] }, { @@ -450,7 +480,12 @@ "tags": [ "maintainability", "readability", - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] }, { @@ -462,7 +497,12 @@ "tags": [ "maintainability", "readability", - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/cpp/Null.json b/rule_packages/cpp/Null.json index a5410840ce..543552660c 100644 --- a/rule_packages/cpp/Null.json +++ b/rule_packages/cpp/Null.json @@ -63,7 +63,12 @@ "severity": "error", "short_name": "DoNotAttemptToCreateAStringFromANullPointer", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], diff --git a/rule_packages/cpp/OperatorInvariants.json b/rule_packages/cpp/OperatorInvariants.json index 8ba76cd0f7..5eaefd68c8 100644 --- a/rule_packages/cpp/OperatorInvariants.json +++ b/rule_packages/cpp/OperatorInvariants.json @@ -177,7 +177,12 @@ "severity": "error", "short_name": "GracefullyHandleSelfCopyAssignment", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], @@ -196,7 +201,12 @@ "severity": "error", "short_name": "CopyOperationsMustNotMutateTheSourceObject", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/low", + "external/cert/priority/p9", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/cpp/OutOfBounds.json b/rule_packages/cpp/OutOfBounds.json index a3cb8fbf91..2a657df95c 100644 --- a/rule_packages/cpp/OutOfBounds.json +++ b/rule_packages/cpp/OutOfBounds.json @@ -42,7 +42,12 @@ "shared_implementation_short_name": "ContainerAccessWithoutRangeCheck", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/high", + "external/cert/priority/p9", + "external/cert/level/l2" ] } ], @@ -62,7 +67,12 @@ "short_name": "GuaranteeGenericCppLibraryFunctionsDoNotOverflow", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" ] } ], @@ -82,7 +92,12 @@ "short_name": "RangeCheckStringElementAccess", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/cpp/Pointers.json b/rule_packages/cpp/Pointers.json index b6a0aaef09..fb1fbe2918 100644 --- a/rule_packages/cpp/Pointers.json +++ b/rule_packages/cpp/Pointers.json @@ -396,7 +396,12 @@ "severity": "warning", "short_name": "DoNotUsePointerArithmeticOnPolymorphicObjects", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/high", + "external/cert/priority/p9", + "external/cert/level/l2" ] } ], @@ -416,7 +421,12 @@ "short_name": "DeletingPointerToIncompleteClass", "shared_implementation_short_name": "DeleteOfPointerToIncompleteClass", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] }, { @@ -427,7 +437,12 @@ "severity": "error", "short_name": "CastOfPointerToIncompleteClass", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -447,7 +462,12 @@ "short_name": "UseOfPointerToMemberToAccessUndefinedMember", "shared_implementation_short_name": "AccessOfUndefinedMemberThroughNullPointer", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] }, { @@ -459,7 +479,12 @@ "short_name": "MemberAccessWithUninitializedStaticPointerToMember", "shared_implementation_short_name": "AccessOfUndefinedMemberThroughUninitializedStaticPointer", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] }, { @@ -471,7 +496,12 @@ "short_name": "UseOfPointerToMemberToAccessNonexistentMember", "shared_implementation_short_name": "AccessOfNonExistingMemberThroughPointerToMember", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/cpp/Representation.json b/rule_packages/cpp/Representation.json index 0284d8098f..813373afb4 100644 --- a/rule_packages/cpp/Representation.json +++ b/rule_packages/cpp/Representation.json @@ -131,7 +131,12 @@ "severity": "error", "short_name": "MemsetUsedToAccessObjectRepresentation", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] }, { @@ -143,7 +148,12 @@ "short_name": "MemcmpUsedToAccessObjectRepresentation", "shared_implementation_short_name": "MemcmpUsedToComparePaddingData", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] }, { @@ -154,7 +164,12 @@ "severity": "error", "short_name": "MemcpyUsedToAccessObjectRepresentation", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/high", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], diff --git a/rule_packages/cpp/Scope.json b/rule_packages/cpp/Scope.json index 6677b8b81a..6fc3aa8487 100644 --- a/rule_packages/cpp/Scope.json +++ b/rule_packages/cpp/Scope.json @@ -254,7 +254,12 @@ "severity": "warning", "short_name": "LocalFunctionDeclaration", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ] }, { @@ -265,7 +270,12 @@ "severity": "warning", "short_name": "LocalConstructorInitializedObjectHidesIdentifier", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p2", + "external/cert/level/l3" ] } ], @@ -284,7 +294,12 @@ "severity": "error", "short_name": "SingularOverloadOfMemoryFunction", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/low", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], @@ -304,7 +319,12 @@ "short_name": "ModificationOfTheStandardNamespaces", "shared_implementation_short_name": "NonStandardEntitiesInStandardNamespaces", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], @@ -323,7 +343,12 @@ "severity": "error", "short_name": "UnnamedNamespaceInHeaderFile", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -343,7 +368,12 @@ "short_name": "OneDefinitionRuleNotObeyed", "shared_implementation_short_name": "OneDefinitionRuleViolation", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/high", + "external/cert/priority/p3", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/cpp/SideEffects1.json b/rule_packages/cpp/SideEffects1.json index adddbc3b36..587a6ceb66 100644 --- a/rule_packages/cpp/SideEffects1.json +++ b/rule_packages/cpp/SideEffects1.json @@ -84,7 +84,12 @@ "severity": "warning", "short_name": "DoNotDependOnTheOrderOfScalarObjectEvaluationForSideEffects", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] }, { @@ -95,7 +100,12 @@ "severity": "warning", "short_name": "DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p8", + "external/cert/level/l2" ] } ], @@ -114,7 +124,12 @@ "severity": "warning", "short_name": "DoNotRelyOnSideEffectsInSizeOfOperand", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] }, { @@ -125,7 +140,12 @@ "severity": "warning", "short_name": "DoNotRelyOnSideEffectsInTypeIdOperand", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] }, { @@ -136,7 +156,12 @@ "severity": "warning", "short_name": "DoNotRelyOnSideEffectsInNoExceptOperand", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] }, { @@ -147,7 +172,12 @@ "severity": "warning", "short_name": "DoNotRelyOnSideEffectsInDeclTypeOperand", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] }, { @@ -158,7 +188,12 @@ "severity": "warning", "short_name": "DoNotRelyOnSideEffectsInDeclValExpression", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/low", + "external/cert/priority/p3", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/cpp/SideEffects2.json b/rule_packages/cpp/SideEffects2.json index 6e5e4812fb..0338b88895 100644 --- a/rule_packages/cpp/SideEffects2.json +++ b/rule_packages/cpp/SideEffects2.json @@ -165,7 +165,12 @@ "shared_implementation_short_name": "PredicateFunctionObjectsShouldNotBeMutable", "short_name": "PredicateFunctionObjectsShouldNotBeMutable", "tags": [ - "correctness" + "correctness", + "external/cert/severity/low", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/high", + "external/cert/priority/p3", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/cpp/SmartPointers2.json b/rule_packages/cpp/SmartPointers2.json index 2f89c4868a..db641b4c7e 100644 --- a/rule_packages/cpp/SmartPointers2.json +++ b/rule_packages/cpp/SmartPointers2.json @@ -16,7 +16,10 @@ "precision": "medium", "severity": "warning", "short_name": "WeakPtrNotUsedToRepresentTemporarySharedOwnership", - "tags": ["correctness", "external/autosar/audit"] + "tags": [ + "correctness", + "external/autosar/audit" + ] } ], "title": "A std::weak_ptr shall be used to represent temporary shared ownership." @@ -36,8 +39,14 @@ "severity": "error", "short_name": "OwnedPointerValueStoredInUnrelatedSmartPointerCert", "shared_implementation_short_name": "OwnedPointerValueStoredInUnrelatedSmartPointer", - - "tags": ["correctness"] + "tags": [ + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" + ] } ], "title": "Do not store an already-owned pointer value in an unrelated smart pointer" diff --git a/rule_packages/cpp/Strings.json b/rule_packages/cpp/Strings.json index 2152684792..acccdc7753 100644 --- a/rule_packages/cpp/Strings.json +++ b/rule_packages/cpp/Strings.json @@ -133,7 +133,13 @@ "severity": "recommendation", "shared_implementation_short_name": "BasicStringMayNotBeNullTerminated", "short_name": "BasicStringMayNotBeNullTerminatedCert", - "tags": [] + "tags": [ + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" + ] }, { "description": "Certain operations may not null terminate CStyle strings which may cause unpredictable behavior.", @@ -143,7 +149,13 @@ "severity": "recommendation", "shared_implementation_short_name": "OperationMayNotNullTerminateCStyleString", "short_name": "OperationMayNotNullTerminateCStyleStringCert", - "tags": [] + "tags": [ + "external/cert/severity/high", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p18", + "external/cert/level/l1" + ] } ], "title": "Guarantee that storage for strings has sufficient space for character data and the null terminator" diff --git a/rule_packages/cpp/TrustBoundaries.json b/rule_packages/cpp/TrustBoundaries.json index 7387fffc1f..0b697cd49c 100644 --- a/rule_packages/cpp/TrustBoundaries.json +++ b/rule_packages/cpp/TrustBoundaries.json @@ -38,7 +38,12 @@ "severity": "error", "short_name": "DoNotThrowAnExceptionAcrossExecutionBoundaries", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p12", + "external/cert/level/l1" ] } ], @@ -57,7 +62,12 @@ "severity": "error", "short_name": "DoNotPassANonstandardObjectAcrossBoundaries", "tags": [ - "correctness" + "correctness", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p12", + "external/cert/level/l1" ] } ], diff --git a/rule_packages/cpp/TypeRanges.json b/rule_packages/cpp/TypeRanges.json index 1b27e0ed91..1e8ef914bf 100644 --- a/rule_packages/cpp/TypeRanges.json +++ b/rule_packages/cpp/TypeRanges.json @@ -184,7 +184,12 @@ "short_name": "DetectErrorsWhenConvertingAStringToANumber", "shared_implementation_short_name": "StringNumberConversionMissingErrorCheck", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], @@ -203,7 +208,12 @@ "severity": "error", "short_name": "DoNotCastToAnOutOfRangeEnumerationValue", "tags": [ - "correctness" + "correctness", + "external/cert/severity/medium", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/medium", + "external/cert/priority/p4", + "external/cert/level/l3" ] } ], diff --git a/rule_packages/cpp/Uninitialized.json b/rule_packages/cpp/Uninitialized.json index 019987eef4..1432e11603 100644 --- a/rule_packages/cpp/Uninitialized.json +++ b/rule_packages/cpp/Uninitialized.json @@ -41,7 +41,12 @@ "short_name": "InformationLeakageAcrossTrustBoundaries", "shared_implementation_short_name": "InformationLeakageAcrossBoundaries", "tags": [ - "security" + "security", + "external/cert/severity/low", + "external/cert/likelihood/unlikely", + "external/cert/remediation-cost/high", + "external/cert/priority/p1", + "external/cert/level/l3" ], "implementation_scope": { "description": "The rule does not detect cases where fields may have uninitialized padding but are initialized via an initializer." @@ -65,7 +70,12 @@ "shared_implementation_short_name": "ReadOfUninitializedMemory", "tags": [ "correctness", - "security" + "security", + "external/cert/severity/high", + "external/cert/likelihood/probable", + "external/cert/remediation-cost/medium", + "external/cert/priority/p12", + "external/cert/level/l1" ] } ], From cb66b8c842930e97a5f1fefc69c42707f9976acf Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 1 May 2025 23:42:11 +0100 Subject: [PATCH 322/370] Update script to check for CERT risk assessment tags --- scripts/verify_rule_package_consistency.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/scripts/verify_rule_package_consistency.py b/scripts/verify_rule_package_consistency.py index 034e367db2..b9eaa5b934 100644 --- a/scripts/verify_rule_package_consistency.py +++ b/scripts/verify_rule_package_consistency.py @@ -109,6 +109,24 @@ print( f' - ERROR: {standard_name} query {query["short_name"]}.ql for Rule {rule_id} in {package_name}.json has a spurious `external/misra/c/2012/...` tag.') failed = True + if standard_name == "CERT-C" or standard_name == "CERT-C++": + expected_properties = [ + "severity", + "likelihood", + "remediation-cost", + "priority", + "level" + ] + for expected_property in expected_properties: + if not any(tag for tag in query["tags"] if tag.startswith(f"external/cert/{expected_property}/")): + print( + f' - ERROR: {standard_name} query {query["short_name"]}.ql for Rule {rule_id} in {package_name}.json is missing a `external/cert/{expected_property}/...` tag.') + failed = True + if not standard_name == "CERT-C" and not standard_name == "CERT-C++": + if any(tag for tag in query["tags"] if tag.startswith("external/cert/")): + print( + f' - ERROR: {standard_name} query {query["short_name"]}.ql for Rule {rule_id} in {package_name}.json has a spurious `external/cert/...` tag.') + failed = True rules_csv_rule_ids = package_rules_from_csv[package_name] json_missing_rules = rules_csv_rule_ids.difference(package_json_rule_ids) From 0b279397def7164aa132fecf6c57701437a47c8e Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 1 May 2025 23:44:27 +0100 Subject: [PATCH 323/370] Add missing header markers to markdown files --- .../rules/DCL39-C/InformationLeakageAcrossTrustBoundariesC.md | 2 +- c/cert/src/rules/INT32-C/SignedIntegerOverflow.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/c/cert/src/rules/DCL39-C/InformationLeakageAcrossTrustBoundariesC.md b/c/cert/src/rules/DCL39-C/InformationLeakageAcrossTrustBoundariesC.md index cdc62493a1..4dd3bcbe3c 100644 --- a/c/cert/src/rules/DCL39-C/InformationLeakageAcrossTrustBoundariesC.md +++ b/c/cert/src/rules/DCL39-C/InformationLeakageAcrossTrustBoundariesC.md @@ -249,7 +249,7 @@ In addition, this solution assumes that there are no integer padding bits in an From this situation, it can be seen that special care must be taken because no solution to the bit-field padding issue will be 100% portable. -Risk Assessment +## Risk Assessment Padding units might contain sensitive data because the C Standard allows any padding to take [unspecified values](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-unspecifiedvalue). A pointer to such a structure could be passed to other functions, causing information leakage. diff --git a/c/cert/src/rules/INT32-C/SignedIntegerOverflow.md b/c/cert/src/rules/INT32-C/SignedIntegerOverflow.md index dbe36775bf..50a9d01dcd 100644 --- a/c/cert/src/rules/INT32-C/SignedIntegerOverflow.md +++ b/c/cert/src/rules/INT32-C/SignedIntegerOverflow.md @@ -398,7 +398,8 @@ void func(signed long s_a) { } ``` -Risk Assessment + +## Risk Assessment Integer overflow can lead to buffer overflows and the execution of arbitrary code by an attacker. From be2985722a7585fdf23f9dc5c4addbae555d2e63 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 1 May 2025 23:45:16 +0100 Subject: [PATCH 324/370] Add risk assessment tags to CERT queries --- .../DoNotFormOutOfBoundsPointersOrArraySubscripts.ql | 5 +++++ .../rules/ARR32-C/VariableLengthArraySizeNotInValidRange.ql | 5 +++++ .../DoNotRelatePointersThatDoNotReferToTheSameArray.ql | 5 +++++ .../DoNotSubtractPointersThatDoNotReferToTheSameArray.ql | 5 +++++ .../DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql | 5 +++++ .../src/rules/ARR38-C/LibraryFunctionArgumentOutOfBounds.ql | 5 +++++ .../ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql | 5 +++++ c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql | 5 +++++ .../CON31-C/DoNotAllowAMutexToGoOutOfScopeWhileLocked.ql | 5 +++++ .../src/rules/CON31-C/DoNotDestroyAMutexWhileItIsLocked.ql | 5 +++++ .../rules/CON32-C/PreventDataRacesWithMultipleThreads.ql | 5 +++++ .../CON33-C/RaceConditionsWhenUsingLibraryFunctions.ql | 5 +++++ .../CON34-C/AppropriateThreadObjectStorageDurations.ql | 6 ++++++ .../CON34-C/ThreadObjectStorageDurationsNotInitialized.ql | 6 ++++++ .../src/rules/CON35-C/DeadlockByLockingInPredefinedOrder.ql | 5 +++++ .../CON36-C/WrapFunctionsThatCanSpuriouslyWakeUpInLoop.ql | 5 +++++ .../rules/CON37-C/DoNotCallSignalInMultithreadedProgram.ql | 5 +++++ .../CON38-C/PreserveSafetyWhenUsingConditionVariables.ql | 5 +++++ .../rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.ql | 5 +++++ c/cert/src/rules/CON40-C/AtomicVariableTwiceInExpression.ql | 5 +++++ .../CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.ql | 5 +++++ .../DCL30-C/AppropriateStorageDurationsFunctionReturn.ql | 5 +++++ .../DCL30-C/AppropriateStorageDurationsStackAdressEscape.ql | 5 +++++ .../src/rules/DCL31-C/DeclareIdentifiersBeforeUsingThem.ql | 5 +++++ .../DCL37-C/DoNotDeclareOrDefineAReservedIdentifier.ql | 5 +++++ c/cert/src/rules/DCL38-C/DeclaringAFlexibleArrayMember.ql | 5 +++++ .../DCL39-C/InformationLeakageAcrossTrustBoundariesC.ql | 5 +++++ .../DCL40-C/ExcessLengthNamesIdentifiersNotDistinct.ql | 5 +++++ .../src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql | 5 +++++ c/cert/src/rules/DCL40-C/IncompatibleObjectDeclarations.ql | 5 +++++ c/cert/src/rules/DCL41-C/VariablesInsideSwitchStatement.ql | 5 +++++ .../ENV30-C/DoNotModifyTheReturnValueOfCertainFunctions.ql | 5 +++++ .../ENV31-C/EnvPointerIsInvalidAfterCertainOperations.ql | 5 +++++ c/cert/src/rules/ENV32-C/ExitHandlersMustReturnNormally.ql | 5 +++++ c/cert/src/rules/ENV33-C/DoNotCallSystem.ql | 5 +++++ .../ENV34-C/DoNotStorePointersReturnedByEnvFunctions.ql | 5 +++++ .../DoNotStorePointersReturnedByEnvironmentFunWarn.ql | 5 +++++ c/cert/src/rules/ERR30-C/ErrnoNotSetToZero.ql | 5 +++++ c/cert/src/rules/ERR30-C/ErrnoReadBeforeReturn.ql | 5 +++++ c/cert/src/rules/ERR30-C/FunctionCallBeforeErrnoCheck.ql | 5 +++++ c/cert/src/rules/ERR30-C/SetlocaleMightSetErrno.ql | 5 +++++ .../rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.ql | 5 +++++ .../rules/ERR33-C/DetectAndHandleStandardLibraryErrors.ql | 5 +++++ .../DependenceOnOrderOfFunctionArgumentsForSideEffects.ql | 5 +++++ .../DependenceOnOrderOfScalarEvaluationForSideEffects.ql | 5 +++++ .../DoNotAccessVolatileObjectWithNonVolatileReference.ql | 5 +++++ c/cert/src/rules/EXP33-C/DoNotReadUninitializedMemory.ql | 5 +++++ c/cert/src/rules/EXP34-C/DoNotDereferenceNullPointers.ql | 5 +++++ .../EXP35-C/DoNotModifyObjectsWithTemporaryLifetime.ql | 5 +++++ .../DoNotCastPointerToMoreStrictlyAlignedPointerType.ql | 5 +++++ .../rules/EXP37-C/CallPOSIXOpenWithCorrectArgumentCount.ql | 5 +++++ .../EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.ql | 5 +++++ .../EXP37-C/DoNotCallFunctionsWithIncompatibleArguments.ql | 5 +++++ .../DoNotAccessVariableViaPointerOfIncompatibleType.ql | 6 ++++++ c/cert/src/rules/EXP40-C/DoNotModifyConstantObjects.ql | 5 +++++ c/cert/src/rules/EXP42-C/DoNotComparePaddingData.ql | 5 +++++ .../DoNotPassAliasedPointerToRestrictQualifiedParam.ql | 5 +++++ .../EXP43-C/RestrictPointerReferencesOverlappingObject.ql | 5 +++++ .../src/rules/EXP44-C/UnevaluatedOperandWithSideEffect.ql | 5 +++++ .../src/rules/EXP45-C/AssignmentsInSelectionStatements.ql | 6 ++++++ .../DoNotUseABitwiseOperatorWithABooleanLikeOperand.ql | 5 +++++ .../src/rules/FIO30-C/ExcludeUserInputFromFormatStrings.ql | 5 +++++ .../rules/FIO32-C/DoNotPerformFileOperationsOnDevices.ql | 5 +++++ .../DistinguishBetweenCharReadFromAFileAndEofOrWeof.ql | 5 +++++ c/cert/src/rules/FIO34-C/EndOfFileCheckPortability.ql | 5 +++++ .../SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql | 5 +++++ c/cert/src/rules/FIO38-C/DoNotCopyAFileObject.ql | 5 +++++ .../DoNotAlternatelyIOFromAStreamWithoutPositioning.ql | 5 +++++ .../src/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.ql | 5 +++++ .../rules/FIO41-C/DoNotCallGetcAndPutcWithSideEffects.ql | 5 +++++ .../rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.ql | 5 +++++ .../OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql | 5 +++++ .../FIO45-C/ToctouRaceConditionsWhileAccessingFiles.ql | 5 +++++ .../rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile.ql | 5 +++++ c/cert/src/rules/FIO47-C/UseValidSpecifiers.ql | 5 +++++ c/cert/src/rules/FIO47-C/WrongNumberOfFormatArguments.ql | 5 +++++ c/cert/src/rules/FIO47-C/WrongTypeFormatArguments.ql | 5 +++++ c/cert/src/rules/FLP30-C/FloatingPointLoopCounters.ql | 5 +++++ c/cert/src/rules/FLP32-C/UncheckedRangeDomainPoleErrors.ql | 5 +++++ .../src/rules/FLP34-C/UncheckedFloatingPointConversion.ql | 5 +++++ c/cert/src/rules/FLP36-C/IntToFloatPreservePrecision.ql | 5 +++++ c/cert/src/rules/FLP37-C/MemcmpUsedToCompareFloats.ql | 5 +++++ .../rules/INT30-C/UnsignedIntegerOperationsWrapAround.ql | 5 +++++ c/cert/src/rules/INT31-C/IntegerConversionCausesDataLoss.ql | 5 +++++ c/cert/src/rules/INT32-C/SignedIntegerOverflow.ql | 5 +++++ c/cert/src/rules/INT33-C/DivOrRemByZero.ql | 5 +++++ .../ExprShiftedbyNegativeOrGreaterPrecisionOperand.ql | 5 +++++ c/cert/src/rules/INT35-C/UseCorrectIntegerPrecisions.ql | 5 +++++ .../ConvertingAPointerToIntegerOrIntegerToPointer.ql | 5 +++++ c/cert/src/rules/MEM30-C/DoNotAccessFreedMemory.ql | 5 +++++ .../src/rules/MEM31-C/FreeMemoryWhenNoLongerNeededCert.ql | 5 +++++ .../AllocStructsWithAFlexibleArrayMemberDynamically.ql | 5 +++++ .../CopyStructsWithAFlexibleArrayMemberDynamically.ql | 5 +++++ .../rules/MEM34-C/OnlyFreeMemoryAllocatedDynamicallyCert.ql | 5 +++++ .../rules/MEM35-C/InsufficientMemoryAllocatedForObject.ql | 5 +++++ .../MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.ql | 6 ++++++ .../MSC30-C/RandUsedForGeneratingPseudorandomNumbers.ql | 5 +++++ .../MSC32-C/ProperlySeedPseudorandomNumberGenerators.ql | 5 +++++ .../MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.ql | 5 +++++ .../MSC37-C/ControlFlowReachesTheEndOfANonVoidFunction.ql | 5 +++++ .../MSC38-C/DoNotTreatAPredefinedIdentifierAsObject.ql | 5 +++++ .../DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql | 5 +++++ .../rules/MSC40-C/DoNotViolateInLineLinkageConstraints.ql | 5 +++++ .../rules/PRE31-C/SideEffectsInArgumentsToUnsafeMacros.ql | 5 +++++ .../rules/PRE32-C/MacroOrFunctionArgsContainHashToken.ql | 5 +++++ .../CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql | 5 +++++ .../SIG31-C/DoNotAccessSharedObjectsInSignalHandlers.ql | 5 +++++ .../DoNotCallSignalFromInterruptibleSignalHandlers.ql | 5 +++++ .../DoNotReturnFromAComputationalExceptionHandler.ql | 5 +++++ .../src/rules/STR30-C/DoNotAttemptToModifyStringLiterals.ql | 5 +++++ .../StringsHasSufficientSpaceForTheNullTerminator.ql | 5 +++++ .../NonNullTerminatedToFunctionThatExpectsAString.ql | 5 +++++ .../rules/STR34-C/CastCharBeforeConvertingToLargerSizes.ql | 5 +++++ .../ToCharacterHandlingFunctionsRepresentableAsUChar.ql | 5 +++++ .../src/rules/STR38-C/DoNotConfuseNarrowAndWideFunctions.ql | 5 +++++ .../CON50-CPP/DoNotAllowAMutexToGoOutOfScopeWhileLocked.ql | 5 +++++ .../rules/CON50-CPP/DoNotDestroyAMutexWhileItIsLocked.ql | 5 +++++ ...reActivelyHeldLocksAreReleasedOnExceptionalConditions.ql | 5 +++++ .../CON52-CPP/PreventBitFieldAccessFromMultipleThreads.ql | 5 +++++ .../rules/CON53-CPP/DeadlockByLockingInPredefinedOrder.ql | 5 +++++ .../CON54-CPP/WrapFunctionsThatCanSpuriouslyWakeUpInLoop.ql | 5 +++++ .../CON55-CPP/PreserveSafetyWhenUsingConditionVariables.ql | 5 +++++ .../DoNotSpeculativelyLockALockedNonRecursiveMutex.ql | 5 +++++ .../rules/CON56-CPP/LockedALockedNonRecursiveMutexAudit.ql | 5 +++++ .../rules/CTR50-CPP/ContainerAccessWithoutRangeCheckCert.ql | 5 +++++ .../src/rules/CTR51-CPP/UsesValidContainerElementAccess.ql | 5 +++++ .../GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql | 5 +++++ cpp/cert/src/rules/CTR53-CPP/UseValidIteratorRanges.ql | 5 +++++ .../DoNotSubtractIteratorsForDifferentContainers.ql | 5 +++++ .../CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.ql | 5 +++++ .../DoNotUsePointerArithmeticOnPolymorphicObjects.ql | 5 +++++ .../src/rules/CTR57-CPP/ProvideAValidOrderingPredicate.ql | 5 +++++ .../CTR58-CPP/PredicateFunctionObjectsShouldNotBeMutable.ql | 5 +++++ .../rules/DCL50-CPP/DoNotDefineACStyleVariadicFunction.ql | 5 +++++ .../src/rules/DCL51-CPP/EnumeratorReusesReservedName.ql | 5 +++++ cpp/cert/src/rules/DCL51-CPP/FunctionReusesReservedName.ql | 5 +++++ cpp/cert/src/rules/DCL51-CPP/ObjectReusesReservedName.ql | 5 +++++ .../src/rules/DCL51-CPP/RedefiningOfStandardLibraryName.ql | 5 +++++ cpp/cert/src/rules/DCL51-CPP/ReuseOfReservedIdentifier.ql | 5 +++++ .../rules/DCL51-CPP/UseOfDoubleUnderscoreReservedPrefix.ql | 5 +++++ .../rules/DCL51-CPP/UseOfReservedLiteralSuffixIdentifier.ql | 5 +++++ .../rules/DCL51-CPP/UseOfSingleUnderscoreReservedPrefix.ql | 5 +++++ .../LocalConstructorInitializedObjectHidesIdentifier.ql | 5 +++++ cpp/cert/src/rules/DCL53-CPP/LocalFunctionDeclaration.ql | 5 +++++ .../src/rules/DCL54-CPP/SingularOverloadOfMemoryFunction.ql | 5 +++++ .../DCL55-CPP/InformationLeakageAcrossTrustBoundaries.ql | 5 +++++ .../src/rules/DCL56-CPP/CyclesDuringStaticObjectInit.ql | 5 +++++ ...xceptionsEscapeFromDestructorsOrDeallocationFunctions.ql | 5 +++++ .../rules/DCL58-CPP/ModificationOfTheStandardNamespaces.ql | 5 +++++ .../src/rules/DCL59-CPP/UnnamedNamespaceInHeaderFile.ql | 5 +++++ cpp/cert/src/rules/DCL60-CPP/OneDefinitionRuleNotObeyed.ql | 5 +++++ .../ERR50-CPP/ConditionVariablePostConditionFailedCert.ql | 5 +++++ .../src/rules/ERR50-CPP/ExitHandlerThrowsExceptionCert.ql | 5 +++++ .../src/rules/ERR50-CPP/ExplicitAbruptTerminationCert.ql | 5 +++++ .../rules/ERR50-CPP/JoinableThreadCopiedOrDestroyedCert.ql | 5 +++++ .../src/rules/ERR50-CPP/RethrowNestedWithoutCaptureCert.ql | 5 +++++ cpp/cert/src/rules/ERR51-CPP/HandleAllExceptions.ql | 5 +++++ cpp/cert/src/rules/ERR52-CPP/DoNotUseSetjmpOrLongjmp.ql | 5 +++++ ...royedValueReferencedInConstructorDestructorCatchBlock.ql | 5 +++++ cpp/cert/src/rules/ERR54-CPP/CatchBlockShadowingCert.ql | 5 +++++ .../src/rules/ERR55-CPP/HonorExceptionSpecifications.ql | 5 +++++ cpp/cert/src/rules/ERR56-CPP/GuaranteeExceptionSafety.ql | 5 +++++ .../ERR57-CPP/DoNotLeakResourcesWhenHandlingExceptions.ql | 5 +++++ .../HandleAllExceptionsThrownBeforeMainBeginsExecuting.ql | 5 +++++ .../DoNotThrowAnExceptionAcrossExecutionBoundaries.ql | 5 +++++ .../ExceptionObjectsMustBeNothrowCopyConstructible.ql | 5 +++++ .../src/rules/ERR61-CPP/CatchExceptionsByLvalueReference.ql | 5 +++++ .../ERR62-CPP/DetectErrorsWhenConvertingAStringToANumber.ql | 5 +++++ ...ationForSideEffectsInFunctionCallsAsFunctionArguments.ql | 5 +++++ ...ependOnTheOrderOfScalarObjectEvaluationForSideEffects.ql | 5 +++++ .../DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql | 5 +++++ .../EXP52-CPP/DoNotRelyOnSideEffectsInDeclTypeOperand.ql | 5 +++++ .../EXP52-CPP/DoNotRelyOnSideEffectsInDeclValExpression.ql | 5 +++++ .../EXP52-CPP/DoNotRelyOnSideEffectsInNoExceptOperand.ql | 5 +++++ .../EXP52-CPP/DoNotRelyOnSideEffectsInSizeOfOperand.ql | 5 +++++ .../EXP52-CPP/DoNotRelyOnSideEffectsInTypeIdOperand.ql | 5 +++++ .../src/rules/EXP53-CPP/DoNotReadUninitializedMemory.ql | 5 +++++ .../src/rules/EXP54-CPP/ObjectAccessedAfterLifetimeCert.ql | 5 +++++ .../src/rules/EXP54-CPP/ObjectAccessedBeforeLifetimeCert.ql | 5 +++++ .../EXP55-CPP/RemoveConstOrVolatileQualificationCert.ql | 5 +++++ .../EXP56-CPP/FunctionWithMismatchedLanguageLinkage.ql | 5 +++++ .../src/rules/EXP57-CPP/CastOfPointerToIncompleteClass.ql | 5 +++++ .../src/rules/EXP57-CPP/DeletingPointerToIncompleteClass.ql | 5 +++++ .../src/rules/EXP58-CPP/PassNonTrivialObjectToVaStart.ql | 5 +++++ .../rules/EXP58-CPP/PassPromotablePrimitiveTypeToVaStart.ql | 5 +++++ cpp/cert/src/rules/EXP58-CPP/PassReferenceTypeToVaStart.ql | 5 +++++ .../src/rules/EXP59-CPP/OffsetUsedOnInvalidTypeOrMember.ql | 5 +++++ .../DoNotPassANonstandardObjectAcrossBoundaries.ql | 5 +++++ .../EXP61-CPP/EscapingLambdaObjectWithCaptureByReference.ql | 5 +++++ .../ReturningLambdaObjectWithCaptureByReference.ql | 5 +++++ .../EXP62-CPP/MemcmpUsedToAccessObjectRepresentation.ql | 5 +++++ .../EXP62-CPP/MemcpyUsedToAccessObjectRepresentation.ql | 5 +++++ .../EXP62-CPP/MemsetUsedToAccessObjectRepresentation.ql | 5 +++++ .../EXP63-CPP/DoNotRelyOnTheValueOfAMovedFromObject.ql | 5 +++++ .../FIO50-CPP/InterleavedInputOutputWithoutPosition.ql | 5 +++++ .../rules/FIO51-CPP/CloseFilesWhenTheyAreNoLongerNeeded.ql | 5 +++++ .../INT50-CPP/DoNotCastToAnOutOfRangeEnumerationValue.ql | 5 +++++ cpp/cert/src/rules/MEM50-CPP/UseAfterFree.ql | 5 +++++ .../ProperlyDeallocateDynamicallyAllocatedResources.ql | 5 +++++ .../MEM52-CPP/DetectAndHandleMemoryAllocationErrors.ql | 5 +++++ .../MissingConstructorCallForManuallyManagedObject.ql | 5 +++++ .../MissingDestructorCallForManuallyManagedObject.ql | 5 +++++ .../rules/MEM54-CPP/PlacementNewInsufficientStorageCert.ql | 5 +++++ .../rules/MEM54-CPP/PlacementNewNotProperlyAlignedCert.ql | 5 +++++ .../src/rules/MEM55-CPP/OperatorDeleteMissingPartnerCert.ql | 5 +++++ .../rules/MEM55-CPP/ThrowingNoThrowOperatorNewDeleteCert.ql | 5 +++++ .../rules/MEM55-CPP/ThrowingOperatorNewReturnsNullCert.ql | 5 +++++ .../ThrowingOperatorNewThrowsInvalidExceptionCert.ql | 5 +++++ .../OwnedPointerValueStoredInUnrelatedSmartPointerCert.ql | 5 +++++ .../MEM57-CPP/UsingDefaultOperatorNewForOverAlignedTypes.ql | 5 +++++ .../DoNotUseRandForGeneratingPseudorandomNumbers.ql | 5 +++++ .../src/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.ql | 5 +++++ .../src/rules/MSC52-CPP/NonVoidFunctionDoesNotReturnCert.ql | 5 +++++ .../MSC53-CPP/FunctionNoReturnAttributeConditionCert.ql | 5 +++++ .../rules/MSC54-CPP/SignalHandlerMustBeAPlainOldFunction.ql | 5 +++++ ...otInvokeVirtualFunctionsFromConstructorsOrDestructors.ql | 5 +++++ cpp/cert/src/rules/OOP51-CPP/DoNotSliceDerivedObjects.ql | 5 +++++ ...oNotDeleteAPolymorphicObjectWithoutAVirtualDestructor.ql | 5 +++++ .../src/rules/OOP53-CPP/UseCanonicalOrderForMemberInit.ql | 5 +++++ .../rules/OOP54-CPP/GracefullyHandleSelfCopyAssignment.ql | 5 +++++ .../MemberAccessWithUninitializedStaticPointerToMember.ql | 5 +++++ .../UseOfPointerToMemberToAccessNonexistentMember.ql | 5 +++++ .../UseOfPointerToMemberToAccessUndefinedMember.ql | 5 +++++ .../OOP56-CPP/HonorNewReplacementHandlerRequirements.ql | 5 +++++ .../HonorTerminationReplacementHandlerRequirements.ql | 5 +++++ ...ionsAndOverloadedOperatorsToCStandardLibraryFunctions.ql | 5 +++++ .../OOP58-CPP/CopyOperationsMustNotMutateTheSourceObject.ql | 5 +++++ .../STR50-CPP/BasicStringMayNotBeNullTerminatedCert.ql | 5 +++++ .../OperationMayNotNullTerminateCStyleStringCert.ql | 5 +++++ .../DoNotAttemptToCreateAStringFromANullPointer.ql | 5 +++++ .../STR52-CPP/UseValidReferencesForElementsOfString.ql | 5 +++++ .../src/rules/STR53-CPP/RangeCheckStringElementAccess.ql | 5 +++++ 232 files changed, 1165 insertions(+) diff --git a/c/cert/src/rules/ARR30-C/DoNotFormOutOfBoundsPointersOrArraySubscripts.ql b/c/cert/src/rules/ARR30-C/DoNotFormOutOfBoundsPointersOrArraySubscripts.ql index cc4c99c002..fed579bf34 100644 --- a/c/cert/src/rules/ARR30-C/DoNotFormOutOfBoundsPointersOrArraySubscripts.ql +++ b/c/cert/src/rules/ARR30-C/DoNotFormOutOfBoundsPointersOrArraySubscripts.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/arr30-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/high + * external/cert/priority/p9 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.ql b/c/cert/src/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.ql index 40a800aa69..85fc7b9022 100644 --- a/c/cert/src/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.ql +++ b/c/cert/src/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/arr32-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ARR36-C/DoNotRelatePointersThatDoNotReferToTheSameArray.ql b/c/cert/src/rules/ARR36-C/DoNotRelatePointersThatDoNotReferToTheSameArray.ql index 93244bd483..e42437042f 100644 --- a/c/cert/src/rules/ARR36-C/DoNotRelatePointersThatDoNotReferToTheSameArray.ql +++ b/c/cert/src/rules/ARR36-C/DoNotRelatePointersThatDoNotReferToTheSameArray.ql @@ -8,6 +8,11 @@ * @problem.severity warning * @tags external/cert/id/arr36-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ARR36-C/DoNotSubtractPointersThatDoNotReferToTheSameArray.ql b/c/cert/src/rules/ARR36-C/DoNotSubtractPointersThatDoNotReferToTheSameArray.ql index b3ed62d5d7..a9e53e68b7 100644 --- a/c/cert/src/rules/ARR36-C/DoNotSubtractPointersThatDoNotReferToTheSameArray.ql +++ b/c/cert/src/rules/ARR36-C/DoNotSubtractPointersThatDoNotReferToTheSameArray.ql @@ -8,6 +8,11 @@ * @problem.severity warning * @tags external/cert/id/arr36-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql b/c/cert/src/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql index 0ddf56150c..635d9d5c03 100644 --- a/c/cert/src/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql +++ b/c/cert/src/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/arr37-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ARR38-C/LibraryFunctionArgumentOutOfBounds.ql b/c/cert/src/rules/ARR38-C/LibraryFunctionArgumentOutOfBounds.ql index 5082743193..04e1c8a505 100644 --- a/c/cert/src/rules/ARR38-C/LibraryFunctionArgumentOutOfBounds.ql +++ b/c/cert/src/rules/ARR38-C/LibraryFunctionArgumentOutOfBounds.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/arr38-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql b/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql index 61dd77f6f4..c3ebd6ede6 100644 --- a/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql +++ b/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/arr39-c * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql b/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql index 69b1b333be..1e03c089e8 100644 --- a/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql +++ b/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con30-c * correctness * concurrency + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/CON31-C/DoNotAllowAMutexToGoOutOfScopeWhileLocked.ql b/c/cert/src/rules/CON31-C/DoNotAllowAMutexToGoOutOfScopeWhileLocked.ql index 0bde0b0de7..345623fe0d 100644 --- a/c/cert/src/rules/CON31-C/DoNotAllowAMutexToGoOutOfScopeWhileLocked.ql +++ b/c/cert/src/rules/CON31-C/DoNotAllowAMutexToGoOutOfScopeWhileLocked.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con31-c * correctness * concurrency + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/CON31-C/DoNotDestroyAMutexWhileItIsLocked.ql b/c/cert/src/rules/CON31-C/DoNotDestroyAMutexWhileItIsLocked.ql index b37dccab3a..40c4e936dd 100644 --- a/c/cert/src/rules/CON31-C/DoNotDestroyAMutexWhileItIsLocked.ql +++ b/c/cert/src/rules/CON31-C/DoNotDestroyAMutexWhileItIsLocked.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/con31-c * correctness * concurrency + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/CON32-C/PreventDataRacesWithMultipleThreads.ql b/c/cert/src/rules/CON32-C/PreventDataRacesWithMultipleThreads.ql index d4f3cbbe10..3ea9e1e1fd 100644 --- a/c/cert/src/rules/CON32-C/PreventDataRacesWithMultipleThreads.ql +++ b/c/cert/src/rules/CON32-C/PreventDataRacesWithMultipleThreads.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con32-c * correctness * concurrency + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/CON33-C/RaceConditionsWhenUsingLibraryFunctions.ql b/c/cert/src/rules/CON33-C/RaceConditionsWhenUsingLibraryFunctions.ql index 4efafd8ebf..c9bcaa6bd2 100644 --- a/c/cert/src/rules/CON33-C/RaceConditionsWhenUsingLibraryFunctions.ql +++ b/c/cert/src/rules/CON33-C/RaceConditionsWhenUsingLibraryFunctions.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/con33-c * correctness * concurrency + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql index 3d0cc3f481..eef196a9ec 100644 --- a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql +++ b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql @@ -9,6 +9,12 @@ * @tags external/cert/id/con34-c * correctness * concurrency + * external/cert/recommendation/con34-c + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql b/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql index fc75cb94ff..fa0587bce0 100644 --- a/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql +++ b/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql @@ -10,6 +10,12 @@ * external/cert/audit * correctness * concurrency + * external/cert/recommendation/con34-c + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/CON35-C/DeadlockByLockingInPredefinedOrder.ql b/c/cert/src/rules/CON35-C/DeadlockByLockingInPredefinedOrder.ql index 143e0a58be..764b0f263f 100644 --- a/c/cert/src/rules/CON35-C/DeadlockByLockingInPredefinedOrder.ql +++ b/c/cert/src/rules/CON35-C/DeadlockByLockingInPredefinedOrder.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con35-c * correctness * concurrency + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/CON36-C/WrapFunctionsThatCanSpuriouslyWakeUpInLoop.ql b/c/cert/src/rules/CON36-C/WrapFunctionsThatCanSpuriouslyWakeUpInLoop.ql index 430a0e7c19..d0d948d9b2 100644 --- a/c/cert/src/rules/CON36-C/WrapFunctionsThatCanSpuriouslyWakeUpInLoop.ql +++ b/c/cert/src/rules/CON36-C/WrapFunctionsThatCanSpuriouslyWakeUpInLoop.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con36-c * correctness * concurrency + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/CON37-C/DoNotCallSignalInMultithreadedProgram.ql b/c/cert/src/rules/CON37-C/DoNotCallSignalInMultithreadedProgram.ql index 00cf456948..17691f24dd 100644 --- a/c/cert/src/rules/CON37-C/DoNotCallSignalInMultithreadedProgram.ql +++ b/c/cert/src/rules/CON37-C/DoNotCallSignalInMultithreadedProgram.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con37-c * correctness * concurrency + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/low + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/CON38-C/PreserveSafetyWhenUsingConditionVariables.ql b/c/cert/src/rules/CON38-C/PreserveSafetyWhenUsingConditionVariables.ql index 470480ae62..3b2ae558d8 100644 --- a/c/cert/src/rules/CON38-C/PreserveSafetyWhenUsingConditionVariables.ql +++ b/c/cert/src/rules/CON38-C/PreserveSafetyWhenUsingConditionVariables.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con38-c * correctness * concurrency + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.ql b/c/cert/src/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.ql index 0604d2d483..6ef617ca72 100644 --- a/c/cert/src/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.ql +++ b/c/cert/src/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con39-c * correctness * concurrency + * external/cert/severity/low + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/CON40-C/AtomicVariableTwiceInExpression.ql b/c/cert/src/rules/CON40-C/AtomicVariableTwiceInExpression.ql index 8a44013277..0ec195868f 100644 --- a/c/cert/src/rules/CON40-C/AtomicVariableTwiceInExpression.ql +++ b/c/cert/src/rules/CON40-C/AtomicVariableTwiceInExpression.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con40-c * correctness * concurrency + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.ql b/c/cert/src/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.ql index dd8aed6a55..57be1bc488 100644 --- a/c/cert/src/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.ql +++ b/c/cert/src/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con41-c * correctness * concurrency + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql b/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql index e4f5341014..2e1064ee9d 100644 --- a/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql +++ b/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/dcl30-c * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsStackAdressEscape.ql b/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsStackAdressEscape.ql index fb9b13b39c..a5749aa8bc 100644 --- a/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsStackAdressEscape.ql +++ b/c/cert/src/rules/DCL30-C/AppropriateStorageDurationsStackAdressEscape.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/dcl30-c * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/DCL31-C/DeclareIdentifiersBeforeUsingThem.ql b/c/cert/src/rules/DCL31-C/DeclareIdentifiersBeforeUsingThem.ql index 369baa4a63..35e6cd057a 100644 --- a/c/cert/src/rules/DCL31-C/DeclareIdentifiersBeforeUsingThem.ql +++ b/c/cert/src/rules/DCL31-C/DeclareIdentifiersBeforeUsingThem.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/dcl31-c * correctness * readability + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/DCL37-C/DoNotDeclareOrDefineAReservedIdentifier.ql b/c/cert/src/rules/DCL37-C/DoNotDeclareOrDefineAReservedIdentifier.ql index 99c5a9708b..04a3030cc1 100644 --- a/c/cert/src/rules/DCL37-C/DoNotDeclareOrDefineAReservedIdentifier.ql +++ b/c/cert/src/rules/DCL37-C/DoNotDeclareOrDefineAReservedIdentifier.ql @@ -9,6 +9,11 @@ * correctness * maintainability * readability + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/DCL38-C/DeclaringAFlexibleArrayMember.ql b/c/cert/src/rules/DCL38-C/DeclaringAFlexibleArrayMember.ql index e9fa3f1017..d6000852c6 100644 --- a/c/cert/src/rules/DCL38-C/DeclaringAFlexibleArrayMember.ql +++ b/c/cert/src/rules/DCL38-C/DeclaringAFlexibleArrayMember.ql @@ -10,6 +10,11 @@ * correctness * maintainability * readability + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/DCL39-C/InformationLeakageAcrossTrustBoundariesC.ql b/c/cert/src/rules/DCL39-C/InformationLeakageAcrossTrustBoundariesC.ql index 1199fbeb9b..dd2c1217cf 100644 --- a/c/cert/src/rules/DCL39-C/InformationLeakageAcrossTrustBoundariesC.ql +++ b/c/cert/src/rules/DCL39-C/InformationLeakageAcrossTrustBoundariesC.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/dcl39-c * security + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/high + * external/cert/priority/p1 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/DCL40-C/ExcessLengthNamesIdentifiersNotDistinct.ql b/c/cert/src/rules/DCL40-C/ExcessLengthNamesIdentifiersNotDistinct.ql index ba2cc5c23f..d002326fae 100644 --- a/c/cert/src/rules/DCL40-C/ExcessLengthNamesIdentifiersNotDistinct.ql +++ b/c/cert/src/rules/DCL40-C/ExcessLengthNamesIdentifiersNotDistinct.ql @@ -9,6 +9,11 @@ * correctness * maintainability * readability + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql b/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql index 8cab442e54..8c25fe3350 100644 --- a/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql +++ b/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql @@ -11,6 +11,11 @@ * correctness * maintainability * readability + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/DCL40-C/IncompatibleObjectDeclarations.ql b/c/cert/src/rules/DCL40-C/IncompatibleObjectDeclarations.ql index 151d33db5c..8e220062d4 100644 --- a/c/cert/src/rules/DCL40-C/IncompatibleObjectDeclarations.ql +++ b/c/cert/src/rules/DCL40-C/IncompatibleObjectDeclarations.ql @@ -10,6 +10,11 @@ * correctness * maintainability * readability + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/DCL41-C/VariablesInsideSwitchStatement.ql b/c/cert/src/rules/DCL41-C/VariablesInsideSwitchStatement.ql index db42f7102c..6f06174b99 100644 --- a/c/cert/src/rules/DCL41-C/VariablesInsideSwitchStatement.ql +++ b/c/cert/src/rules/DCL41-C/VariablesInsideSwitchStatement.ql @@ -10,6 +10,11 @@ * correctness * maintainability * readability + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ENV30-C/DoNotModifyTheReturnValueOfCertainFunctions.ql b/c/cert/src/rules/ENV30-C/DoNotModifyTheReturnValueOfCertainFunctions.ql index 42f13f6244..f69a78ba2c 100644 --- a/c/cert/src/rules/ENV30-C/DoNotModifyTheReturnValueOfCertainFunctions.ql +++ b/c/cert/src/rules/ENV30-C/DoNotModifyTheReturnValueOfCertainFunctions.ql @@ -8,6 +8,11 @@ * @problem.severity warning * @tags external/cert/id/env30-c * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ENV31-C/EnvPointerIsInvalidAfterCertainOperations.ql b/c/cert/src/rules/ENV31-C/EnvPointerIsInvalidAfterCertainOperations.ql index a925b80e74..b4d4a74d57 100644 --- a/c/cert/src/rules/ENV31-C/EnvPointerIsInvalidAfterCertainOperations.ql +++ b/c/cert/src/rules/ENV31-C/EnvPointerIsInvalidAfterCertainOperations.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/env31-c * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ENV32-C/ExitHandlersMustReturnNormally.ql b/c/cert/src/rules/ENV32-C/ExitHandlersMustReturnNormally.ql index 1b360ca0d8..19cf28b3e9 100644 --- a/c/cert/src/rules/ENV32-C/ExitHandlersMustReturnNormally.ql +++ b/c/cert/src/rules/ENV32-C/ExitHandlersMustReturnNormally.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/env32-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p12 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ENV33-C/DoNotCallSystem.ql b/c/cert/src/rules/ENV33-C/DoNotCallSystem.ql index 58a9c8db79..3b21cd7544 100644 --- a/c/cert/src/rules/ENV33-C/DoNotCallSystem.ql +++ b/c/cert/src/rules/ENV33-C/DoNotCallSystem.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/env33-c * security + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p12 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ENV34-C/DoNotStorePointersReturnedByEnvFunctions.ql b/c/cert/src/rules/ENV34-C/DoNotStorePointersReturnedByEnvFunctions.ql index 505f26046a..af54dfa823 100644 --- a/c/cert/src/rules/ENV34-C/DoNotStorePointersReturnedByEnvFunctions.ql +++ b/c/cert/src/rules/ENV34-C/DoNotStorePointersReturnedByEnvFunctions.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/env34-c * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ENV34-C/DoNotStorePointersReturnedByEnvironmentFunWarn.ql b/c/cert/src/rules/ENV34-C/DoNotStorePointersReturnedByEnvironmentFunWarn.ql index b5dd9f4d80..784b7898d6 100644 --- a/c/cert/src/rules/ENV34-C/DoNotStorePointersReturnedByEnvironmentFunWarn.ql +++ b/c/cert/src/rules/ENV34-C/DoNotStorePointersReturnedByEnvironmentFunWarn.ql @@ -9,6 +9,11 @@ * @problem.severity warning * @tags external/cert/id/env34-c * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ERR30-C/ErrnoNotSetToZero.ql b/c/cert/src/rules/ERR30-C/ErrnoNotSetToZero.ql index cc1dd82bbb..06ac9d1198 100644 --- a/c/cert/src/rules/ERR30-C/ErrnoNotSetToZero.ql +++ b/c/cert/src/rules/ERR30-C/ErrnoNotSetToZero.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/err30-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ERR30-C/ErrnoReadBeforeReturn.ql b/c/cert/src/rules/ERR30-C/ErrnoReadBeforeReturn.ql index 527529cc30..13f7e40303 100644 --- a/c/cert/src/rules/ERR30-C/ErrnoReadBeforeReturn.ql +++ b/c/cert/src/rules/ERR30-C/ErrnoReadBeforeReturn.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/err30-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ERR30-C/FunctionCallBeforeErrnoCheck.ql b/c/cert/src/rules/ERR30-C/FunctionCallBeforeErrnoCheck.ql index 17714c646f..8bf583faff 100644 --- a/c/cert/src/rules/ERR30-C/FunctionCallBeforeErrnoCheck.ql +++ b/c/cert/src/rules/ERR30-C/FunctionCallBeforeErrnoCheck.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/err30-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ERR30-C/SetlocaleMightSetErrno.ql b/c/cert/src/rules/ERR30-C/SetlocaleMightSetErrno.ql index 9c94284841..a7ccf8c041 100644 --- a/c/cert/src/rules/ERR30-C/SetlocaleMightSetErrno.ql +++ b/c/cert/src/rules/ERR30-C/SetlocaleMightSetErrno.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/err30-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.ql b/c/cert/src/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.ql index 0e3bf26124..c7dfd58c6b 100644 --- a/c/cert/src/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.ql +++ b/c/cert/src/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/err32-c * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.ql b/c/cert/src/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.ql index 6641fe8a52..01e7b83d13 100644 --- a/c/cert/src/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.ql +++ b/c/cert/src/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/err33-c * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.ql b/c/cert/src/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.ql index a761ec7f48..48b9487728 100644 --- a/c/cert/src/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.ql +++ b/c/cert/src/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.ql @@ -8,6 +8,11 @@ * @problem.severity warning * @tags external/cert/id/exp30-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP30-C/DependenceOnOrderOfScalarEvaluationForSideEffects.ql b/c/cert/src/rules/EXP30-C/DependenceOnOrderOfScalarEvaluationForSideEffects.ql index c478a3d51e..51b505ec63 100644 --- a/c/cert/src/rules/EXP30-C/DependenceOnOrderOfScalarEvaluationForSideEffects.ql +++ b/c/cert/src/rules/EXP30-C/DependenceOnOrderOfScalarEvaluationForSideEffects.ql @@ -8,6 +8,11 @@ * @problem.severity warning * @tags external/cert/id/exp30-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP32-C/DoNotAccessVolatileObjectWithNonVolatileReference.ql b/c/cert/src/rules/EXP32-C/DoNotAccessVolatileObjectWithNonVolatileReference.ql index 47b94c5288..891b93bcda 100644 --- a/c/cert/src/rules/EXP32-C/DoNotAccessVolatileObjectWithNonVolatileReference.ql +++ b/c/cert/src/rules/EXP32-C/DoNotAccessVolatileObjectWithNonVolatileReference.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/exp32-c * correctness + * external/cert/severity/low + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP33-C/DoNotReadUninitializedMemory.ql b/c/cert/src/rules/EXP33-C/DoNotReadUninitializedMemory.ql index ef59be1c10..94deea912e 100644 --- a/c/cert/src/rules/EXP33-C/DoNotReadUninitializedMemory.ql +++ b/c/cert/src/rules/EXP33-C/DoNotReadUninitializedMemory.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/exp33-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p12 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP34-C/DoNotDereferenceNullPointers.ql b/c/cert/src/rules/EXP34-C/DoNotDereferenceNullPointers.ql index 042e55dbfd..51b93c8000 100644 --- a/c/cert/src/rules/EXP34-C/DoNotDereferenceNullPointers.ql +++ b/c/cert/src/rules/EXP34-C/DoNotDereferenceNullPointers.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/exp34-c * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP35-C/DoNotModifyObjectsWithTemporaryLifetime.ql b/c/cert/src/rules/EXP35-C/DoNotModifyObjectsWithTemporaryLifetime.ql index 3689aa4397..3f7d9ae142 100644 --- a/c/cert/src/rules/EXP35-C/DoNotModifyObjectsWithTemporaryLifetime.ql +++ b/c/cert/src/rules/EXP35-C/DoNotModifyObjectsWithTemporaryLifetime.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/exp35-c * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.ql b/c/cert/src/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.ql index f3b3aa364d..0d294e48b1 100644 --- a/c/cert/src/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.ql +++ b/c/cert/src/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/exp36-c * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP37-C/CallPOSIXOpenWithCorrectArgumentCount.ql b/c/cert/src/rules/EXP37-C/CallPOSIXOpenWithCorrectArgumentCount.ql index ad8520e321..a6e633d7f6 100644 --- a/c/cert/src/rules/EXP37-C/CallPOSIXOpenWithCorrectArgumentCount.ql +++ b/c/cert/src/rules/EXP37-C/CallPOSIXOpenWithCorrectArgumentCount.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/exp37-c * correctness * security + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.ql b/c/cert/src/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.ql index 9bbe27aa31..6d223dab72 100644 --- a/c/cert/src/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.ql +++ b/c/cert/src/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/exp37-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP37-C/DoNotCallFunctionsWithIncompatibleArguments.ql b/c/cert/src/rules/EXP37-C/DoNotCallFunctionsWithIncompatibleArguments.ql index e76c62ee2d..4c5ba57504 100644 --- a/c/cert/src/rules/EXP37-C/DoNotCallFunctionsWithIncompatibleArguments.ql +++ b/c/cert/src/rules/EXP37-C/DoNotCallFunctionsWithIncompatibleArguments.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/exp37-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.ql b/c/cert/src/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.ql index fde564665c..c5772340ef 100644 --- a/c/cert/src/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.ql +++ b/c/cert/src/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.ql @@ -8,6 +8,12 @@ * @problem.severity error * @tags external/cert/id/exp39-c * correctness + * external/cert/recommendation/exp39-c + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/high + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP40-C/DoNotModifyConstantObjects.ql b/c/cert/src/rules/EXP40-C/DoNotModifyConstantObjects.ql index 20c9f1bcc8..9d8e4b16d4 100644 --- a/c/cert/src/rules/EXP40-C/DoNotModifyConstantObjects.ql +++ b/c/cert/src/rules/EXP40-C/DoNotModifyConstantObjects.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/exp40-c * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP42-C/DoNotComparePaddingData.ql b/c/cert/src/rules/EXP42-C/DoNotComparePaddingData.ql index 9592ebfd30..4fb80352a3 100644 --- a/c/cert/src/rules/EXP42-C/DoNotComparePaddingData.ql +++ b/c/cert/src/rules/EXP42-C/DoNotComparePaddingData.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/exp42-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.ql b/c/cert/src/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.ql index 08121f8c2b..4aced57136 100644 --- a/c/cert/src/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.ql +++ b/c/cert/src/rules/EXP43-C/DoNotPassAliasedPointerToRestrictQualifiedParam.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/exp43-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.ql b/c/cert/src/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.ql index 1d740ec4f3..31618785d2 100644 --- a/c/cert/src/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.ql +++ b/c/cert/src/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/exp43-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP44-C/UnevaluatedOperandWithSideEffect.ql b/c/cert/src/rules/EXP44-C/UnevaluatedOperandWithSideEffect.ql index 32d30a09ad..02d71b3497 100644 --- a/c/cert/src/rules/EXP44-C/UnevaluatedOperandWithSideEffect.ql +++ b/c/cert/src/rules/EXP44-C/UnevaluatedOperandWithSideEffect.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/exp44-c * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP45-C/AssignmentsInSelectionStatements.ql b/c/cert/src/rules/EXP45-C/AssignmentsInSelectionStatements.ql index f6e29eb28c..5478bb03f7 100644 --- a/c/cert/src/rules/EXP45-C/AssignmentsInSelectionStatements.ql +++ b/c/cert/src/rules/EXP45-C/AssignmentsInSelectionStatements.ql @@ -8,6 +8,12 @@ * @problem.severity error * @tags external/cert/id/exp45-c * correctness + * external/cert/recommendation/exp45-c + * external/cert/severity/low + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/EXP46-C/DoNotUseABitwiseOperatorWithABooleanLikeOperand.ql b/c/cert/src/rules/EXP46-C/DoNotUseABitwiseOperatorWithABooleanLikeOperand.ql index 040a8bb6ee..549e57236a 100644 --- a/c/cert/src/rules/EXP46-C/DoNotUseABitwiseOperatorWithABooleanLikeOperand.ql +++ b/c/cert/src/rules/EXP46-C/DoNotUseABitwiseOperatorWithABooleanLikeOperand.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/exp46-c * maintainability * readability + * external/cert/severity/low + * external/cert/likelihood/likely + * external/cert/remediation-cost/low + * external/cert/priority/p9 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings.ql b/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings.ql index b9df838b06..81ecf56ccf 100644 --- a/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings.ql +++ b/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/fio30-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO32-C/DoNotPerformFileOperationsOnDevices.ql b/c/cert/src/rules/FIO32-C/DoNotPerformFileOperationsOnDevices.ql index 5784e820d9..78817d31e9 100644 --- a/c/cert/src/rules/FIO32-C/DoNotPerformFileOperationsOnDevices.ql +++ b/c/cert/src/rules/FIO32-C/DoNotPerformFileOperationsOnDevices.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/fio32-c * correctness * security + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.ql b/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.ql index a55c2dbf29..01c13e642b 100644 --- a/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.ql +++ b/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/fio34-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p12 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability.ql b/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability.ql index 274514e598..3336a059cd 100644 --- a/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability.ql +++ b/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/fio34-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p12 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql b/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql index 5945da57f4..ad3a2c8192 100644 --- a/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql +++ b/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/fio37-c * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p12 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO38-C/DoNotCopyAFileObject.ql b/c/cert/src/rules/FIO38-C/DoNotCopyAFileObject.ql index e8e897009e..5b5a043395 100644 --- a/c/cert/src/rules/FIO38-C/DoNotCopyAFileObject.ql +++ b/c/cert/src/rules/FIO38-C/DoNotCopyAFileObject.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/fio38-c * correctness * security + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning.ql b/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning.ql index 668a7d982e..09289d1f79 100644 --- a/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning.ql +++ b/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/fio39-c * correctness + * external/cert/severity/low + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.ql b/c/cert/src/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.ql index 69fb92a15c..b54436c835 100644 --- a/c/cert/src/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.ql +++ b/c/cert/src/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/fio40-c * correctness * security + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO41-C/DoNotCallGetcAndPutcWithSideEffects.ql b/c/cert/src/rules/FIO41-C/DoNotCallGetcAndPutcWithSideEffects.ql index 7fc1c11d26..5c7d759606 100644 --- a/c/cert/src/rules/FIO41-C/DoNotCallGetcAndPutcWithSideEffects.ql +++ b/c/cert/src/rules/FIO41-C/DoNotCallGetcAndPutcWithSideEffects.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/fio41-c * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.ql b/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.ql index 3650fad82f..26f8aa239d 100644 --- a/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.ql +++ b/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/fio42-c * correctness * security + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql b/c/cert/src/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql index 7ed5887e42..bc0a417bd0 100644 --- a/c/cert/src/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql +++ b/c/cert/src/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/fio44-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.ql b/c/cert/src/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.ql index b02ce2f58d..85369b502e 100644 --- a/c/cert/src/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.ql +++ b/c/cert/src/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/fio45-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile.ql b/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile.ql index 6bc284c2c7..dc52dca487 100644 --- a/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile.ql +++ b/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/fio46-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO47-C/UseValidSpecifiers.ql b/c/cert/src/rules/FIO47-C/UseValidSpecifiers.ql index 2062cba2c4..8ed99d4541 100644 --- a/c/cert/src/rules/FIO47-C/UseValidSpecifiers.ql +++ b/c/cert/src/rules/FIO47-C/UseValidSpecifiers.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/fio47-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO47-C/WrongNumberOfFormatArguments.ql b/c/cert/src/rules/FIO47-C/WrongNumberOfFormatArguments.ql index a8b9e9fbac..7266f1fc7c 100644 --- a/c/cert/src/rules/FIO47-C/WrongNumberOfFormatArguments.ql +++ b/c/cert/src/rules/FIO47-C/WrongNumberOfFormatArguments.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/fio47-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FIO47-C/WrongTypeFormatArguments.ql b/c/cert/src/rules/FIO47-C/WrongTypeFormatArguments.ql index 66cbe409f6..00853abfbc 100644 --- a/c/cert/src/rules/FIO47-C/WrongTypeFormatArguments.ql +++ b/c/cert/src/rules/FIO47-C/WrongTypeFormatArguments.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/fio47-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FLP30-C/FloatingPointLoopCounters.ql b/c/cert/src/rules/FLP30-C/FloatingPointLoopCounters.ql index a26736707c..a042d80ba5 100644 --- a/c/cert/src/rules/FLP30-C/FloatingPointLoopCounters.ql +++ b/c/cert/src/rules/FLP30-C/FloatingPointLoopCounters.ql @@ -9,6 +9,11 @@ * maintainability * readability * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/low + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FLP32-C/UncheckedRangeDomainPoleErrors.ql b/c/cert/src/rules/FLP32-C/UncheckedRangeDomainPoleErrors.ql index fc054d7289..1e87aa3fae 100644 --- a/c/cert/src/rules/FLP32-C/UncheckedRangeDomainPoleErrors.ql +++ b/c/cert/src/rules/FLP32-C/UncheckedRangeDomainPoleErrors.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/flp32-c * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FLP34-C/UncheckedFloatingPointConversion.ql b/c/cert/src/rules/FLP34-C/UncheckedFloatingPointConversion.ql index 4637985076..eebc16afe3 100644 --- a/c/cert/src/rules/FLP34-C/UncheckedFloatingPointConversion.ql +++ b/c/cert/src/rules/FLP34-C/UncheckedFloatingPointConversion.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/flp34-c * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FLP36-C/IntToFloatPreservePrecision.ql b/c/cert/src/rules/FLP36-C/IntToFloatPreservePrecision.ql index e3b98c61c5..81e5670b11 100644 --- a/c/cert/src/rules/FLP36-C/IntToFloatPreservePrecision.ql +++ b/c/cert/src/rules/FLP36-C/IntToFloatPreservePrecision.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/flp36-c * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/FLP37-C/MemcmpUsedToCompareFloats.ql b/c/cert/src/rules/FLP37-C/MemcmpUsedToCompareFloats.ql index 0e3031262e..8735a804fa 100644 --- a/c/cert/src/rules/FLP37-C/MemcmpUsedToCompareFloats.ql +++ b/c/cert/src/rules/FLP37-C/MemcmpUsedToCompareFloats.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/flp37-c * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/INT30-C/UnsignedIntegerOperationsWrapAround.ql b/c/cert/src/rules/INT30-C/UnsignedIntegerOperationsWrapAround.ql index 1c7ae3e31b..c893584a1e 100644 --- a/c/cert/src/rules/INT30-C/UnsignedIntegerOperationsWrapAround.ql +++ b/c/cert/src/rules/INT30-C/UnsignedIntegerOperationsWrapAround.ql @@ -10,6 +10,11 @@ * @tags external/cert/id/int30-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/high + * external/cert/priority/p9 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/INT31-C/IntegerConversionCausesDataLoss.ql b/c/cert/src/rules/INT31-C/IntegerConversionCausesDataLoss.ql index 51ae704461..203e60a9e3 100644 --- a/c/cert/src/rules/INT31-C/IntegerConversionCausesDataLoss.ql +++ b/c/cert/src/rules/INT31-C/IntegerConversionCausesDataLoss.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/int31-c * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/INT32-C/SignedIntegerOverflow.ql b/c/cert/src/rules/INT32-C/SignedIntegerOverflow.ql index 4c781c4e50..2edee2e5c6 100644 --- a/c/cert/src/rules/INT32-C/SignedIntegerOverflow.ql +++ b/c/cert/src/rules/INT32-C/SignedIntegerOverflow.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/int32-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/high + * external/cert/priority/p9 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/INT33-C/DivOrRemByZero.ql b/c/cert/src/rules/INT33-C/DivOrRemByZero.ql index a5e34f13c4..6090e8842a 100644 --- a/c/cert/src/rules/INT33-C/DivOrRemByZero.ql +++ b/c/cert/src/rules/INT33-C/DivOrRemByZero.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/int33-c * correctness + * external/cert/severity/low + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/INT34-C/ExprShiftedbyNegativeOrGreaterPrecisionOperand.ql b/c/cert/src/rules/INT34-C/ExprShiftedbyNegativeOrGreaterPrecisionOperand.ql index d6445d4937..4260a5e677 100644 --- a/c/cert/src/rules/INT34-C/ExprShiftedbyNegativeOrGreaterPrecisionOperand.ql +++ b/c/cert/src/rules/INT34-C/ExprShiftedbyNegativeOrGreaterPrecisionOperand.ql @@ -7,6 +7,11 @@ * @precision very-high * @problem.severity error * @tags external/cert/id/int34-c + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/INT35-C/UseCorrectIntegerPrecisions.ql b/c/cert/src/rules/INT35-C/UseCorrectIntegerPrecisions.ql index cf510bf999..1bc372506d 100644 --- a/c/cert/src/rules/INT35-C/UseCorrectIntegerPrecisions.ql +++ b/c/cert/src/rules/INT35-C/UseCorrectIntegerPrecisions.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/int35-c * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/INT36-C/ConvertingAPointerToIntegerOrIntegerToPointer.ql b/c/cert/src/rules/INT36-C/ConvertingAPointerToIntegerOrIntegerToPointer.ql index 3052f0aadd..1cbdcc4e12 100644 --- a/c/cert/src/rules/INT36-C/ConvertingAPointerToIntegerOrIntegerToPointer.ql +++ b/c/cert/src/rules/INT36-C/ConvertingAPointerToIntegerOrIntegerToPointer.ql @@ -7,6 +7,11 @@ * @precision very-high * @problem.severity error * @tags external/cert/id/int36-c + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/MEM30-C/DoNotAccessFreedMemory.ql b/c/cert/src/rules/MEM30-C/DoNotAccessFreedMemory.ql index 800ec103ff..59ab0df670 100644 --- a/c/cert/src/rules/MEM30-C/DoNotAccessFreedMemory.ql +++ b/c/cert/src/rules/MEM30-C/DoNotAccessFreedMemory.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/mem30-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/MEM31-C/FreeMemoryWhenNoLongerNeededCert.ql b/c/cert/src/rules/MEM31-C/FreeMemoryWhenNoLongerNeededCert.ql index d4c81748a2..18e9478aee 100644 --- a/c/cert/src/rules/MEM31-C/FreeMemoryWhenNoLongerNeededCert.ql +++ b/c/cert/src/rules/MEM31-C/FreeMemoryWhenNoLongerNeededCert.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/mem31-c * correctness * security + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/MEM33-C/AllocStructsWithAFlexibleArrayMemberDynamically.ql b/c/cert/src/rules/MEM33-C/AllocStructsWithAFlexibleArrayMemberDynamically.ql index f4483bd9fe..2ed5035ff0 100644 --- a/c/cert/src/rules/MEM33-C/AllocStructsWithAFlexibleArrayMemberDynamically.ql +++ b/c/cert/src/rules/MEM33-C/AllocStructsWithAFlexibleArrayMemberDynamically.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/mem33-c * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/MEM33-C/CopyStructsWithAFlexibleArrayMemberDynamically.ql b/c/cert/src/rules/MEM33-C/CopyStructsWithAFlexibleArrayMemberDynamically.ql index b4993e2cae..b4d2a9127b 100644 --- a/c/cert/src/rules/MEM33-C/CopyStructsWithAFlexibleArrayMemberDynamically.ql +++ b/c/cert/src/rules/MEM33-C/CopyStructsWithAFlexibleArrayMemberDynamically.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/mem33-c * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/MEM34-C/OnlyFreeMemoryAllocatedDynamicallyCert.ql b/c/cert/src/rules/MEM34-C/OnlyFreeMemoryAllocatedDynamicallyCert.ql index 95da1cc86a..78081944be 100644 --- a/c/cert/src/rules/MEM34-C/OnlyFreeMemoryAllocatedDynamicallyCert.ql +++ b/c/cert/src/rules/MEM34-C/OnlyFreeMemoryAllocatedDynamicallyCert.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/mem34-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/MEM35-C/InsufficientMemoryAllocatedForObject.ql b/c/cert/src/rules/MEM35-C/InsufficientMemoryAllocatedForObject.ql index 5ff1725269..06fd267560 100644 --- a/c/cert/src/rules/MEM35-C/InsufficientMemoryAllocatedForObject.ql +++ b/c/cert/src/rules/MEM35-C/InsufficientMemoryAllocatedForObject.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/mem35-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.ql b/c/cert/src/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.ql index df0eb3b1e3..5515bfc80d 100644 --- a/c/cert/src/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.ql +++ b/c/cert/src/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.ql @@ -9,6 +9,12 @@ * @tags external/cert/id/mem36-c * correctness * security + * external/cert/recommendation/mem36-c + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/MSC30-C/RandUsedForGeneratingPseudorandomNumbers.ql b/c/cert/src/rules/MSC30-C/RandUsedForGeneratingPseudorandomNumbers.ql index ed553b9814..722e6fff80 100644 --- a/c/cert/src/rules/MSC30-C/RandUsedForGeneratingPseudorandomNumbers.ql +++ b/c/cert/src/rules/MSC30-C/RandUsedForGeneratingPseudorandomNumbers.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/msc30-c * security + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/MSC32-C/ProperlySeedPseudorandomNumberGenerators.ql b/c/cert/src/rules/MSC32-C/ProperlySeedPseudorandomNumberGenerators.ql index 2c3db87ee8..85623d9390 100644 --- a/c/cert/src/rules/MSC32-C/ProperlySeedPseudorandomNumberGenerators.ql +++ b/c/cert/src/rules/MSC32-C/ProperlySeedPseudorandomNumberGenerators.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/msc32-c * security + * external/cert/severity/medium + * external/cert/likelihood/likely + * external/cert/remediation-cost/low + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.ql b/c/cert/src/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.ql index fa4a29cb3d..67fa83e852 100644 --- a/c/cert/src/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.ql +++ b/c/cert/src/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/msc33-c * security * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/low + * external/cert/priority/p27 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/MSC37-C/ControlFlowReachesTheEndOfANonVoidFunction.ql b/c/cert/src/rules/MSC37-C/ControlFlowReachesTheEndOfANonVoidFunction.ql index c56f3e48c1..265fc0af55 100644 --- a/c/cert/src/rules/MSC37-C/ControlFlowReachesTheEndOfANonVoidFunction.ql +++ b/c/cert/src/rules/MSC37-C/ControlFlowReachesTheEndOfANonVoidFunction.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/msc37-c * correctness + * external/cert/severity/high + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p9 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/MSC38-C/DoNotTreatAPredefinedIdentifierAsObject.ql b/c/cert/src/rules/MSC38-C/DoNotTreatAPredefinedIdentifierAsObject.ql index 76e9c4539f..828f86dd95 100644 --- a/c/cert/src/rules/MSC38-C/DoNotTreatAPredefinedIdentifierAsObject.ql +++ b/c/cert/src/rules/MSC38-C/DoNotTreatAPredefinedIdentifierAsObject.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/msc38-c * correctness * readability + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql b/c/cert/src/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql index 1c706a8e3f..56613c1943 100644 --- a/c/cert/src/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql +++ b/c/cert/src/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/msc39-c * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.ql b/c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.ql index 63dec179c6..746cea2e9f 100644 --- a/c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.ql +++ b/c/cert/src/rules/MSC40-C/DoNotViolateInLineLinkageConstraints.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/msc40-c * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/PRE31-C/SideEffectsInArgumentsToUnsafeMacros.ql b/c/cert/src/rules/PRE31-C/SideEffectsInArgumentsToUnsafeMacros.ql index 7974c4d601..322048f6de 100644 --- a/c/cert/src/rules/PRE31-C/SideEffectsInArgumentsToUnsafeMacros.ql +++ b/c/cert/src/rules/PRE31-C/SideEffectsInArgumentsToUnsafeMacros.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/pre31-c * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/PRE32-C/MacroOrFunctionArgsContainHashToken.ql b/c/cert/src/rules/PRE32-C/MacroOrFunctionArgsContainHashToken.ql index 9680bea813..0a777dc25d 100644 --- a/c/cert/src/rules/PRE32-C/MacroOrFunctionArgsContainHashToken.ql +++ b/c/cert/src/rules/PRE32-C/MacroOrFunctionArgsContainHashToken.ql @@ -10,6 +10,11 @@ * @tags external/cert/id/pre32-c * correctness * readability + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql b/c/cert/src/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql index 0da48daa70..4cc0f9e32c 100644 --- a/c/cert/src/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql +++ b/c/cert/src/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/sig30-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/SIG31-C/DoNotAccessSharedObjectsInSignalHandlers.ql b/c/cert/src/rules/SIG31-C/DoNotAccessSharedObjectsInSignalHandlers.ql index 2a7a6a77f2..eaa0a446b5 100644 --- a/c/cert/src/rules/SIG31-C/DoNotAccessSharedObjectsInSignalHandlers.ql +++ b/c/cert/src/rules/SIG31-C/DoNotAccessSharedObjectsInSignalHandlers.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/sig31-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/high + * external/cert/priority/p9 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/SIG34-C/DoNotCallSignalFromInterruptibleSignalHandlers.ql b/c/cert/src/rules/SIG34-C/DoNotCallSignalFromInterruptibleSignalHandlers.ql index d1eb773acb..0586c40c36 100644 --- a/c/cert/src/rules/SIG34-C/DoNotCallSignalFromInterruptibleSignalHandlers.ql +++ b/c/cert/src/rules/SIG34-C/DoNotCallSignalFromInterruptibleSignalHandlers.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/sig34-c * correctness * security + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.ql b/c/cert/src/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.ql index fa3cc3bf14..bd65019f98 100644 --- a/c/cert/src/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.ql +++ b/c/cert/src/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/sig35-c * correctness * security + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/high + * external/cert/priority/p1 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/STR30-C/DoNotAttemptToModifyStringLiterals.ql b/c/cert/src/rules/STR30-C/DoNotAttemptToModifyStringLiterals.ql index 244fe6d8e5..397e1bfc9e 100644 --- a/c/cert/src/rules/STR30-C/DoNotAttemptToModifyStringLiterals.ql +++ b/c/cert/src/rules/STR30-C/DoNotAttemptToModifyStringLiterals.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/str30-c * correctness * security + * external/cert/severity/low + * external/cert/likelihood/likely + * external/cert/remediation-cost/low + * external/cert/priority/p9 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.ql b/c/cert/src/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.ql index 3742207720..437b13f7f9 100644 --- a/c/cert/src/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.ql +++ b/c/cert/src/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.ql @@ -10,6 +10,11 @@ * @tags external/cert/id/str31-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.ql b/c/cert/src/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.ql index 8b9b23cd4c..723c8ee0ea 100644 --- a/c/cert/src/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.ql +++ b/c/cert/src/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/str32-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p12 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.ql b/c/cert/src/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.ql index 394df49d99..d814951b37 100644 --- a/c/cert/src/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.ql +++ b/c/cert/src/rules/STR34-C/CastCharBeforeConvertingToLargerSizes.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/str34-c * correctness * security + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/STR37-C/ToCharacterHandlingFunctionsRepresentableAsUChar.ql b/c/cert/src/rules/STR37-C/ToCharacterHandlingFunctionsRepresentableAsUChar.ql index 8dda9012d2..a29dbd34b9 100644 --- a/c/cert/src/rules/STR37-C/ToCharacterHandlingFunctionsRepresentableAsUChar.ql +++ b/c/cert/src/rules/STR37-C/ToCharacterHandlingFunctionsRepresentableAsUChar.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/str37-c * correctness * security + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/c/cert/src/rules/STR38-C/DoNotConfuseNarrowAndWideFunctions.ql b/c/cert/src/rules/STR38-C/DoNotConfuseNarrowAndWideFunctions.ql index a45f7ec7e1..58b2b1c7dd 100644 --- a/c/cert/src/rules/STR38-C/DoNotConfuseNarrowAndWideFunctions.ql +++ b/c/cert/src/rules/STR38-C/DoNotConfuseNarrowAndWideFunctions.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/str38-c * correctness * security + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/low + * external/cert/priority/p27 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CON50-CPP/DoNotAllowAMutexToGoOutOfScopeWhileLocked.ql b/cpp/cert/src/rules/CON50-CPP/DoNotAllowAMutexToGoOutOfScopeWhileLocked.ql index 88232118bb..53f362e275 100644 --- a/cpp/cert/src/rules/CON50-CPP/DoNotAllowAMutexToGoOutOfScopeWhileLocked.ql +++ b/cpp/cert/src/rules/CON50-CPP/DoNotAllowAMutexToGoOutOfScopeWhileLocked.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con50-cpp * correctness * concurrency + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CON50-CPP/DoNotDestroyAMutexWhileItIsLocked.ql b/cpp/cert/src/rules/CON50-CPP/DoNotDestroyAMutexWhileItIsLocked.ql index 2f2f5a6cdb..c15dfca5fc 100644 --- a/cpp/cert/src/rules/CON50-CPP/DoNotDestroyAMutexWhileItIsLocked.ql +++ b/cpp/cert/src/rules/CON50-CPP/DoNotDestroyAMutexWhileItIsLocked.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/con50-cpp * correctness * concurrency + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CON51-CPP/EnsureActivelyHeldLocksAreReleasedOnExceptionalConditions.ql b/cpp/cert/src/rules/CON51-CPP/EnsureActivelyHeldLocksAreReleasedOnExceptionalConditions.ql index df17ec9a27..ac09d41c42 100644 --- a/cpp/cert/src/rules/CON51-CPP/EnsureActivelyHeldLocksAreReleasedOnExceptionalConditions.ql +++ b/cpp/cert/src/rules/CON51-CPP/EnsureActivelyHeldLocksAreReleasedOnExceptionalConditions.ql @@ -10,6 +10,11 @@ * @tags external/cert/id/con51-cpp * correctness * concurrency + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/low + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CON52-CPP/PreventBitFieldAccessFromMultipleThreads.ql b/cpp/cert/src/rules/CON52-CPP/PreventBitFieldAccessFromMultipleThreads.ql index 49d5309113..9ca1a89525 100644 --- a/cpp/cert/src/rules/CON52-CPP/PreventBitFieldAccessFromMultipleThreads.ql +++ b/cpp/cert/src/rules/CON52-CPP/PreventBitFieldAccessFromMultipleThreads.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con52-cpp * correctness * concurrency + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CON53-CPP/DeadlockByLockingInPredefinedOrder.ql b/cpp/cert/src/rules/CON53-CPP/DeadlockByLockingInPredefinedOrder.ql index bbd075b930..d83b3d520b 100644 --- a/cpp/cert/src/rules/CON53-CPP/DeadlockByLockingInPredefinedOrder.ql +++ b/cpp/cert/src/rules/CON53-CPP/DeadlockByLockingInPredefinedOrder.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con53-cpp * correctness * concurrency + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CON54-CPP/WrapFunctionsThatCanSpuriouslyWakeUpInLoop.ql b/cpp/cert/src/rules/CON54-CPP/WrapFunctionsThatCanSpuriouslyWakeUpInLoop.ql index 5584b7bec2..84255dbfc7 100644 --- a/cpp/cert/src/rules/CON54-CPP/WrapFunctionsThatCanSpuriouslyWakeUpInLoop.ql +++ b/cpp/cert/src/rules/CON54-CPP/WrapFunctionsThatCanSpuriouslyWakeUpInLoop.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con54-cpp * correctness * concurrency + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CON55-CPP/PreserveSafetyWhenUsingConditionVariables.ql b/cpp/cert/src/rules/CON55-CPP/PreserveSafetyWhenUsingConditionVariables.ql index 05d73a4d9f..d4f43c7d09 100644 --- a/cpp/cert/src/rules/CON55-CPP/PreserveSafetyWhenUsingConditionVariables.ql +++ b/cpp/cert/src/rules/CON55-CPP/PreserveSafetyWhenUsingConditionVariables.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con55-cpp * correctness * concurrency + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CON56-CPP/DoNotSpeculativelyLockALockedNonRecursiveMutex.ql b/cpp/cert/src/rules/CON56-CPP/DoNotSpeculativelyLockALockedNonRecursiveMutex.ql index 94d23c8664..67edf2fc22 100644 --- a/cpp/cert/src/rules/CON56-CPP/DoNotSpeculativelyLockALockedNonRecursiveMutex.ql +++ b/cpp/cert/src/rules/CON56-CPP/DoNotSpeculativelyLockALockedNonRecursiveMutex.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con56-cpp * correctness * concurrency + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/high + * external/cert/priority/p1 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CON56-CPP/LockedALockedNonRecursiveMutexAudit.ql b/cpp/cert/src/rules/CON56-CPP/LockedALockedNonRecursiveMutexAudit.ql index 478a37af65..09ec2fa3d5 100644 --- a/cpp/cert/src/rules/CON56-CPP/LockedALockedNonRecursiveMutexAudit.ql +++ b/cpp/cert/src/rules/CON56-CPP/LockedALockedNonRecursiveMutexAudit.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/con56-cpp * correctness * concurrency + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/high + * external/cert/priority/p1 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CTR50-CPP/ContainerAccessWithoutRangeCheckCert.ql b/cpp/cert/src/rules/CTR50-CPP/ContainerAccessWithoutRangeCheckCert.ql index a64e8fca2c..e5565ccbbb 100644 --- a/cpp/cert/src/rules/CTR50-CPP/ContainerAccessWithoutRangeCheckCert.ql +++ b/cpp/cert/src/rules/CTR50-CPP/ContainerAccessWithoutRangeCheckCert.ql @@ -10,6 +10,11 @@ * @tags external/cert/id/ctr50-cpp * correctness * security + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/high + * external/cert/priority/p9 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CTR51-CPP/UsesValidContainerElementAccess.ql b/cpp/cert/src/rules/CTR51-CPP/UsesValidContainerElementAccess.ql index 2163412435..0652f065cb 100644 --- a/cpp/cert/src/rules/CTR51-CPP/UsesValidContainerElementAccess.ql +++ b/cpp/cert/src/rules/CTR51-CPP/UsesValidContainerElementAccess.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/ctr51-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql b/cpp/cert/src/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql index 9f49b43786..b022869136 100644 --- a/cpp/cert/src/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql +++ b/cpp/cert/src/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/ctr52-cpp * correctness * security + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CTR53-CPP/UseValidIteratorRanges.ql b/cpp/cert/src/rules/CTR53-CPP/UseValidIteratorRanges.ql index d0afb7754c..3702cbcd6e 100644 --- a/cpp/cert/src/rules/CTR53-CPP/UseValidIteratorRanges.ql +++ b/cpp/cert/src/rules/CTR53-CPP/UseValidIteratorRanges.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/ctr53-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CTR54-CPP/DoNotSubtractIteratorsForDifferentContainers.ql b/cpp/cert/src/rules/CTR54-CPP/DoNotSubtractIteratorsForDifferentContainers.ql index f47f9db201..2401bcbf54 100644 --- a/cpp/cert/src/rules/CTR54-CPP/DoNotSubtractIteratorsForDifferentContainers.ql +++ b/cpp/cert/src/rules/CTR54-CPP/DoNotSubtractIteratorsForDifferentContainers.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/ctr54-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.ql b/cpp/cert/src/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.ql index ce1fb52667..3f2de63246 100644 --- a/cpp/cert/src/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.ql +++ b/cpp/cert/src/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/ctr55-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.ql b/cpp/cert/src/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.ql index 0f5c50164c..b4ac267225 100644 --- a/cpp/cert/src/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.ql +++ b/cpp/cert/src/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.ql @@ -8,6 +8,11 @@ * @problem.severity warning * @tags external/cert/id/ctr56-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/high + * external/cert/priority/p9 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CTR57-CPP/ProvideAValidOrderingPredicate.ql b/cpp/cert/src/rules/CTR57-CPP/ProvideAValidOrderingPredicate.ql index f28409bfc9..950ecd0c46 100644 --- a/cpp/cert/src/rules/CTR57-CPP/ProvideAValidOrderingPredicate.ql +++ b/cpp/cert/src/rules/CTR57-CPP/ProvideAValidOrderingPredicate.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/ctr57-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/CTR58-CPP/PredicateFunctionObjectsShouldNotBeMutable.ql b/cpp/cert/src/rules/CTR58-CPP/PredicateFunctionObjectsShouldNotBeMutable.ql index be26725105..304b532b79 100644 --- a/cpp/cert/src/rules/CTR58-CPP/PredicateFunctionObjectsShouldNotBeMutable.ql +++ b/cpp/cert/src/rules/CTR58-CPP/PredicateFunctionObjectsShouldNotBeMutable.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/ctr58-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/likely + * external/cert/remediation-cost/high + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL50-CPP/DoNotDefineACStyleVariadicFunction.ql b/cpp/cert/src/rules/DCL50-CPP/DoNotDefineACStyleVariadicFunction.ql index 368f154e22..b24988823c 100644 --- a/cpp/cert/src/rules/DCL50-CPP/DoNotDefineACStyleVariadicFunction.ql +++ b/cpp/cert/src/rules/DCL50-CPP/DoNotDefineACStyleVariadicFunction.ql @@ -9,6 +9,11 @@ * correctness * security * scope/single-translation-unit + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p12 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL51-CPP/EnumeratorReusesReservedName.ql b/cpp/cert/src/rules/DCL51-CPP/EnumeratorReusesReservedName.ql index 074ae6ebfc..3f8ea668dd 100644 --- a/cpp/cert/src/rules/DCL51-CPP/EnumeratorReusesReservedName.ql +++ b/cpp/cert/src/rules/DCL51-CPP/EnumeratorReusesReservedName.ql @@ -10,6 +10,11 @@ * maintainability * readability * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL51-CPP/FunctionReusesReservedName.ql b/cpp/cert/src/rules/DCL51-CPP/FunctionReusesReservedName.ql index 8cae916a9a..74d683a0cb 100644 --- a/cpp/cert/src/rules/DCL51-CPP/FunctionReusesReservedName.ql +++ b/cpp/cert/src/rules/DCL51-CPP/FunctionReusesReservedName.ql @@ -10,6 +10,11 @@ * maintainability * readability * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL51-CPP/ObjectReusesReservedName.ql b/cpp/cert/src/rules/DCL51-CPP/ObjectReusesReservedName.ql index 03e1ef7264..fabf036198 100644 --- a/cpp/cert/src/rules/DCL51-CPP/ObjectReusesReservedName.ql +++ b/cpp/cert/src/rules/DCL51-CPP/ObjectReusesReservedName.ql @@ -10,6 +10,11 @@ * maintainability * readability * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL51-CPP/RedefiningOfStandardLibraryName.ql b/cpp/cert/src/rules/DCL51-CPP/RedefiningOfStandardLibraryName.ql index 974b231c26..3aaf5d37cb 100644 --- a/cpp/cert/src/rules/DCL51-CPP/RedefiningOfStandardLibraryName.ql +++ b/cpp/cert/src/rules/DCL51-CPP/RedefiningOfStandardLibraryName.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/dcl51-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL51-CPP/ReuseOfReservedIdentifier.ql b/cpp/cert/src/rules/DCL51-CPP/ReuseOfReservedIdentifier.ql index b32bdf70ba..583a768d22 100644 --- a/cpp/cert/src/rules/DCL51-CPP/ReuseOfReservedIdentifier.ql +++ b/cpp/cert/src/rules/DCL51-CPP/ReuseOfReservedIdentifier.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/dcl51-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL51-CPP/UseOfDoubleUnderscoreReservedPrefix.ql b/cpp/cert/src/rules/DCL51-CPP/UseOfDoubleUnderscoreReservedPrefix.ql index 472f0444ad..c85a7536e9 100644 --- a/cpp/cert/src/rules/DCL51-CPP/UseOfDoubleUnderscoreReservedPrefix.ql +++ b/cpp/cert/src/rules/DCL51-CPP/UseOfDoubleUnderscoreReservedPrefix.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/dcl51-cpp * maintainability * readability + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL51-CPP/UseOfReservedLiteralSuffixIdentifier.ql b/cpp/cert/src/rules/DCL51-CPP/UseOfReservedLiteralSuffixIdentifier.ql index eb2163f667..81036f6f57 100644 --- a/cpp/cert/src/rules/DCL51-CPP/UseOfReservedLiteralSuffixIdentifier.ql +++ b/cpp/cert/src/rules/DCL51-CPP/UseOfReservedLiteralSuffixIdentifier.ql @@ -10,6 +10,11 @@ * maintainability * readability * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL51-CPP/UseOfSingleUnderscoreReservedPrefix.ql b/cpp/cert/src/rules/DCL51-CPP/UseOfSingleUnderscoreReservedPrefix.ql index e2f7270f9c..ed57351d6a 100644 --- a/cpp/cert/src/rules/DCL51-CPP/UseOfSingleUnderscoreReservedPrefix.ql +++ b/cpp/cert/src/rules/DCL51-CPP/UseOfSingleUnderscoreReservedPrefix.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/dcl51-cpp * maintainability * readability + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL53-CPP/LocalConstructorInitializedObjectHidesIdentifier.ql b/cpp/cert/src/rules/DCL53-CPP/LocalConstructorInitializedObjectHidesIdentifier.ql index f6fe18a3db..f576144c46 100644 --- a/cpp/cert/src/rules/DCL53-CPP/LocalConstructorInitializedObjectHidesIdentifier.ql +++ b/cpp/cert/src/rules/DCL53-CPP/LocalConstructorInitializedObjectHidesIdentifier.ql @@ -9,6 +9,11 @@ * @problem.severity warning * @tags external/cert/id/dcl53-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL53-CPP/LocalFunctionDeclaration.ql b/cpp/cert/src/rules/DCL53-CPP/LocalFunctionDeclaration.ql index 368c0a05e4..45aa70dc31 100644 --- a/cpp/cert/src/rules/DCL53-CPP/LocalFunctionDeclaration.ql +++ b/cpp/cert/src/rules/DCL53-CPP/LocalFunctionDeclaration.ql @@ -8,6 +8,11 @@ * @problem.severity warning * @tags external/cert/id/dcl53-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL54-CPP/SingularOverloadOfMemoryFunction.ql b/cpp/cert/src/rules/DCL54-CPP/SingularOverloadOfMemoryFunction.ql index 7f419397ee..8f168e90c8 100644 --- a/cpp/cert/src/rules/DCL54-CPP/SingularOverloadOfMemoryFunction.ql +++ b/cpp/cert/src/rules/DCL54-CPP/SingularOverloadOfMemoryFunction.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/dcl54-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/low + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL55-CPP/InformationLeakageAcrossTrustBoundaries.ql b/cpp/cert/src/rules/DCL55-CPP/InformationLeakageAcrossTrustBoundaries.ql index cf301dfb5f..85b72afaeb 100644 --- a/cpp/cert/src/rules/DCL55-CPP/InformationLeakageAcrossTrustBoundaries.ql +++ b/cpp/cert/src/rules/DCL55-CPP/InformationLeakageAcrossTrustBoundaries.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/dcl55-cpp * security + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/high + * external/cert/priority/p1 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL56-CPP/CyclesDuringStaticObjectInit.ql b/cpp/cert/src/rules/DCL56-CPP/CyclesDuringStaticObjectInit.ql index 1ad411427f..4eb94f3d1d 100644 --- a/cpp/cert/src/rules/DCL56-CPP/CyclesDuringStaticObjectInit.ql +++ b/cpp/cert/src/rules/DCL56-CPP/CyclesDuringStaticObjectInit.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/dcl56-cpp * correctness * maintainability + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL57-CPP/DoNotLetExceptionsEscapeFromDestructorsOrDeallocationFunctions.ql b/cpp/cert/src/rules/DCL57-CPP/DoNotLetExceptionsEscapeFromDestructorsOrDeallocationFunctions.ql index 951169abe5..6f625fd308 100644 --- a/cpp/cert/src/rules/DCL57-CPP/DoNotLetExceptionsEscapeFromDestructorsOrDeallocationFunctions.ql +++ b/cpp/cert/src/rules/DCL57-CPP/DoNotLetExceptionsEscapeFromDestructorsOrDeallocationFunctions.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/dcl57-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL58-CPP/ModificationOfTheStandardNamespaces.ql b/cpp/cert/src/rules/DCL58-CPP/ModificationOfTheStandardNamespaces.ql index a0e94d083c..81242bc0f4 100644 --- a/cpp/cert/src/rules/DCL58-CPP/ModificationOfTheStandardNamespaces.ql +++ b/cpp/cert/src/rules/DCL58-CPP/ModificationOfTheStandardNamespaces.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/dcl58-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL59-CPP/UnnamedNamespaceInHeaderFile.ql b/cpp/cert/src/rules/DCL59-CPP/UnnamedNamespaceInHeaderFile.ql index 57dae96f09..2b8b364c7d 100644 --- a/cpp/cert/src/rules/DCL59-CPP/UnnamedNamespaceInHeaderFile.ql +++ b/cpp/cert/src/rules/DCL59-CPP/UnnamedNamespaceInHeaderFile.ql @@ -10,6 +10,11 @@ * @problem.severity error * @tags external/cert/id/dcl59-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/DCL60-CPP/OneDefinitionRuleNotObeyed.ql b/cpp/cert/src/rules/DCL60-CPP/OneDefinitionRuleNotObeyed.ql index 7908609cc6..84e63a9569 100644 --- a/cpp/cert/src/rules/DCL60-CPP/OneDefinitionRuleNotObeyed.ql +++ b/cpp/cert/src/rules/DCL60-CPP/OneDefinitionRuleNotObeyed.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/dcl60-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/high + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR50-CPP/ConditionVariablePostConditionFailedCert.ql b/cpp/cert/src/rules/ERR50-CPP/ConditionVariablePostConditionFailedCert.ql index 6c22010ef7..40a884fc5a 100644 --- a/cpp/cert/src/rules/ERR50-CPP/ConditionVariablePostConditionFailedCert.ql +++ b/cpp/cert/src/rules/ERR50-CPP/ConditionVariablePostConditionFailedCert.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/err50-cpp * correctness * external/cert/audit + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR50-CPP/ExitHandlerThrowsExceptionCert.ql b/cpp/cert/src/rules/ERR50-CPP/ExitHandlerThrowsExceptionCert.ql index 9c312672e7..548b7b4b94 100644 --- a/cpp/cert/src/rules/ERR50-CPP/ExitHandlerThrowsExceptionCert.ql +++ b/cpp/cert/src/rules/ERR50-CPP/ExitHandlerThrowsExceptionCert.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/err50-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR50-CPP/ExplicitAbruptTerminationCert.ql b/cpp/cert/src/rules/ERR50-CPP/ExplicitAbruptTerminationCert.ql index ddee05aecf..4fe89c634d 100644 --- a/cpp/cert/src/rules/ERR50-CPP/ExplicitAbruptTerminationCert.ql +++ b/cpp/cert/src/rules/ERR50-CPP/ExplicitAbruptTerminationCert.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/err50-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR50-CPP/JoinableThreadCopiedOrDestroyedCert.ql b/cpp/cert/src/rules/ERR50-CPP/JoinableThreadCopiedOrDestroyedCert.ql index 015a5ffede..2036ff2f46 100644 --- a/cpp/cert/src/rules/ERR50-CPP/JoinableThreadCopiedOrDestroyedCert.ql +++ b/cpp/cert/src/rules/ERR50-CPP/JoinableThreadCopiedOrDestroyedCert.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/err50-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR50-CPP/RethrowNestedWithoutCaptureCert.ql b/cpp/cert/src/rules/ERR50-CPP/RethrowNestedWithoutCaptureCert.ql index 088cfe93b0..05d04de99e 100644 --- a/cpp/cert/src/rules/ERR50-CPP/RethrowNestedWithoutCaptureCert.ql +++ b/cpp/cert/src/rules/ERR50-CPP/RethrowNestedWithoutCaptureCert.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/err50-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR51-CPP/HandleAllExceptions.ql b/cpp/cert/src/rules/ERR51-CPP/HandleAllExceptions.ql index 2811815821..f8447d4af5 100644 --- a/cpp/cert/src/rules/ERR51-CPP/HandleAllExceptions.ql +++ b/cpp/cert/src/rules/ERR51-CPP/HandleAllExceptions.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/err51-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR52-CPP/DoNotUseSetjmpOrLongjmp.ql b/cpp/cert/src/rules/ERR52-CPP/DoNotUseSetjmpOrLongjmp.ql index 45e29d02ff..6c9cb2e436 100644 --- a/cpp/cert/src/rules/ERR52-CPP/DoNotUseSetjmpOrLongjmp.ql +++ b/cpp/cert/src/rules/ERR52-CPP/DoNotUseSetjmpOrLongjmp.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/err52-cpp * correctness * scope/single-translation-unit + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR53-CPP/DestroyedValueReferencedInConstructorDestructorCatchBlock.ql b/cpp/cert/src/rules/ERR53-CPP/DestroyedValueReferencedInConstructorDestructorCatchBlock.ql index c45c3785e6..8587a73c33 100644 --- a/cpp/cert/src/rules/ERR53-CPP/DestroyedValueReferencedInConstructorDestructorCatchBlock.ql +++ b/cpp/cert/src/rules/ERR53-CPP/DestroyedValueReferencedInConstructorDestructorCatchBlock.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/err53-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR54-CPP/CatchBlockShadowingCert.ql b/cpp/cert/src/rules/ERR54-CPP/CatchBlockShadowingCert.ql index 8c4c5b5f06..c3e0aeb2f5 100644 --- a/cpp/cert/src/rules/ERR54-CPP/CatchBlockShadowingCert.ql +++ b/cpp/cert/src/rules/ERR54-CPP/CatchBlockShadowingCert.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/err54-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/likely + * external/cert/remediation-cost/low + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR55-CPP/HonorExceptionSpecifications.ql b/cpp/cert/src/rules/ERR55-CPP/HonorExceptionSpecifications.ql index 7d433e2480..4f35d3cd93 100644 --- a/cpp/cert/src/rules/ERR55-CPP/HonorExceptionSpecifications.ql +++ b/cpp/cert/src/rules/ERR55-CPP/HonorExceptionSpecifications.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/err55-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/likely + * external/cert/remediation-cost/low + * external/cert/priority/p9 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR56-CPP/GuaranteeExceptionSafety.ql b/cpp/cert/src/rules/ERR56-CPP/GuaranteeExceptionSafety.ql index b027d02e3f..5831a7f404 100644 --- a/cpp/cert/src/rules/ERR56-CPP/GuaranteeExceptionSafety.ql +++ b/cpp/cert/src/rules/ERR56-CPP/GuaranteeExceptionSafety.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/err56-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/high + * external/cert/priority/p9 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR57-CPP/DoNotLeakResourcesWhenHandlingExceptions.ql b/cpp/cert/src/rules/ERR57-CPP/DoNotLeakResourcesWhenHandlingExceptions.ql index e283ca8e95..6180bf2f83 100644 --- a/cpp/cert/src/rules/ERR57-CPP/DoNotLeakResourcesWhenHandlingExceptions.ql +++ b/cpp/cert/src/rules/ERR57-CPP/DoNotLeakResourcesWhenHandlingExceptions.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/err57-cpp * correctness * security + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR58-CPP/HandleAllExceptionsThrownBeforeMainBeginsExecuting.ql b/cpp/cert/src/rules/ERR58-CPP/HandleAllExceptionsThrownBeforeMainBeginsExecuting.ql index 843b1f0964..ca6b6ae83f 100644 --- a/cpp/cert/src/rules/ERR58-CPP/HandleAllExceptionsThrownBeforeMainBeginsExecuting.ql +++ b/cpp/cert/src/rules/ERR58-CPP/HandleAllExceptionsThrownBeforeMainBeginsExecuting.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/err58-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/likely + * external/cert/remediation-cost/low + * external/cert/priority/p9 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR59-CPP/DoNotThrowAnExceptionAcrossExecutionBoundaries.ql b/cpp/cert/src/rules/ERR59-CPP/DoNotThrowAnExceptionAcrossExecutionBoundaries.ql index 902d392c5f..e1c7af4030 100644 --- a/cpp/cert/src/rules/ERR59-CPP/DoNotThrowAnExceptionAcrossExecutionBoundaries.ql +++ b/cpp/cert/src/rules/ERR59-CPP/DoNotThrowAnExceptionAcrossExecutionBoundaries.ql @@ -11,6 +11,11 @@ * @problem.severity error * @tags external/cert/id/err59-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p12 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR60-CPP/ExceptionObjectsMustBeNothrowCopyConstructible.ql b/cpp/cert/src/rules/ERR60-CPP/ExceptionObjectsMustBeNothrowCopyConstructible.ql index 37a5fedd14..61a145c7a1 100644 --- a/cpp/cert/src/rules/ERR60-CPP/ExceptionObjectsMustBeNothrowCopyConstructible.ql +++ b/cpp/cert/src/rules/ERR60-CPP/ExceptionObjectsMustBeNothrowCopyConstructible.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/err60-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR61-CPP/CatchExceptionsByLvalueReference.ql b/cpp/cert/src/rules/ERR61-CPP/CatchExceptionsByLvalueReference.ql index 29b879b5ea..8cc9c47854 100644 --- a/cpp/cert/src/rules/ERR61-CPP/CatchExceptionsByLvalueReference.ql +++ b/cpp/cert/src/rules/ERR61-CPP/CatchExceptionsByLvalueReference.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/err61-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/ERR62-CPP/DetectErrorsWhenConvertingAStringToANumber.ql b/cpp/cert/src/rules/ERR62-CPP/DetectErrorsWhenConvertingAStringToANumber.ql index 9c6f8120c5..e5451a0fc4 100644 --- a/cpp/cert/src/rules/ERR62-CPP/DetectErrorsWhenConvertingAStringToANumber.ql +++ b/cpp/cert/src/rules/ERR62-CPP/DetectErrorsWhenConvertingAStringToANumber.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/err62-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql b/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql index 7bfb298d3d..960d04449e 100644 --- a/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql +++ b/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql @@ -8,6 +8,11 @@ * @problem.severity warning * @tags external/cert/id/exp50-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfScalarObjectEvaluationForSideEffects.ql b/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfScalarObjectEvaluationForSideEffects.ql index 1ddb315506..4c268e9c7e 100644 --- a/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfScalarObjectEvaluationForSideEffects.ql +++ b/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfScalarObjectEvaluationForSideEffects.ql @@ -8,6 +8,11 @@ * @problem.severity warning * @tags external/cert/id/exp50-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql b/cpp/cert/src/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql index e900d1b259..d0935cc798 100644 --- a/cpp/cert/src/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql +++ b/cpp/cert/src/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/exp51-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclTypeOperand.ql b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclTypeOperand.ql index 217be3db6a..59745c2cd0 100644 --- a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclTypeOperand.ql +++ b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclTypeOperand.ql @@ -8,6 +8,11 @@ * @problem.severity warning * @tags external/cert/id/exp52-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclValExpression.ql b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclValExpression.ql index 93bb653c11..c9ced6825c 100644 --- a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclValExpression.ql +++ b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclValExpression.ql @@ -8,6 +8,11 @@ * @problem.severity warning * @tags external/cert/id/exp52-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInNoExceptOperand.ql b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInNoExceptOperand.ql index a32aa1eb14..d8ed036a06 100644 --- a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInNoExceptOperand.ql +++ b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInNoExceptOperand.ql @@ -8,6 +8,11 @@ * @problem.severity warning * @tags external/cert/id/exp52-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInSizeOfOperand.ql b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInSizeOfOperand.ql index 4cc602362e..aa0b8ff23a 100644 --- a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInSizeOfOperand.ql +++ b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInSizeOfOperand.ql @@ -8,6 +8,11 @@ * @problem.severity warning * @tags external/cert/id/exp52-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInTypeIdOperand.ql b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInTypeIdOperand.ql index cc43a008d9..dc65dddcd1 100644 --- a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInTypeIdOperand.ql +++ b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInTypeIdOperand.ql @@ -8,6 +8,11 @@ * @problem.severity warning * @tags external/cert/id/exp52-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p3 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP53-CPP/DoNotReadUninitializedMemory.ql b/cpp/cert/src/rules/EXP53-CPP/DoNotReadUninitializedMemory.ql index 47ee746038..9839fae0fd 100644 --- a/cpp/cert/src/rules/EXP53-CPP/DoNotReadUninitializedMemory.ql +++ b/cpp/cert/src/rules/EXP53-CPP/DoNotReadUninitializedMemory.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/exp53-cpp * correctness * security + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p12 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedAfterLifetimeCert.ql b/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedAfterLifetimeCert.ql index 4f72fc725a..534bb83796 100644 --- a/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedAfterLifetimeCert.ql +++ b/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedAfterLifetimeCert.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/exp54-cpp * correctness * security + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedBeforeLifetimeCert.ql b/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedBeforeLifetimeCert.ql index d97c002dbd..ea2349194b 100644 --- a/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedBeforeLifetimeCert.ql +++ b/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedBeforeLifetimeCert.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/exp54-cpp * correctness * security + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP55-CPP/RemoveConstOrVolatileQualificationCert.ql b/cpp/cert/src/rules/EXP55-CPP/RemoveConstOrVolatileQualificationCert.ql index 3c915191d4..68216f2e43 100644 --- a/cpp/cert/src/rules/EXP55-CPP/RemoveConstOrVolatileQualificationCert.ql +++ b/cpp/cert/src/rules/EXP55-CPP/RemoveConstOrVolatileQualificationCert.ql @@ -8,6 +8,11 @@ * @problem.severity warning * @tags external/cert/id/exp55-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP56-CPP/FunctionWithMismatchedLanguageLinkage.ql b/cpp/cert/src/rules/EXP56-CPP/FunctionWithMismatchedLanguageLinkage.ql index 23efb87e0b..d8460c58fa 100644 --- a/cpp/cert/src/rules/EXP56-CPP/FunctionWithMismatchedLanguageLinkage.ql +++ b/cpp/cert/src/rules/EXP56-CPP/FunctionWithMismatchedLanguageLinkage.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/exp56-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP57-CPP/CastOfPointerToIncompleteClass.ql b/cpp/cert/src/rules/EXP57-CPP/CastOfPointerToIncompleteClass.ql index 4358f11b34..2a8345c05d 100644 --- a/cpp/cert/src/rules/EXP57-CPP/CastOfPointerToIncompleteClass.ql +++ b/cpp/cert/src/rules/EXP57-CPP/CastOfPointerToIncompleteClass.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/exp57-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP57-CPP/DeletingPointerToIncompleteClass.ql b/cpp/cert/src/rules/EXP57-CPP/DeletingPointerToIncompleteClass.ql index 8534885c9e..935218f78e 100644 --- a/cpp/cert/src/rules/EXP57-CPP/DeletingPointerToIncompleteClass.ql +++ b/cpp/cert/src/rules/EXP57-CPP/DeletingPointerToIncompleteClass.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/exp57-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP58-CPP/PassNonTrivialObjectToVaStart.ql b/cpp/cert/src/rules/EXP58-CPP/PassNonTrivialObjectToVaStart.ql index 5c7ef31a6f..b537fa34c5 100644 --- a/cpp/cert/src/rules/EXP58-CPP/PassNonTrivialObjectToVaStart.ql +++ b/cpp/cert/src/rules/EXP58-CPP/PassNonTrivialObjectToVaStart.ql @@ -9,6 +9,11 @@ * @problem.severity warning * @tags external/cert/id/exp58-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP58-CPP/PassPromotablePrimitiveTypeToVaStart.ql b/cpp/cert/src/rules/EXP58-CPP/PassPromotablePrimitiveTypeToVaStart.ql index dab95c8303..1d34680261 100644 --- a/cpp/cert/src/rules/EXP58-CPP/PassPromotablePrimitiveTypeToVaStart.ql +++ b/cpp/cert/src/rules/EXP58-CPP/PassPromotablePrimitiveTypeToVaStart.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/exp58-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP58-CPP/PassReferenceTypeToVaStart.ql b/cpp/cert/src/rules/EXP58-CPP/PassReferenceTypeToVaStart.ql index 0b9e0a9f99..ce340d63c8 100644 --- a/cpp/cert/src/rules/EXP58-CPP/PassReferenceTypeToVaStart.ql +++ b/cpp/cert/src/rules/EXP58-CPP/PassReferenceTypeToVaStart.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/exp58-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP59-CPP/OffsetUsedOnInvalidTypeOrMember.ql b/cpp/cert/src/rules/EXP59-CPP/OffsetUsedOnInvalidTypeOrMember.ql index 8cda1c0851..7ece8faef6 100644 --- a/cpp/cert/src/rules/EXP59-CPP/OffsetUsedOnInvalidTypeOrMember.ql +++ b/cpp/cert/src/rules/EXP59-CPP/OffsetUsedOnInvalidTypeOrMember.ql @@ -7,6 +7,11 @@ * @problem.severity recommendation * @tags external/cert/id/exp59-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP60-CPP/DoNotPassANonstandardObjectAcrossBoundaries.ql b/cpp/cert/src/rules/EXP60-CPP/DoNotPassANonstandardObjectAcrossBoundaries.ql index 8442e5eda1..ddd6fa0efc 100644 --- a/cpp/cert/src/rules/EXP60-CPP/DoNotPassANonstandardObjectAcrossBoundaries.ql +++ b/cpp/cert/src/rules/EXP60-CPP/DoNotPassANonstandardObjectAcrossBoundaries.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/exp60-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p12 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP61-CPP/EscapingLambdaObjectWithCaptureByReference.ql b/cpp/cert/src/rules/EXP61-CPP/EscapingLambdaObjectWithCaptureByReference.ql index c57de9b2d1..1268d1c82b 100644 --- a/cpp/cert/src/rules/EXP61-CPP/EscapingLambdaObjectWithCaptureByReference.ql +++ b/cpp/cert/src/rules/EXP61-CPP/EscapingLambdaObjectWithCaptureByReference.ql @@ -10,6 +10,11 @@ * @tags external/cert/id/exp61-cpp * correctness * security + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP61-CPP/ReturningLambdaObjectWithCaptureByReference.ql b/cpp/cert/src/rules/EXP61-CPP/ReturningLambdaObjectWithCaptureByReference.ql index 8487c78039..eb76ba6187 100644 --- a/cpp/cert/src/rules/EXP61-CPP/ReturningLambdaObjectWithCaptureByReference.ql +++ b/cpp/cert/src/rules/EXP61-CPP/ReturningLambdaObjectWithCaptureByReference.ql @@ -10,6 +10,11 @@ * @tags external/cert/id/exp61-cpp * correctness * security + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP62-CPP/MemcmpUsedToAccessObjectRepresentation.ql b/cpp/cert/src/rules/EXP62-CPP/MemcmpUsedToAccessObjectRepresentation.ql index 4b8b67368f..64bfb4673b 100644 --- a/cpp/cert/src/rules/EXP62-CPP/MemcmpUsedToAccessObjectRepresentation.ql +++ b/cpp/cert/src/rules/EXP62-CPP/MemcmpUsedToAccessObjectRepresentation.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/exp62-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP62-CPP/MemcpyUsedToAccessObjectRepresentation.ql b/cpp/cert/src/rules/EXP62-CPP/MemcpyUsedToAccessObjectRepresentation.ql index 87f797bf25..0e8847257c 100644 --- a/cpp/cert/src/rules/EXP62-CPP/MemcpyUsedToAccessObjectRepresentation.ql +++ b/cpp/cert/src/rules/EXP62-CPP/MemcpyUsedToAccessObjectRepresentation.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/exp62-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP62-CPP/MemsetUsedToAccessObjectRepresentation.ql b/cpp/cert/src/rules/EXP62-CPP/MemsetUsedToAccessObjectRepresentation.ql index 302410def1..a4ae635289 100644 --- a/cpp/cert/src/rules/EXP62-CPP/MemsetUsedToAccessObjectRepresentation.ql +++ b/cpp/cert/src/rules/EXP62-CPP/MemsetUsedToAccessObjectRepresentation.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/exp62-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP63-CPP/DoNotRelyOnTheValueOfAMovedFromObject.ql b/cpp/cert/src/rules/EXP63-CPP/DoNotRelyOnTheValueOfAMovedFromObject.ql index 785d4b8b2b..48e534bfbb 100644 --- a/cpp/cert/src/rules/EXP63-CPP/DoNotRelyOnTheValueOfAMovedFromObject.ql +++ b/cpp/cert/src/rules/EXP63-CPP/DoNotRelyOnTheValueOfAMovedFromObject.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/exp63-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/FIO50-CPP/InterleavedInputOutputWithoutPosition.ql b/cpp/cert/src/rules/FIO50-CPP/InterleavedInputOutputWithoutPosition.ql index e30168dc23..0333955f72 100644 --- a/cpp/cert/src/rules/FIO50-CPP/InterleavedInputOutputWithoutPosition.ql +++ b/cpp/cert/src/rules/FIO50-CPP/InterleavedInputOutputWithoutPosition.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/fio50-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/FIO51-CPP/CloseFilesWhenTheyAreNoLongerNeeded.ql b/cpp/cert/src/rules/FIO51-CPP/CloseFilesWhenTheyAreNoLongerNeeded.ql index 383fb9db1f..a444692594 100644 --- a/cpp/cert/src/rules/FIO51-CPP/CloseFilesWhenTheyAreNoLongerNeeded.ql +++ b/cpp/cert/src/rules/FIO51-CPP/CloseFilesWhenTheyAreNoLongerNeeded.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/fio51-cpp * correctness * security + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/INT50-CPP/DoNotCastToAnOutOfRangeEnumerationValue.ql b/cpp/cert/src/rules/INT50-CPP/DoNotCastToAnOutOfRangeEnumerationValue.ql index f90d3a42ef..c7437073e9 100644 --- a/cpp/cert/src/rules/INT50-CPP/DoNotCastToAnOutOfRangeEnumerationValue.ql +++ b/cpp/cert/src/rules/INT50-CPP/DoNotCastToAnOutOfRangeEnumerationValue.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/int50-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MEM50-CPP/UseAfterFree.ql b/cpp/cert/src/rules/MEM50-CPP/UseAfterFree.ql index 59bf3e5bc7..8c31fc104c 100644 --- a/cpp/cert/src/rules/MEM50-CPP/UseAfterFree.ql +++ b/cpp/cert/src/rules/MEM50-CPP/UseAfterFree.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/mem50-cpp * correctness * security + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MEM51-CPP/ProperlyDeallocateDynamicallyAllocatedResources.ql b/cpp/cert/src/rules/MEM51-CPP/ProperlyDeallocateDynamicallyAllocatedResources.ql index 5854b169f2..70fd363c64 100644 --- a/cpp/cert/src/rules/MEM51-CPP/ProperlyDeallocateDynamicallyAllocatedResources.ql +++ b/cpp/cert/src/rules/MEM51-CPP/ProperlyDeallocateDynamicallyAllocatedResources.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/mem51-cpp * correctness * security + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.ql b/cpp/cert/src/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.ql index 083aad1e3c..90685f1c96 100644 --- a/cpp/cert/src/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.ql +++ b/cpp/cert/src/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/mem52-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject.ql b/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject.ql index 5398aa04e1..a56fa18da8 100644 --- a/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject.ql +++ b/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/mem53-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MEM53-CPP/MissingDestructorCallForManuallyManagedObject.ql b/cpp/cert/src/rules/MEM53-CPP/MissingDestructorCallForManuallyManagedObject.ql index 22e2ac336f..fe6fff2d4f 100644 --- a/cpp/cert/src/rules/MEM53-CPP/MissingDestructorCallForManuallyManagedObject.ql +++ b/cpp/cert/src/rules/MEM53-CPP/MissingDestructorCallForManuallyManagedObject.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/mem53-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MEM54-CPP/PlacementNewInsufficientStorageCert.ql b/cpp/cert/src/rules/MEM54-CPP/PlacementNewInsufficientStorageCert.ql index 695d39de69..fca9190552 100644 --- a/cpp/cert/src/rules/MEM54-CPP/PlacementNewInsufficientStorageCert.ql +++ b/cpp/cert/src/rules/MEM54-CPP/PlacementNewInsufficientStorageCert.ql @@ -10,6 +10,11 @@ * @tags external/cert/id/mem54-cpp * security * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MEM54-CPP/PlacementNewNotProperlyAlignedCert.ql b/cpp/cert/src/rules/MEM54-CPP/PlacementNewNotProperlyAlignedCert.ql index 4993de85ed..d623e85a50 100644 --- a/cpp/cert/src/rules/MEM54-CPP/PlacementNewNotProperlyAlignedCert.ql +++ b/cpp/cert/src/rules/MEM54-CPP/PlacementNewNotProperlyAlignedCert.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/mem54-cpp * security * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MEM55-CPP/OperatorDeleteMissingPartnerCert.ql b/cpp/cert/src/rules/MEM55-CPP/OperatorDeleteMissingPartnerCert.ql index d3366f15fc..fd8f4f3a04 100644 --- a/cpp/cert/src/rules/MEM55-CPP/OperatorDeleteMissingPartnerCert.ql +++ b/cpp/cert/src/rules/MEM55-CPP/OperatorDeleteMissingPartnerCert.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/mem55-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MEM55-CPP/ThrowingNoThrowOperatorNewDeleteCert.ql b/cpp/cert/src/rules/MEM55-CPP/ThrowingNoThrowOperatorNewDeleteCert.ql index 564d74c333..2740498eef 100644 --- a/cpp/cert/src/rules/MEM55-CPP/ThrowingNoThrowOperatorNewDeleteCert.ql +++ b/cpp/cert/src/rules/MEM55-CPP/ThrowingNoThrowOperatorNewDeleteCert.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/mem55-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewReturnsNullCert.ql b/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewReturnsNullCert.ql index c07dbff76c..072c69201f 100644 --- a/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewReturnsNullCert.ql +++ b/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewReturnsNullCert.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/mem55-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewThrowsInvalidExceptionCert.ql b/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewThrowsInvalidExceptionCert.ql index 0b02be8b3f..da4b63200b 100644 --- a/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewThrowsInvalidExceptionCert.ql +++ b/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewThrowsInvalidExceptionCert.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/mem55-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MEM56-CPP/OwnedPointerValueStoredInUnrelatedSmartPointerCert.ql b/cpp/cert/src/rules/MEM56-CPP/OwnedPointerValueStoredInUnrelatedSmartPointerCert.ql index 7fa3209151..ba7a39272a 100644 --- a/cpp/cert/src/rules/MEM56-CPP/OwnedPointerValueStoredInUnrelatedSmartPointerCert.ql +++ b/cpp/cert/src/rules/MEM56-CPP/OwnedPointerValueStoredInUnrelatedSmartPointerCert.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/mem56-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MEM57-CPP/UsingDefaultOperatorNewForOverAlignedTypes.ql b/cpp/cert/src/rules/MEM57-CPP/UsingDefaultOperatorNewForOverAlignedTypes.ql index f8a5247ff1..6c3d18c27f 100644 --- a/cpp/cert/src/rules/MEM57-CPP/UsingDefaultOperatorNewForOverAlignedTypes.ql +++ b/cpp/cert/src/rules/MEM57-CPP/UsingDefaultOperatorNewForOverAlignedTypes.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/mem57-cpp * correctness * security + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MSC50-CPP/DoNotUseRandForGeneratingPseudorandomNumbers.ql b/cpp/cert/src/rules/MSC50-CPP/DoNotUseRandForGeneratingPseudorandomNumbers.ql index 8ab68974cb..b67cec99f3 100644 --- a/cpp/cert/src/rules/MSC50-CPP/DoNotUseRandForGeneratingPseudorandomNumbers.ql +++ b/cpp/cert/src/rules/MSC50-CPP/DoNotUseRandForGeneratingPseudorandomNumbers.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/msc50-cpp * security * scope/single-translation-unit + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.ql b/cpp/cert/src/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.ql index 76f8500362..5322fbbde3 100644 --- a/cpp/cert/src/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.ql +++ b/cpp/cert/src/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/msc51-cpp * security * correctness + * external/cert/severity/medium + * external/cert/likelihood/likely + * external/cert/remediation-cost/low + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MSC52-CPP/NonVoidFunctionDoesNotReturnCert.ql b/cpp/cert/src/rules/MSC52-CPP/NonVoidFunctionDoesNotReturnCert.ql index 9634592715..dcf42a78f4 100644 --- a/cpp/cert/src/rules/MSC52-CPP/NonVoidFunctionDoesNotReturnCert.ql +++ b/cpp/cert/src/rules/MSC52-CPP/NonVoidFunctionDoesNotReturnCert.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/msc52-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p8 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MSC53-CPP/FunctionNoReturnAttributeConditionCert.ql b/cpp/cert/src/rules/MSC53-CPP/FunctionNoReturnAttributeConditionCert.ql index 511369e46c..5044b3b421 100644 --- a/cpp/cert/src/rules/MSC53-CPP/FunctionNoReturnAttributeConditionCert.ql +++ b/cpp/cert/src/rules/MSC53-CPP/FunctionNoReturnAttributeConditionCert.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/msc53-cpp * correctness + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/low + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/MSC54-CPP/SignalHandlerMustBeAPlainOldFunction.ql b/cpp/cert/src/rules/MSC54-CPP/SignalHandlerMustBeAPlainOldFunction.ql index a537346630..885d8caa0a 100644 --- a/cpp/cert/src/rules/MSC54-CPP/SignalHandlerMustBeAPlainOldFunction.ql +++ b/cpp/cert/src/rules/MSC54-CPP/SignalHandlerMustBeAPlainOldFunction.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/msc54-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/OOP50-CPP/DoNotInvokeVirtualFunctionsFromConstructorsOrDestructors.ql b/cpp/cert/src/rules/OOP50-CPP/DoNotInvokeVirtualFunctionsFromConstructorsOrDestructors.ql index 5cbcee6be9..1c3df97cfa 100644 --- a/cpp/cert/src/rules/OOP50-CPP/DoNotInvokeVirtualFunctionsFromConstructorsOrDestructors.ql +++ b/cpp/cert/src/rules/OOP50-CPP/DoNotInvokeVirtualFunctionsFromConstructorsOrDestructors.ql @@ -7,6 +7,11 @@ * @precision very-high * @problem.severity error * @tags external/cert/id/oop50-cpp + * external/cert/severity/low + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/OOP51-CPP/DoNotSliceDerivedObjects.ql b/cpp/cert/src/rules/OOP51-CPP/DoNotSliceDerivedObjects.ql index f0af256fb9..4cb654730b 100644 --- a/cpp/cert/src/rules/OOP51-CPP/DoNotSliceDerivedObjects.ql +++ b/cpp/cert/src/rules/OOP51-CPP/DoNotSliceDerivedObjects.ql @@ -7,6 +7,11 @@ * @precision very-high * @problem.severity error * @tags external/cert/id/oop51-cpp + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/OOP52-CPP/DoNotDeleteAPolymorphicObjectWithoutAVirtualDestructor.ql b/cpp/cert/src/rules/OOP52-CPP/DoNotDeleteAPolymorphicObjectWithoutAVirtualDestructor.ql index 13bfdd5c0c..190c4d720d 100644 --- a/cpp/cert/src/rules/OOP52-CPP/DoNotDeleteAPolymorphicObjectWithoutAVirtualDestructor.ql +++ b/cpp/cert/src/rules/OOP52-CPP/DoNotDeleteAPolymorphicObjectWithoutAVirtualDestructor.ql @@ -7,6 +7,11 @@ * @precision very-high * @problem.severity warning * @tags external/cert/id/oop52-cpp + * external/cert/severity/low + * external/cert/likelihood/likely + * external/cert/remediation-cost/low + * external/cert/priority/p9 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/OOP53-CPP/UseCanonicalOrderForMemberInit.ql b/cpp/cert/src/rules/OOP53-CPP/UseCanonicalOrderForMemberInit.ql index 96fd7812d7..b42b54ef6c 100644 --- a/cpp/cert/src/rules/OOP53-CPP/UseCanonicalOrderForMemberInit.ql +++ b/cpp/cert/src/rules/OOP53-CPP/UseCanonicalOrderForMemberInit.ql @@ -12,6 +12,11 @@ * security * maintainability * readability + * external/cert/severity/medium + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p4 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/OOP54-CPP/GracefullyHandleSelfCopyAssignment.ql b/cpp/cert/src/rules/OOP54-CPP/GracefullyHandleSelfCopyAssignment.ql index 85940bf862..844d0f54bb 100644 --- a/cpp/cert/src/rules/OOP54-CPP/GracefullyHandleSelfCopyAssignment.ql +++ b/cpp/cert/src/rules/OOP54-CPP/GracefullyHandleSelfCopyAssignment.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/oop54-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/OOP55-CPP/MemberAccessWithUninitializedStaticPointerToMember.ql b/cpp/cert/src/rules/OOP55-CPP/MemberAccessWithUninitializedStaticPointerToMember.ql index ead970ca71..27c63c2c16 100644 --- a/cpp/cert/src/rules/OOP55-CPP/MemberAccessWithUninitializedStaticPointerToMember.ql +++ b/cpp/cert/src/rules/OOP55-CPP/MemberAccessWithUninitializedStaticPointerToMember.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/oop55-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessNonexistentMember.ql b/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessNonexistentMember.ql index 614d3fbaca..72d640f29b 100644 --- a/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessNonexistentMember.ql +++ b/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessNonexistentMember.ql @@ -9,6 +9,11 @@ * @problem.severity error * @tags external/cert/id/oop55-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessUndefinedMember.ql b/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessUndefinedMember.ql index e6b8f10d9c..202123c11c 100644 --- a/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessUndefinedMember.ql +++ b/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessUndefinedMember.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/oop55-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/OOP56-CPP/HonorNewReplacementHandlerRequirements.ql b/cpp/cert/src/rules/OOP56-CPP/HonorNewReplacementHandlerRequirements.ql index 18b259ef86..981bd1ce5b 100644 --- a/cpp/cert/src/rules/OOP56-CPP/HonorNewReplacementHandlerRequirements.ql +++ b/cpp/cert/src/rules/OOP56-CPP/HonorNewReplacementHandlerRequirements.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/oop56-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/OOP56-CPP/HonorTerminationReplacementHandlerRequirements.ql b/cpp/cert/src/rules/OOP56-CPP/HonorTerminationReplacementHandlerRequirements.ql index ea499791ff..4d59b36b52 100644 --- a/cpp/cert/src/rules/OOP56-CPP/HonorTerminationReplacementHandlerRequirements.ql +++ b/cpp/cert/src/rules/OOP56-CPP/HonorTerminationReplacementHandlerRequirements.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/oop56-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p2 + * external/cert/level/l3 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/OOP57-CPP/PreferSpecialMemberFunctionsAndOverloadedOperatorsToCStandardLibraryFunctions.ql b/cpp/cert/src/rules/OOP57-CPP/PreferSpecialMemberFunctionsAndOverloadedOperatorsToCStandardLibraryFunctions.ql index 19b14730bb..9ac17e84a0 100644 --- a/cpp/cert/src/rules/OOP57-CPP/PreferSpecialMemberFunctionsAndOverloadedOperatorsToCStandardLibraryFunctions.ql +++ b/cpp/cert/src/rules/OOP57-CPP/PreferSpecialMemberFunctionsAndOverloadedOperatorsToCStandardLibraryFunctions.ql @@ -8,6 +8,11 @@ * @tags external/cert/id/oop57-cpp * correctness * scope/single-translation-unit + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/OOP58-CPP/CopyOperationsMustNotMutateTheSourceObject.ql b/cpp/cert/src/rules/OOP58-CPP/CopyOperationsMustNotMutateTheSourceObject.ql index 97cfe0fa3c..9ad0593702 100644 --- a/cpp/cert/src/rules/OOP58-CPP/CopyOperationsMustNotMutateTheSourceObject.ql +++ b/cpp/cert/src/rules/OOP58-CPP/CopyOperationsMustNotMutateTheSourceObject.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/oop58-cpp * correctness + * external/cert/severity/low + * external/cert/likelihood/likely + * external/cert/remediation-cost/low + * external/cert/priority/p9 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/STR50-CPP/BasicStringMayNotBeNullTerminatedCert.ql b/cpp/cert/src/rules/STR50-CPP/BasicStringMayNotBeNullTerminatedCert.ql index 9ff12eca5c..2cd08be70a 100644 --- a/cpp/cert/src/rules/STR50-CPP/BasicStringMayNotBeNullTerminatedCert.ql +++ b/cpp/cert/src/rules/STR50-CPP/BasicStringMayNotBeNullTerminatedCert.ql @@ -7,6 +7,11 @@ * @precision very-high * @problem.severity recommendation * @tags external/cert/id/str50-cpp + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/STR50-CPP/OperationMayNotNullTerminateCStyleStringCert.ql b/cpp/cert/src/rules/STR50-CPP/OperationMayNotNullTerminateCStyleStringCert.ql index d79297a63b..59f56207cd 100644 --- a/cpp/cert/src/rules/STR50-CPP/OperationMayNotNullTerminateCStyleStringCert.ql +++ b/cpp/cert/src/rules/STR50-CPP/OperationMayNotNullTerminateCStyleStringCert.ql @@ -7,6 +7,11 @@ * @precision very-high * @problem.severity recommendation * @tags external/cert/id/str50-cpp + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/STR51-CPP/DoNotAttemptToCreateAStringFromANullPointer.ql b/cpp/cert/src/rules/STR51-CPP/DoNotAttemptToCreateAStringFromANullPointer.ql index e775dc205f..a6337e2fcf 100644 --- a/cpp/cert/src/rules/STR51-CPP/DoNotAttemptToCreateAStringFromANullPointer.ql +++ b/cpp/cert/src/rules/STR51-CPP/DoNotAttemptToCreateAStringFromANullPointer.ql @@ -7,6 +7,11 @@ * @problem.severity error * @tags external/cert/id/str51-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/likely + * external/cert/remediation-cost/medium + * external/cert/priority/p18 + * external/cert/level/l1 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/STR52-CPP/UseValidReferencesForElementsOfString.ql b/cpp/cert/src/rules/STR52-CPP/UseValidReferencesForElementsOfString.ql index 211e490b33..21c29f54ef 100644 --- a/cpp/cert/src/rules/STR52-CPP/UseValidReferencesForElementsOfString.ql +++ b/cpp/cert/src/rules/STR52-CPP/UseValidReferencesForElementsOfString.ql @@ -8,6 +8,11 @@ * @problem.severity error * @tags external/cert/id/str52-cpp * correctness + * external/cert/severity/high + * external/cert/likelihood/probable + * external/cert/remediation-cost/high + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/STR53-CPP/RangeCheckStringElementAccess.ql b/cpp/cert/src/rules/STR53-CPP/RangeCheckStringElementAccess.ql index 3300b77e18..c92f2b2316 100644 --- a/cpp/cert/src/rules/STR53-CPP/RangeCheckStringElementAccess.ql +++ b/cpp/cert/src/rules/STR53-CPP/RangeCheckStringElementAccess.ql @@ -9,6 +9,11 @@ * @tags external/cert/id/str53-cpp * correctness * security + * external/cert/severity/high + * external/cert/likelihood/unlikely + * external/cert/remediation-cost/medium + * external/cert/priority/p6 + * external/cert/level/l2 * external/cert/obligation/rule */ From 54416547ef052258c37bb7db49f26fb84e6f0802 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Fri, 2 May 2025 11:04:59 +0100 Subject: [PATCH 325/370] Add query suites for levels 1 to 3. --- c/cert/src/codeql-suites/cert-c-l1.qls | 12 ++++++++++++ c/cert/src/codeql-suites/cert-c-l2.qls | 12 ++++++++++++ c/cert/src/codeql-suites/cert-c-l3.qls | 12 ++++++++++++ cpp/cert/src/codeql-suites/cert-cpp-l1.qls | 12 ++++++++++++ cpp/cert/src/codeql-suites/cert-cpp-l2.qls | 12 ++++++++++++ cpp/cert/src/codeql-suites/cert-cpp-l3.qls | 12 ++++++++++++ 6 files changed, 72 insertions(+) create mode 100644 c/cert/src/codeql-suites/cert-c-l1.qls create mode 100644 c/cert/src/codeql-suites/cert-c-l2.qls create mode 100644 c/cert/src/codeql-suites/cert-c-l3.qls create mode 100644 cpp/cert/src/codeql-suites/cert-cpp-l1.qls create mode 100644 cpp/cert/src/codeql-suites/cert-cpp-l2.qls create mode 100644 cpp/cert/src/codeql-suites/cert-cpp-l3.qls diff --git a/c/cert/src/codeql-suites/cert-c-l1.qls b/c/cert/src/codeql-suites/cert-c-l1.qls new file mode 100644 index 0000000000..b2056fbec8 --- /dev/null +++ b/c/cert/src/codeql-suites/cert-c-l1.qls @@ -0,0 +1,12 @@ +- description: CERT C 2016 Level 1 Rules (Priority 12 - Priority 27) +- qlpack: codeql/cert-c-coding-standards +- include: + kind: + - problem + - path-problem + - external/cert/obligation/rule + tags contain: + - external/cert/level/l1 +- exclude: + tags contain: + - external/cert/default-disabled \ No newline at end of file diff --git a/c/cert/src/codeql-suites/cert-c-l2.qls b/c/cert/src/codeql-suites/cert-c-l2.qls new file mode 100644 index 0000000000..9c0a4b1ef9 --- /dev/null +++ b/c/cert/src/codeql-suites/cert-c-l2.qls @@ -0,0 +1,12 @@ +- description: CERT C 2016 Level 2 Rules (Priority 6 - Priority 9) +- qlpack: codeql/cert-c-coding-standards +- include: + kind: + - problem + - path-problem + - external/cert/obligation/rule + tags contain: + - external/cert/level/l2 +- exclude: + tags contain: + - external/cert/default-disabled \ No newline at end of file diff --git a/c/cert/src/codeql-suites/cert-c-l3.qls b/c/cert/src/codeql-suites/cert-c-l3.qls new file mode 100644 index 0000000000..462a6d816f --- /dev/null +++ b/c/cert/src/codeql-suites/cert-c-l3.qls @@ -0,0 +1,12 @@ +- description: CERT C 2016 Level 3 Rules (Priority 1 - Priority 4) +- qlpack: codeql/cert-c-coding-standards +- include: + kind: + - problem + - path-problem + - external/cert/obligation/rule + tags contain: + - external/cert/level/l3 +- exclude: + tags contain: + - external/cert/default-disabled \ No newline at end of file diff --git a/cpp/cert/src/codeql-suites/cert-cpp-l1.qls b/cpp/cert/src/codeql-suites/cert-cpp-l1.qls new file mode 100644 index 0000000000..d96def2456 --- /dev/null +++ b/cpp/cert/src/codeql-suites/cert-cpp-l1.qls @@ -0,0 +1,12 @@ +- description: CERT C++ 2016 Level 1 Rules (Priority 12 - Priority 27) +- qlpack: codeql/cert-cpp-coding-standards +- include: + kind: + - problem + - path-problem + - external/cert/obligation/rule + tags contain: + - external/cert/level/l1 +- exclude: + tags contain: + - external/cert/default-disabled \ No newline at end of file diff --git a/cpp/cert/src/codeql-suites/cert-cpp-l2.qls b/cpp/cert/src/codeql-suites/cert-cpp-l2.qls new file mode 100644 index 0000000000..b08cb07536 --- /dev/null +++ b/cpp/cert/src/codeql-suites/cert-cpp-l2.qls @@ -0,0 +1,12 @@ +- description: CERT C++ 2016 Level 2 Rules (Priority 6 - Priority 9) +- qlpack: codeql/cert-cpp-coding-standards +- include: + kind: + - problem + - path-problem + - external/cert/obligation/rule + tags contain: + - external/cert/level/l2 +- exclude: + tags contain: + - external/cert/default-disabled \ No newline at end of file diff --git a/cpp/cert/src/codeql-suites/cert-cpp-l3.qls b/cpp/cert/src/codeql-suites/cert-cpp-l3.qls new file mode 100644 index 0000000000..ca621c96ab --- /dev/null +++ b/cpp/cert/src/codeql-suites/cert-cpp-l3.qls @@ -0,0 +1,12 @@ +- description: CERT C++ 2016 Level 3 Rules (Priority 1 - Priority 4) +- qlpack: codeql/cert-cpp-coding-standards +- include: + kind: + - problem + - path-problem + - external/cert/obligation/rule + tags contain: + - external/cert/level/l3 +- exclude: + tags contain: + - external/cert/default-disabled \ No newline at end of file From df44da0bf059d33abdedd6d4997631c13f617e31 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Fri, 2 May 2025 11:32:50 +0100 Subject: [PATCH 326/370] Add change note --- change_notes/2025-05-01-cert-extra-props.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 change_notes/2025-05-01-cert-extra-props.md diff --git a/change_notes/2025-05-01-cert-extra-props.md b/change_notes/2025-05-01-cert-extra-props.md new file mode 100644 index 0000000000..3244360703 --- /dev/null +++ b/change_notes/2025-05-01-cert-extra-props.md @@ -0,0 +1,2 @@ + - All CERT rules now include additional tags to represent the [Risk Assessment](https://wiki.sei.cmu.edu/confluence/display/c/How+this+Coding+Standard+is+Organized#HowthisCodingStandardisOrganized-RiskAssessment) properties specified on CERT rules. + - In addition, new query suites are included which allow the selection of queries that represent CERT Rules (not Recommendations) for each of the Levels (1-3). These are called `cert--.qls` and can be used either directly in the CodeQL CLI, or via the CodeQL Action. \ No newline at end of file From 9e24b41e85cbecee58cc3e333fbc3cd695134dfc Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 5 May 2025 15:47:32 +0100 Subject: [PATCH 327/370] Remove spurious recommendation tag In some of the CERT help files they use "Recommendation" rather than "Rule" as a header in the Risk Assessment table, creating spurious query tags. --- .../rules/CON34-C/AppropriateThreadObjectStorageDurations.ql | 1 - .../CON34-C/ThreadObjectStorageDurationsNotInitialized.ql | 1 - .../DoNotAccessVariableViaPointerOfIncompatibleType.ql | 1 - c/cert/src/rules/EXP45-C/AssignmentsInSelectionStatements.ql | 1 - .../rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.ql | 1 - rule_packages/c/Concurrency4.json | 2 -- rule_packages/c/Memory2.json | 1 - rule_packages/c/Pointers3.json | 1 - rule_packages/c/SideEffects1.json | 1 - scripts/add_risk_assessment_tags.py | 4 ++-- 10 files changed, 2 insertions(+), 12 deletions(-) diff --git a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql index eef196a9ec..4fb034406b 100644 --- a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql +++ b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql @@ -9,7 +9,6 @@ * @tags external/cert/id/con34-c * correctness * concurrency - * external/cert/recommendation/con34-c * external/cert/severity/medium * external/cert/likelihood/probable * external/cert/remediation-cost/high diff --git a/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql b/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql index fa0587bce0..07b114d6ca 100644 --- a/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql +++ b/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql @@ -10,7 +10,6 @@ * external/cert/audit * correctness * concurrency - * external/cert/recommendation/con34-c * external/cert/severity/medium * external/cert/likelihood/probable * external/cert/remediation-cost/high diff --git a/c/cert/src/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.ql b/c/cert/src/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.ql index c5772340ef..856cad1d58 100644 --- a/c/cert/src/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.ql +++ b/c/cert/src/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.ql @@ -8,7 +8,6 @@ * @problem.severity error * @tags external/cert/id/exp39-c * correctness - * external/cert/recommendation/exp39-c * external/cert/severity/medium * external/cert/likelihood/unlikely * external/cert/remediation-cost/high diff --git a/c/cert/src/rules/EXP45-C/AssignmentsInSelectionStatements.ql b/c/cert/src/rules/EXP45-C/AssignmentsInSelectionStatements.ql index 5478bb03f7..c831713486 100644 --- a/c/cert/src/rules/EXP45-C/AssignmentsInSelectionStatements.ql +++ b/c/cert/src/rules/EXP45-C/AssignmentsInSelectionStatements.ql @@ -8,7 +8,6 @@ * @problem.severity error * @tags external/cert/id/exp45-c * correctness - * external/cert/recommendation/exp45-c * external/cert/severity/low * external/cert/likelihood/likely * external/cert/remediation-cost/medium diff --git a/c/cert/src/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.ql b/c/cert/src/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.ql index 5515bfc80d..90c34a44a2 100644 --- a/c/cert/src/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.ql +++ b/c/cert/src/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.ql @@ -9,7 +9,6 @@ * @tags external/cert/id/mem36-c * correctness * security - * external/cert/recommendation/mem36-c * external/cert/severity/low * external/cert/likelihood/probable * external/cert/remediation-cost/high diff --git a/rule_packages/c/Concurrency4.json b/rule_packages/c/Concurrency4.json index 45f4b495fc..b981ebaa8b 100644 --- a/rule_packages/c/Concurrency4.json +++ b/rule_packages/c/Concurrency4.json @@ -43,7 +43,6 @@ "tags": [ "correctness", "concurrency", - "external/cert/recommendation/con34-c", "external/cert/severity/medium", "external/cert/likelihood/probable", "external/cert/remediation-cost/high", @@ -65,7 +64,6 @@ "external/cert/audit", "correctness", "concurrency", - "external/cert/recommendation/con34-c", "external/cert/severity/medium", "external/cert/likelihood/probable", "external/cert/remediation-cost/high", diff --git a/rule_packages/c/Memory2.json b/rule_packages/c/Memory2.json index 9f475e4df8..55a7dd2a35 100644 --- a/rule_packages/c/Memory2.json +++ b/rule_packages/c/Memory2.json @@ -177,7 +177,6 @@ "tags": [ "correctness", "security", - "external/cert/recommendation/mem36-c", "external/cert/severity/low", "external/cert/likelihood/probable", "external/cert/remediation-cost/high", diff --git a/rule_packages/c/Pointers3.json b/rule_packages/c/Pointers3.json index f00018b1ad..8a169b71a8 100644 --- a/rule_packages/c/Pointers3.json +++ b/rule_packages/c/Pointers3.json @@ -65,7 +65,6 @@ "short_name": "DoNotAccessVariableViaPointerOfIncompatibleType", "tags": [ "correctness", - "external/cert/recommendation/exp39-c", "external/cert/severity/medium", "external/cert/likelihood/unlikely", "external/cert/remediation-cost/high", diff --git a/rule_packages/c/SideEffects1.json b/rule_packages/c/SideEffects1.json index 7e0ab9c90b..4dec3d8bbf 100644 --- a/rule_packages/c/SideEffects1.json +++ b/rule_packages/c/SideEffects1.json @@ -78,7 +78,6 @@ "short_name": "AssignmentsInSelectionStatements", "tags": [ "correctness", - "external/cert/recommendation/exp45-c", "external/cert/severity/low", "external/cert/likelihood/likely", "external/cert/remediation-cost/medium", diff --git a/scripts/add_risk_assessment_tags.py b/scripts/add_risk_assessment_tags.py index f2ed9a5a73..6560d82a44 100644 --- a/scripts/add_risk_assessment_tags.py +++ b/scripts/add_risk_assessment_tags.py @@ -123,8 +123,8 @@ def process_rule_package(rule_package_file): # Add each risk assessment property as a tag for key, value in risk_data.items(): key_sanitized = key.lower().replace(" ", "-") - if key_sanitized == "rule": - # skip rule, as that is already in the rule ID + if key_sanitized == "rule" or key_sanitized == "recommendation": + # skip rule/recommendation as they just repeat the rule ID continue tag = f"external/cert/{key_sanitized}/{value.lower()}" if tag not in query["tags"]: From 44617e8d78b44bf7dd8ae0258751eb4fc33753db Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 5 May 2025 22:16:18 +0100 Subject: [PATCH 328/370] Update expected results for query file changes Deprecation warning lists location in query file, which has changed due to addition of new tags. --- ...bleLengthArraySizeNotInValidRange.expected | 4 +- ...rithmeticOnNonArrayObjectPointers.expected | 10 ++-- ...rSubtractAScaledIntegerToAPointer.expected | 8 ++-- .../CleanUpThreadSpecificStorage.expected | 12 ++--- ...riateThreadObjectStorageDurations.expected | 26 +++++----- ...ectStorageDurationsNotInitialized.expected | 10 ++-- ...ateStorageDurationsFunctionReturn.expected | 10 ++-- .../ERR30-C/ErrnoReadBeforeReturn.expected | 2 +- .../ERR30-C/SetlocaleMightSetErrno.expected | 2 +- ...tRelyOnIndeterminateValuesOfErrno.expected | 8 ++-- ...ectAndHandleStandardLibraryErrors.expected | 2 +- ...OfFunctionArgumentsForSideEffects.expected | 48 +++++++++---------- ...rToMoreStrictlyAlignedPointerType.expected | 20 ++++---- ...nctionPointerWithIncompatibleType.expected | 8 ++-- ...iableViaPointerOfIncompatibleType.expected | 14 +++--- .../DoNotModifyConstantObjects.expected | 8 ++-- ...ointerReferencesOverlappingObject.expected | 14 +++--- ...esetStringsOnFgetsOrFgetwsFailure.expected | 6 +-- ...FsetposThatAreReturnedFromFgetpos.expected | 10 ++-- ...RaceConditionsWhileAccessingFiles.expected | 2 +- ...ufficientMemoryAllocatedForObject.expected | 4 +- ...odifyAlignmentOfMemoryWithRealloc.expected | 10 ++-- ...ssInvalidDataToTheAsctimeFunction.expected | 8 ++-- ...VaListThatHasAnIndeterminateValue.expected | 14 +++--- ...SafeFunctionsWithinSignalHandlers.expected | 6 +-- ...romAComputationalExceptionHandler.expected | 2 +- ...oNotAttemptToModifyStringLiterals.expected | 26 +++++----- ...fficientSpaceForTheNullTerminator.expected | 12 ++--- ...natedToFunctionThatExpectsAString.expected | 20 ++++---- ...cCppLibraryFunctionsDoNotOverflow.expected | 18 +++---- .../CTR53-CPP/UseValidIteratorRanges.expected | 12 ++--- ...UseAnAdditiveOperatorOnAnIterator.expected | 18 +++---- ...terArithmeticOnPolymorphicObjects.expected | 8 ++-- ...nFunctionCallsAsFunctionArguments.expected | 48 +++++++++---------- ...ThroughAPointerOfTheIncorrectType.expected | 8 ++-- ...ctAndHandleMemoryAllocationErrors.expected | 14 +++--- .../BadlySeededRandomNumberGenerator.expected | 2 +- 37 files changed, 227 insertions(+), 227 deletions(-) diff --git a/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected b/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected index 083e7dfb87..0b400c5256 100644 --- a/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected +++ b/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected @@ -1,5 +1,5 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:104,11-19) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:87,5-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:109,11-19) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:92,5-18) | test.c:14:8:14:8 | VLA declaration | Variable-length array dimension size may be in an invalid range. | | test.c:15:8:15:8 | VLA declaration | Variable-length array dimension size may be in an invalid range. | | test.c:16:8:16:8 | VLA declaration | Variable-length array dimension size may be in an invalid range. | diff --git a/c/cert/test/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.expected b/c/cert/test/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.expected index ca4ef2a7a0..fb0074e0e6 100644 --- a/c/cert/test/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.expected +++ b/c/cert/test/rules/ARR37-C/DoNotUsePointerArithmeticOnNonArrayObjectPointers.expected @@ -1,8 +1,8 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:23,60-68) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:24,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:36,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:44,26-34) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:65,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:28,60-68) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:29,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:41,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:49,26-34) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnNonArrayObjectPointers.ql:70,3-11) edges | test.c:14:38:14:39 | p1 | test.c:18:10:18:11 | v1 | provenance | | | test.c:14:38:14:39 | p1 | test.c:19:10:19:11 | v2 | provenance | | diff --git a/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.expected b/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.expected index d343811aaf..0a6471deac 100644 --- a/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.expected +++ b/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.expected @@ -1,7 +1,7 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:72,56-64) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:73,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:75,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:84,45-53) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:77,56-64) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:78,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:80,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAddOrSubtractAScaledIntegerToAPointer.ql:89,45-53) edges | test.c:7:13:7:14 | p1 | test.c:9:9:9:10 | p1 | provenance | | | test.c:16:19:16:41 | ... - ... | test.c:18:26:18:31 | offset | provenance | | diff --git a/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected b/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected index 047ed12e8e..f3ea87136a 100644 --- a/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected +++ b/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected @@ -1,9 +1,9 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:20,46-54) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:21,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:30,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:40,35-43) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:48,36-44) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:50,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:25,46-54) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:26,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:35,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:45,35-43) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:53,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:55,36-44) | test.c:27:3:27:12 | call to tss_create | Resources used by thread specific storage may not be cleaned up. | | test.c:49:3:49:12 | call to tss_create | Resources used by thread specific storage may not be cleaned up. | | test.c:71:3:71:12 | call to tss_create | Resources used by thread specific storage may not be cleaned up. | diff --git a/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected b/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected index 503a01bdad..2cd844f81b 100644 --- a/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected +++ b/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected @@ -1,16 +1,16 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:30,14-22) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:32,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:34,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:37,45-53) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:47,33-41) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:47,58-66) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:48,42-50) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:51,9-17) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:51,34-42) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:52,9-17) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:52,34-42) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:37,9-22) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:47,7-20) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:35,14-22) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:37,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:39,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:42,45-53) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:52,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:52,58-66) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:53,42-50) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:56,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:56,34-42) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:57,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:57,34-42) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:42,9-22) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:52,7-20) | test.c:23:3:23:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:23:24:23:29 | & ... | Shared object | | test.c:74:3:74:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:74:24:74:24 | p | Shared object | | test.c:85:3:85:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:85:24:85:24 | p | Shared object | diff --git a/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected b/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected index f8e86fbb51..b2ac853fbf 100644 --- a/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected +++ b/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected @@ -1,6 +1,6 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:27,38-46) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:30,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:30,30-38) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:31,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:31,30-38) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:32,38-46) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:35,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:35,30-38) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:36,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:36,30-38) | test.c:14:7:14:13 | call to tss_get | Call to a thread specific storage function from within a threaded context on an object that may not be owned by this thread. | diff --git a/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected b/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected index f60689dbb1..a4359d7000 100644 --- a/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected +++ b/c/cert/test/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.expected @@ -1,7 +1,7 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:28,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:32,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:45,6-14) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:45,26-34) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:51,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:33,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:37,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:50,6-14) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:50,26-34) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateStorageDurationsFunctionReturn.ql:56,3-11) | test.c:3:10:3:10 | a | $@ with automatic storage may be accessible outside of its lifetime. | test.c:3:10:3:10 | a | a | | test.c:15:4:15:8 | param [inner post update] | $@ with automatic storage may be accessible outside of its lifetime. | test.c:15:12:15:13 | a2 | a2 | diff --git a/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected b/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected index e925901b47..125f55118b 100644 --- a/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected +++ b/c/cert/test/rules/ERR30-C/ErrnoReadBeforeReturn.expected @@ -1,4 +1,4 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ErrnoReadBeforeReturn.ql:41,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ErrnoReadBeforeReturn.ql:46,7-15) | test.c:69:7:69:11 | * ... | Do not read `errno` before checking the return value of function $@. | test.c:68:3:68:7 | call to ftell | call to ftell | | test.c:69:7:69:11 | call to __errno_location | Do not read `errno` before checking the return value of function $@. | test.c:68:3:68:7 | call to ftell | call to ftell | | test.c:70:5:70:10 | call to perror | Do not read `errno` before checking the return value of function $@. | test.c:68:3:68:7 | call to ftell | call to ftell | diff --git a/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected b/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected index 489bfc6bb0..20a7ff60b1 100644 --- a/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected +++ b/c/cert/test/rules/ERR30-C/SetlocaleMightSetErrno.expected @@ -1,3 +1,3 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (SetlocaleMightSetErrno.ql:65,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (SetlocaleMightSetErrno.ql:70,7-15) | test.c:98:3:98:11 | call to setlocale | Do not read `errno` before checking the return value of a call to `setlocale`. | | test.c:104:7:104:15 | call to setlocale | The value of `errno` may be different than `0` when `setlocale` is called. The following `errno` check might be invalid. | diff --git a/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected b/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected index a90dd6b7f5..1f313cb90d 100644 --- a/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected +++ b/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected @@ -1,7 +1,7 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:50,7-15) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:50,27-35) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:51,9-17) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:54,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:55,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:55,27-35) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:56,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:59,9-17) | test.c:12:5:12:10 | call to perror | `errno` has indeterminate value after this $@. | test.c:10:21:10:26 | call to signal | call to signal | | test.c:30:5:30:10 | call to perror | `errno` has indeterminate value after this $@. | test.c:26:21:26:26 | call to signal | call to signal | | test.c:49:5:49:10 | call to perror | `errno` has indeterminate value after this $@. | test.c:45:21:45:26 | call to signal | call to signal | diff --git a/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected b/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected index 030596976e..b13f34522c 100644 --- a/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected +++ b/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected @@ -1,4 +1,4 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleStandardLibraryErrors.ql:453,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleStandardLibraryErrors.ql:458,5-13) | test.c:18:3:18:11 | call to setlocale | Missing error detection for the call to function `setlocale`. | | test.c:24:23:24:31 | call to setlocale | Missing error detection for the call to function `setlocale`. | | test.c:29:22:29:27 | call to calloc | Missing error detection for the call to function `calloc`. | diff --git a/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected b/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected index ec791fe3e4..034f7e9366 100644 --- a/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected +++ b/c/cert/test/rules/EXP30-C/DependenceOnOrderOfFunctionArgumentsForSideEffects.expected @@ -1,25 +1,25 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:23,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:23,59-67) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:26,33-41) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:26,57-65) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:30,33-41) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:30,59-67) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:39,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:39,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:39,53-61) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:42,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:42,57-65) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:51,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:51,55-63) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:58,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:58,57-65) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:70,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:70,55-63) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:23,5-18) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:26,7-20) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:30,7-20) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:42,5-18) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:51,5-18) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:58,5-18) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:70,5-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:28,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:28,59-67) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:31,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:31,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:35,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:35,59-67) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:44,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:44,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:44,53-61) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:47,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:47,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:56,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:56,55-63) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:63,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:63,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:75,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:75,55-63) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:28,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:31,7-20) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:35,7-20) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:47,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:56,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:63,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DependenceOnOrderOfFunctionArgumentsForSideEffects.ql:75,5-18) | test.c:20:3:20:4 | call to f1 | Depending on the order of evaluation for the arguments $@ and $@ for side effects on shared state is unspecified and can result in unexpected behavior. | test.c:20:6:20:7 | call to f2 | call to f2 | test.c:20:12:20:13 | call to f3 | call to f3 | diff --git a/c/cert/test/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.expected b/c/cert/test/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.expected index eed9fb4585..eb7642ae28 100644 --- a/c/cert/test/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.expected +++ b/c/cert/test/rules/EXP36-C/DoNotCastPointerToMoreStrictlyAlignedPointerType.expected @@ -1,13 +1,13 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:98,86-94) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:120,3-11) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:122,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:127,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:133,3-11) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:139,55-63) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:140,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:142,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:149,26-34) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:164,44-52) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:103,86-94) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:125,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:127,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:132,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:138,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:144,55-63) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:145,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:147,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:154,26-34) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCastPointerToMoreStrictlyAlignedPointerType.ql:169,44-52) edges | test.c:75:14:75:16 | & ... | test.c:76:11:76:12 | v1 | provenance | | | test.c:75:14:75:16 | & ... | test.c:77:12:77:13 | v1 | provenance | | diff --git a/c/cert/test/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.expected b/c/cert/test/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.expected index 229bd74165..8daaf8361a 100644 --- a/c/cert/test/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.expected +++ b/c/cert/test/rules/EXP37-C/DoNotCallFunctionPointerWithIncompatibleType.expected @@ -1,7 +1,7 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:40,54-62) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:41,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:45,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:50,43-51) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:45,54-62) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:46,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:50,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallFunctionPointerWithIncompatibleType.ql:55,43-51) edges | test.c:48:68:48:70 | fns [f1] | test.c:49:3:49:5 | fns [f1] | provenance | | | test.c:49:3:49:5 | fns [f1] | test.c:49:8:49:9 | f1 | provenance | | diff --git a/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected b/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected index 9f0880455f..381e409d2a 100644 --- a/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected +++ b/c/cert/test/rules/EXP39-C/DoNotAccessVariableViaPointerOfIncompatibleType.expected @@ -1,10 +1,10 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:61,38-46) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:64,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:69,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:102,23-31) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:111,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:111,45-53) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:133,27-35) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:66,38-46) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:69,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:74,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:107,23-31) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:116,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:116,45-53) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAccessVariableViaPointerOfIncompatibleType.ql:138,27-35) edges | test.c:49:8:49:9 | s3 | test.c:50:8:50:9 | s1 | provenance | | | test.c:60:16:60:18 | E1A | test.c:61:16:61:17 | e1 | provenance | | diff --git a/c/cert/test/rules/EXP40-C/DoNotModifyConstantObjects.expected b/c/cert/test/rules/EXP40-C/DoNotModifyConstantObjects.expected index 6dd4ec261a..2ac874e770 100644 --- a/c/cert/test/rules/EXP40-C/DoNotModifyConstantObjects.expected +++ b/c/cert/test/rules/EXP40-C/DoNotModifyConstantObjects.expected @@ -1,7 +1,7 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:35,30-38) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:36,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:42,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:47,19-27) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:40,30-38) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:41,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:47,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyConstantObjects.ql:52,19-27) edges | test.c:5:8:5:9 | & ... | test.c:6:4:6:5 | aa | provenance | | | test.c:26:15:26:15 | a | test.c:27:4:27:4 | a | provenance | | diff --git a/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected b/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected index b9765e77fb..40009edc03 100644 --- a/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected +++ b/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected @@ -1,10 +1,10 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:42,57-65) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:43,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:47,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:53,3-11) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:56,58-66) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:72,64-72) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:73,64-72) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:47,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:48,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:52,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:58,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:61,58-66) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:77,64-72) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:78,64-72) | test.c:18:22:18:23 | i2 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:18:17:18:18 | i3 | i3 | test.c:18:22:18:23 | i2 | the object pointed to by i2 | | test.c:19:8:19:9 | g2 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:5:15:5:16 | g1 | g1 | test.c:19:8:19:9 | g2 | the object pointed to by g2 | | test.c:20:8:20:9 | i2 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:16:17:16:18 | i1 | i1 | test.c:20:8:20:9 | i2 | the object pointed to by i2 | diff --git a/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected b/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected index 669dd829c8..7d3cbe355b 100644 --- a/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected +++ b/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected @@ -1,6 +1,6 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:42,11-19) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:42,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:43,13-21) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:47,11-19) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:47,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:48,13-21) | test.c:20:10:20:12 | buf | The buffer is not reset before being referenced following a failed $@. | test.c:15:7:15:11 | call to fgets | call to fgets | | test.c:57:10:57:12 | buf | The buffer is not reset before being referenced following a failed $@. | test.c:52:7:52:11 | call to fgets | call to fgets | | test.c:66:18:66:20 | buf | The buffer is not reset before being referenced following a failed $@. | test.c:61:7:61:11 | call to fgets | call to fgets | diff --git a/c/cert/test/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.expected b/c/cert/test/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.expected index 5bff6016e4..ec05727161 100644 --- a/c/cert/test/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.expected +++ b/c/cert/test/rules/FIO44-C/OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.expected @@ -1,7 +1,7 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:25,32-40) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:26,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:28,14-22) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:31,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:37,21-29) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:30,32-40) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:31,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:33,14-22) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:36,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (OnlyUseValuesForFsetposThatAreReturnedFromFgetpos.ql:42,21-29) | test.c:7:24:7:30 | & ... | The position argument of a call to `fsetpos()` should be obtained from a call to `fgetpos()`. | | test.c:33:24:33:30 | & ... | The position argument of a call to `fsetpos()` should be obtained from a call to `fgetpos()`. | diff --git a/c/cert/test/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.expected b/c/cert/test/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.expected index 71df14e907..a211aa4002 100644 --- a/c/cert/test/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.expected +++ b/c/cert/test/rules/FIO45-C/ToctouRaceConditionsWhileAccessingFiles.expected @@ -1,3 +1,3 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ToctouRaceConditionsWhileAccessingFiles.ql:27,35-43) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ToctouRaceConditionsWhileAccessingFiles.ql:32,35-43) | test.c:4:13:4:17 | call to fopen | This call is trying to prevent an existing file from being overwritten by $@. An attacker might be able to exploit the race window between the two calls. | test.c:11:9:11:13 | call to fopen | another call | | test.c:88:13:88:17 | call to fopen | This call is trying to prevent an existing file from being overwritten by $@. An attacker might be able to exploit the race window between the two calls. | test.c:95:9:95:13 | call to fopen | another call | diff --git a/c/cert/test/rules/MEM35-C/InsufficientMemoryAllocatedForObject.expected b/c/cert/test/rules/MEM35-C/InsufficientMemoryAllocatedForObject.expected index 6bfbbefc14..86bdeedf5f 100644 --- a/c/cert/test/rules/MEM35-C/InsufficientMemoryAllocatedForObject.expected +++ b/c/cert/test/rules/MEM35-C/InsufficientMemoryAllocatedForObject.expected @@ -1,5 +1,5 @@ -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (InsufficientMemoryAllocatedForObject.ql:85,5-18) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (InsufficientMemoryAllocatedForObject.ql:143,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (InsufficientMemoryAllocatedForObject.ql:90,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (InsufficientMemoryAllocatedForObject.ql:148,5-18) | test.c:12:19:12:24 | call to malloc | Allocation size (32 bytes) is not a multiple of the size of 'S1' (36 bytes). | test.c:12:26:12:32 | 32 | | | test.c:15:19:15:24 | call to malloc | Allocation size calculated from the size of a different type ($@). | test.c:15:26:15:35 | sizeof() | sizeof(S1 *) | | test.c:20:19:20:24 | call to malloc | Allocation size (128 bytes) is not a multiple of the size of 'S1' (36 bytes). | test.c:20:26:20:36 | ... * ... | | diff --git a/c/cert/test/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.expected b/c/cert/test/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.expected index 2f5889c4c6..587ae786d1 100644 --- a/c/cert/test/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.expected +++ b/c/cert/test/rules/MEM36-C/DoNotModifyAlignmentOfMemoryWithRealloc.expected @@ -1,8 +1,8 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:26,36-44) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:40,47-55) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:41,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:45,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:50,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:31,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:45,47-55) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:46,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:50,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotModifyAlignmentOfMemoryWithRealloc.ql:55,36-44) edges | test.c:5:10:5:22 | call to aligned_alloc | test.c:15:8:15:28 | call to aligned_alloc_wrapper | provenance | | | test.c:8:29:8:31 | ptr | test.c:8:64:8:66 | ptr | provenance | | diff --git a/c/cert/test/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.expected b/c/cert/test/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.expected index 853d999d4e..7ebeb7a8c1 100644 --- a/c/cert/test/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.expected +++ b/c/cert/test/rules/MSC33-C/DoNotPassInvalidDataToTheAsctimeFunction.expected @@ -1,5 +1,5 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:33,38-46) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:34,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:41,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:44,27-35) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:38,38-46) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:39,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:46,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotPassInvalidDataToTheAsctimeFunction.ql:49,27-35) | test.c:6:24:6:30 | time_tm | The function `asctime` and `asctime_r` should be discouraged. Unsanitized input can overflow the output buffer. | diff --git a/c/cert/test/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.expected b/c/cert/test/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.expected index 4eaa05b179..4e14eb2873 100644 --- a/c/cert/test/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.expected +++ b/c/cert/test/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.expected @@ -1,10 +1,10 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:38,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:39,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:44,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:47,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:68,10-18) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:69,29-37) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:70,29-37) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:43,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:44,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:49,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:52,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:73,10-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:74,29-37) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql:75,29-37) | test.c:23:32:23:33 | ap | The value of ap is indeterminate after the $@. | test.c:17:7:17:19 | call to contains_zero | call to contains_zero | | test.c:26:10:26:11 | ap | The value of ap is indeterminate after the $@. | test.c:17:7:17:19 | call to contains_zero | call to contains_zero | | test.c:39:12:39:13 | ap | The value of ap is indeterminate after the $@. | test.c:35:7:35:19 | call to contains_zero | call to contains_zero | diff --git a/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected b/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected index 6190259408..4898448814 100644 --- a/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected +++ b/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected @@ -1,6 +1,6 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:105,11-19) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:105,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:106,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:110,11-19) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:110,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:111,9-17) | test.c:10:3:10:18 | call to log_local_unsafe | Asyncronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:16:7:16:12 | call to signal | signal handler | | test.c:11:3:11:6 | call to free | Asyncronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:16:7:16:12 | call to signal | signal handler | | test.c:46:3:46:9 | call to longjmp | Asyncronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:50:7:50:12 | call to signal | signal handler | diff --git a/c/cert/test/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.expected b/c/cert/test/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.expected index e861e90e9e..fb78049d25 100644 --- a/c/cert/test/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.expected +++ b/c/cert/test/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.expected @@ -1,2 +1,2 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotReturnFromAComputationalExceptionHandler.ql:39,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotReturnFromAComputationalExceptionHandler.ql:44,5-13) | test.c:10:1:10:1 | return ... | Do not return from a $@ signal handler. | test.c:13:10:13:15 | SIGFPE | computational exception | diff --git a/c/cert/test/rules/STR30-C/DoNotAttemptToModifyStringLiterals.expected b/c/cert/test/rules/STR30-C/DoNotAttemptToModifyStringLiterals.expected index 2a45193a17..d95b48e1c3 100644 --- a/c/cert/test/rules/STR30-C/DoNotAttemptToModifyStringLiterals.expected +++ b/c/cert/test/rules/STR30-C/DoNotAttemptToModifyStringLiterals.expected @@ -1,18 +1,18 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:42,65-73) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:43,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:64,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:77,3-11) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:101,11-19) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:101,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:101,55-63) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:47,65-73) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:48,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:69,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:82,3-11) WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:106,11-19) WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:106,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:106,57-65) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:139,11-19) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:139,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:139,55-63) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:150,53-61) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:151,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:106,55-63) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:111,11-19) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:111,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:111,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:144,11-19) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:144,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:144,55-63) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:155,53-61) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotAttemptToModifyStringLiterals.ql:156,5-13) | test.c:7:3:7:3 | a | This operation may write to a string that may be a string literal that was $@. | test.c:6:13:6:20 | codeql | created here | | test.c:30:3:30:3 | a | This operation may write to a string that may be a string literal that was $@. | test.c:29:13:29:18 | call to strchr | created here | | test.c:36:3:36:3 | b | This operation may write to a string that may be a string literal that was $@. | test.c:35:13:35:18 | call to strchr | created here | diff --git a/c/cert/test/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.expected b/c/cert/test/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.expected index 9012a2d78a..9a87a6775b 100644 --- a/c/cert/test/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.expected +++ b/c/cert/test/rules/STR31-C/StringsHasSufficientSpaceForTheNullTerminator.expected @@ -1,9 +1,9 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:57,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:57,55-63) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:63,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:63,54-62) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:57,5-18) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:63,5-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:62,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:62,55-63) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:68,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:68,54-62) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:62,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (StringsHasSufficientSpaceForTheNullTerminator.ql:68,5-18) | test.c:10:20:10:24 | Cod | Expression produces or consumes a string that may not have sufficient space for a null-terminator. | | test.c:16:3:16:9 | call to strncpy | Expression produces or consumes a string that may not have sufficient space for a null-terminator. | | test.c:26:3:26:10 | call to snprintf | Expression produces or consumes a string that may not have sufficient space for a null-terminator. | diff --git a/c/cert/test/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.expected b/c/cert/test/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.expected index da86e69b88..f537cc72ac 100644 --- a/c/cert/test/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.expected +++ b/c/cert/test/rules/STR32-C/NonNullTerminatedToFunctionThatExpectsAString.expected @@ -1,13 +1,13 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:64,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:66,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:74,39-47) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:75,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:81,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:83,34-42) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:83,57-65) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:123,3-11) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:123,26-34) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:120,17-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:69,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:71,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:79,39-47) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:80,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:86,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:88,34-42) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:88,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:128,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:128,26-34) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (NonNullTerminatedToFunctionThatExpectsAString.ql:125,17-30) | test.c:20:3:20:8 | call to printf | String modified by $@ is passed to function expecting a null-terminated string. | test.c:8:20:8:24 | Cod | this expression | | test.c:21:3:21:8 | call to printf | String modified by $@ is passed to function expecting a null-terminated string. | test.c:8:20:8:24 | Cod | this expression | | test.c:23:3:23:8 | call to printf | String modified by $@ is passed to function expecting a null-terminated string. | test.c:14:3:14:9 | call to strncpy | this expression | diff --git a/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected b/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected index 209d81ba8b..6be9fd55cc 100644 --- a/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected +++ b/cpp/cert/test/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow.expected @@ -1,12 +1,12 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:88,7-15) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:88,27-35) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:89,9-17) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:93,9-17) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:93,29-37) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:94,11-19) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:104,35-43) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:105,11-19) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:104,9-22) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:93,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:93,27-35) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:94,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:98,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:98,29-37) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:99,11-19) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:109,35-43) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:110,11-19) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (GuaranteeGenericCppLibraryFunctionsDoNotOverflow.ql:109,9-22) | test.cpp:8:42:8:46 | call to begin | Output iterator for $@ is not guaranteed to be large enough for the input iterator. | test.cpp:8:3:8:11 | call to copy | call to copy | | test.cpp:17:42:17:46 | call to begin | Output iterator for $@ is not guaranteed to be large enough for the input iterator. | test.cpp:17:3:17:11 | call to copy | call to copy | | test.cpp:55:42:55:46 | call to begin | Output iterator for $@ is not guaranteed to be large enough for the input iterator. | test.cpp:55:3:55:11 | call to copy | call to copy | diff --git a/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected b/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected index b5c36727f5..1953314c2f 100644 --- a/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected +++ b/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected @@ -1,9 +1,9 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:23,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:23,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:24,7-15) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:30,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:30,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:31,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:28,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:28,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:29,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:35,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:35,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:36,7-15) | test.cpp:7:3:7:15 | call to for_each | The $@ of iterator range function does not point to the end of an iterator. | test.cpp:7:28:7:32 | call to begin | argument | | test.cpp:7:3:7:15 | call to for_each | The $@ of iterator range function does not point to the start of an iterator. | test.cpp:7:19:7:21 | call to end | argument | | test.cpp:8:3:8:15 | call to for_each | The $@ of iterator range function does not point to the end of an iterator. | test.cpp:8:30:8:34 | call to begin | argument | diff --git a/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected b/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected index 0ba2fad433..48da16d208 100644 --- a/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected +++ b/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected @@ -1,12 +1,12 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:38,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:38,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:38,51-59) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:39,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:39,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:39,52-60) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:74,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:74,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:75,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:43,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:43,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:43,51-59) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:44,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:44,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:44,52-60) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:79,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:79,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:80,7-15) | test.cpp:8:7:8:7 | i | Increment of iterator may overflow since its bounds are not checked. | | test.cpp:9:9:9:9 | i | Increment of iterator may overflow since its bounds are not checked. | | test.cpp:10:9:10:9 | i | Increment of iterator may overflow since its bounds are not checked. | diff --git a/cpp/cert/test/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.expected b/cpp/cert/test/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.expected index 59caaa22d8..51ef13412c 100644 --- a/cpp/cert/test/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.expected +++ b/cpp/cert/test/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects.expected @@ -1,7 +1,7 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:41,62-70) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:42,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:51,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:57,3-11) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:46,62-70) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:47,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:56,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUsePointerArithmeticOnPolymorphicObjects.ql:62,3-11) edges | test.cpp:15:19:15:21 | foo | test.cpp:16:24:16:26 | foo | provenance | | | test.cpp:15:19:15:21 | foo | test.cpp:16:51:16:53 | foo | provenance | | diff --git a/cpp/cert/test/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.expected b/cpp/cert/test/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.expected index 00f1a6ba03..08d46a7bbd 100644 --- a/cpp/cert/test/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.expected +++ b/cpp/cert/test/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.expected @@ -1,27 +1,27 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:24,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:24,59-67) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:27,33-41) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:27,57-65) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:31,33-41) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:31,59-67) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:40,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:40,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:40,53-61) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:43,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:43,57-65) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:52,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:52,55-63) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:59,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:59,57-65) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:71,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:71,55-63) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:24,5-18) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:27,7-20) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:31,7-20) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:43,5-18) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:52,5-18) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:59,5-18) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:71,5-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:29,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:29,59-67) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:32,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:32,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:36,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:36,59-67) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:45,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:45,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:45,53-61) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:48,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:48,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:57,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:57,55-63) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:64,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:64,57-65) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:76,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:76,55-63) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:29,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:32,7-20) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:36,7-20) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:48,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:57,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:64,5-18) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments.ql:76,5-18) | test.cpp:82:3:82:4 | call to f2 | Depending on the order of evaluation for the arguments $@ and $@ for side effects on shared state is unspecified and can result in unexpected behavior. | test.cpp:82:6:82:7 | call to f5 | call to f5 | test.cpp:82:12:82:13 | call to f6 | call to f6 | | test.cpp:84:3:84:4 | call to f2 | Depending on the order of evaluation for the arguments $@ and $@ for side effects on shared state is unspecified and can result in unexpected behavior. | test.cpp:84:6:84:7 | call to f5 | call to f5 | test.cpp:84:12:84:13 | call to f7 | call to f7 | | test.cpp:87:3:87:4 | call to f2 | Depending on the order of evaluation for the arguments $@ and $@ for side effects on shared state is unspecified and can result in unexpected behavior. | test.cpp:87:9:87:10 | call to m1 | call to m1 | test.cpp:87:18:87:19 | call to m1 | call to m1 | diff --git a/cpp/cert/test/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.expected b/cpp/cert/test/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.expected index c271269ab8..8b7a4902cc 100644 --- a/cpp/cert/test/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.expected +++ b/cpp/cert/test/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.expected @@ -1,7 +1,7 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:19,44-52) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:20,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:22,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:27,33-41) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:24,44-52) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:25,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:27,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql:32,33-41) edges | test.cpp:6:19:6:37 | new[] | test.cpp:9:12:9:13 | l1 | provenance | | | test.cpp:7:22:7:40 | new[] | test.cpp:10:12:10:13 | l2 | provenance | | diff --git a/cpp/cert/test/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.expected b/cpp/cert/test/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.expected index b7b4891776..41fa58045f 100644 --- a/cpp/cert/test/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.expected +++ b/cpp/cert/test/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors.expected @@ -1,9 +1,9 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:59,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:61,36-44) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:77,46-54) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:78,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:82,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:85,35-43) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:90,38-46) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:64,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:66,36-44) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:82,46-54) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:83,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:87,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:90,35-43) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleMemoryAllocationErrors.ql:95,38-46) | test.cpp:24:7:24:34 | new | nothrow new allocation of $@ returns here without a subsequent check to see whether the pointer is valid. | test.cpp:24:7:24:34 | new | StructA * | | test.cpp:40:17:40:38 | call to allocate_without_check | nothrow new allocation of $@ returns here without a subsequent check to see whether the pointer is valid. | test.cpp:35:17:35:44 | new | StructA * | diff --git a/cpp/cert/test/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.expected b/cpp/cert/test/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.expected index 3743c3d414..606ccbff2b 100644 --- a/cpp/cert/test/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.expected +++ b/cpp/cert/test/rules/MSC51-CPP/BadlySeededRandomNumberGenerator.expected @@ -1,4 +1,4 @@ -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (BadlySeededRandomNumberGenerator.ql:37,7-20) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (BadlySeededRandomNumberGenerator.ql:42,7-20) | test.cpp:9:33:9:33 | call to linear_congruential_engine | Random number generator linear_congruential_engine is default-initialized and is therefore not properly seeded. | | test.cpp:10:30:10:31 | call to linear_congruential_engine | Random number generator linear_congruential_engine is default-initialized and is therefore not properly seeded. | | test.cpp:11:21:11:22 | call to linear_congruential_engine | Random number generator linear_congruential_engine is default-initialized and is therefore not properly seeded. | From f7c77cb9749547ee38201774d1bacb935621e72d Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Tue, 6 May 2025 06:52:46 -0400 Subject: [PATCH 329/370] Update rule package schema for new allowed tags --- schemas/rule-package.schema.json | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/schemas/rule-package.schema.json b/schemas/rule-package.schema.json index f8c3f028e3..fff79fede0 100644 --- a/schemas/rule-package.schema.json +++ b/schemas/rule-package.schema.json @@ -348,7 +348,29 @@ "external/misra/c/2012/amendment2", "external/misra/c/2012/amendment3", "external/misra/c/2012/amendment4", - "external/misra/c/strict" + "external/misra/c/strict", + "external/cert/severity/low", + "external/cert/severity/medium", + "external/cert/severity/high", + "external/cert/likelihood/unlikely", + "external/cert/likelihood/probable", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/low", + "external/cert/remediation-cost/medium", + "external/cert/remediation-cost/high", + "external/cert/priority/p1", + "external/cert/priority/p2", + "external/cert/priority/p3", + "external/cert/priority/p4", + "external/cert/priority/p6", + "external/cert/priority/p8", + "external/cert/priority/p9", + "external/cert/priority/p12", + "external/cert/priority/p18", + "external/cert/priority/p27", + "external/cert/level/l1", + "external/cert/level/l2", + "external/cert/level/l3" ] }, "minLength": 1 From 9169ec6831ed6382bd764d3a7e4fbd64607c9954 Mon Sep 17 00:00:00 2001 From: Max Base Date: Tue, 13 May 2025 18:35:12 +0000 Subject: [PATCH 330/370] fix: occured -> occurred --- cpp/report/src/Diagnostics/ExtractionErrors.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/report/src/Diagnostics/ExtractionErrors.qll b/cpp/report/src/Diagnostics/ExtractionErrors.qll index 55e1c96461..58757ca544 100644 --- a/cpp/report/src/Diagnostics/ExtractionErrors.qll +++ b/cpp/report/src/Diagnostics/ExtractionErrors.qll @@ -60,10 +60,10 @@ class ExtractionError extends TExtractionError { /** Gets the error message for this error. */ string getErrorMessage() { none() } - /** Gets the file this error occured in. */ + /** Gets the file this error occurred in. */ File getFile() { none() } - /** Gets the location this error occured in. */ + /** Gets the location this error occurred in. */ Location getLocation() { none() } /** Gets the SARIF severity of this error. */ From af488d1ba039526901d6a94a1922a2535a17fcd9 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 15 May 2025 21:25:26 +0100 Subject: [PATCH 331/370] Update README.md to list MISRA C 2023 as completed, and update date for MISRA C++ 2023. --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0f24587afe..02c226f84a 100644 --- a/README.md +++ b/README.md @@ -15,14 +15,15 @@ The following coding standards are supported: - [MISRA C 2012, 3rd Edition, 1st revision](https://www.misra.org.uk/product/misra-c2012-third-edition-first-revision/) (incoporating Amendment 1 & Technical Corrigendum 1). In addition, we support the following additional amendments and technical corrigendums: - [MISRA C 2012 Amendment 2](https://misra.org.uk/app/uploads/2021/06/MISRA-C-2012-AMD2.pdf) - [MISRA C 2012 Technical Corrigendum 2](https://misra.org.uk/app/uploads/2022/04/MISRA-C-2012-TC2.pdf) + - [MISRA C 2012 Amendment 3](https://misra.org.uk/app/uploads/2021/06/MISRA-C-2012-AMD3.pdf) + - [MISRA C 2012 Amendment 4](https://misra.org.uk/app/uploads/2021/06/MISRA-C-2012-AMD4.pdf) +- [MISRA C 2023](https://misra.org.uk/product/misra-c2023/) ## :construction: Standards under development :construction: -The following standards are under active development: +The following standards are under active development for [C++17](https://www.iso.org/standard/68564.html): -- [MISRA C++ 2023](https://misra.org.uk/product/misra-cpp2023/) - under development - _scheduled for release 2025 Q1_ -- [MISRA C 2023](https://misra.org.uk/product/misra-c2023/) - under development - _scheduled for release 2025 Q1_ - - This includes the development of [MISRA C 2012 Amendment 3](https://misra.org.uk/app/uploads/2021/06/MISRA-C-2012-AMD3.pdf) and [MISRA C 2012 Amendment 4](https://misra.org.uk/app/uploads/2021/06/MISRA-C-2012-AMD4.pdf), which are incorporated into MISRA C 2023. +- [MISRA C++ 2023](https://misra.org.uk/product/misra-cpp2023/) - under development - _scheduled for release 2025 Q2/Q3_ ## How do I use the CodeQL Coding Standards Queries? From 80529f072f721fb14e782d1e4041423246dba381 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 15 May 2025 21:26:15 +0100 Subject: [PATCH 332/370] Update user manual with MISRA C 2023 coverage. --- docs/user_manual.md | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/docs/user_manual.md b/docs/user_manual.md index 2920e024a6..4ab3de39c0 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -31,7 +31,8 @@ | 0.23.0 | 2024-10-21 | Luke Cartey | Add assembly as a hazard. | | 0.24.0 | 2024-10-22 | Luke Cartey | Add CodeQL packs as a usable output, update release artifacts list. | | 0.25.0 | 2025-01-15 | Mike Fairhurst | Add guidance for the usage of 'strict' queries. | -| 0.26.0 | 2025-02-12 | Luke Cartey | Describe support for new deviation code identifier formats | +| 0.26.0 | 2025-02-12 | Luke Cartey | Describe support for new deviation code identifier formats | +| 0.27.0 | 2025-05-15 | Luke Cartey | Documented completed support for MISRA C 2023. | ## Release information @@ -59,16 +60,16 @@ A _coding standard_ is a set of rules or guidelines which restrict or prohibit t The _CodeQL Coding Standards_ product is a set of CodeQL queries for identifying contraventions of rules in the following coding standards: -| Standard | Version | Rules | Supportable rules | Implemented rules | Status | -| -------------------------------------------------------------------------------------------------------------------- | ------- | ----------- | ----------------------- | ----------------- | ------- | -| AUTOSAR C++ | [^1] [R22-11](https://www.autosar.org/fileadmin/standards/R22-11/AP/AUTOSAR_RS_CPP14Guidelines.pdf), R21-11, R20-11, R19-11, R19-03 | 397 | 372 | 370[^2] | Implemented | -| CERT-C++ | [2016](https://resources.sei.cmu.edu/downloads/secure-coding/assets/sei-cert-cpp-coding-standard-2016-v01.pdf) | 83 | 82 | 82 | Implemented | -| CERT C | [2016](https://resources.sei.cmu.edu/downloads/secure-coding/assets/sei-cert-c-coding-standard-2016-v01.pdf) | 99 | 97 | 97 | Implemented | -| MISRA C | [2012 Third Edition, First Revision](https://www.misra.org.uk/product/misra-c2012-third-edition-first-revision/), [Amendment 2](https://misra.org.uk/app/uploads/2021/06/MISRA-C-2012-AMD2.pdf) and TC2 | 175 | 164 | 162[^3] | Implemented | -| | [MISRA C 2012 Amendment 3](https://misra.org.uk/app/uploads/2021/06/MISRA-C-2012-AMD3.pdf) | 24 | 24 | - | Under development | -| | [MISRA C 2012 Amendment 4](https://misra.org.uk/app/uploads/2021/06/MISRA-C-2012-AMD4.pdf) | 22 | 22 | - | Under development | -| | [2023 Third Edition, Second Revision](https://misra.org.uk/product/misra-c2023/) | 221 | 210 | - | Under development | -| MISRA C++ | [2023](https://misra.org.uk/product/misra-cpp2023/) | 179 | 176[^4] | - | Under development | +| Standard | Version | Rules | Supportable rules | Implemented rules | Status | +| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | ----------------- | ----------------- | ----------------- | +| AUTOSAR C++ | [^1] [R22-11](https://www.autosar.org/fileadmin/standards/R22-11/AP/AUTOSAR_RS_CPP14Guidelines.pdf), R21-11, R20-11, R19-11, R19-03 | 397 | 372 | 370[^2] | Implemented | +| CERT-C++ | [2016](https://resources.sei.cmu.edu/downloads/secure-coding/assets/sei-cert-cpp-coding-standard-2016-v01.pdf) | 83 | 82 | 82 | Implemented | +| CERT C | [2016](https://resources.sei.cmu.edu/downloads/secure-coding/assets/sei-cert-c-coding-standard-2016-v01.pdf) | 99 | 97 | 97 | Implemented | +| MISRA C | [2012 Third Edition, First Revision](https://www.misra.org.uk/product/misra-c2012-third-edition-first-revision/), [Amendment 2](https://misra.org.uk/app/uploads/2021/06/MISRA-C-2012-AMD2.pdf) and TC2 | 175 | 164 | 162[^3] | Implemented | +| | [2012 Amendment 3](https://misra.org.uk/app/uploads/2021/06/MISRA-C-2012-AMD3.pdf) | 24 | 24 | 24 | Implemented | +| | [2012 Amendment 4](https://misra.org.uk/app/uploads/2021/06/MISRA-C-2012-AMD4.pdf) | 22 | 22 | 21[^4] | Implemented | +| | [2023 Third Edition, Second Revision](https://misra.org.uk/product/misra-c2023/) | 221 | 210 | 207[^5] | Implemented | +| MISRA C++ | [2023](https://misra.org.uk/product/misra-cpp2023/) | 179 | 176[^6] | - | Under development | Not all rules in these standards are amenable to static analysis by CodeQL - some rules require external or domain specific knowledge to validate, or refer to properties which are not present in our representation of the codebase under analysis. In addition, some rules are natively enforced by the supported compilers. As CodeQL requires that the program under analysis compiles, we are unable to implement queries for these rules, and doing so would be redundant. @@ -84,8 +85,10 @@ The datasheet _"CodeQL Coding Standards: supported rules"_, provided with each r [^1]: AUTOSAR C++ versions R22-11, R21-11, R20-11, R19-11 and R19-03 are all identical as indicated in the document change history. [^2]: The unimplemented supportable AUTOSAR rules are `A7-1-8` and `A8-2-1`. These rules require additional support in the CodeQL CLI to ensure the required information is available in the CodeQL database to identify violations of these rules. -[^3]: The unimplemented supportable MISRA C 2012 rules are `Rule 9.5`, `Rule 17.13`, and `Dir 4.14`. `Rule 9.5` and `Rule 17.13` require additional support in the CodeQL CLI to ensure the required information is available in the CodeQL database to identify violations of these rules. `Dir 4.14` is covered by the default CodeQL queries, which identify potential security vulnerabilities caused by not validating external input. -[^4]: The rules 5.13.7, 19.0.1 and 19.1.2 are not planned to be implemented by CodeQL as they are compiler checked in all supported compilers. +[^3]: The unimplemented supportable MISRA C 2012 rules are `Rule 9.5`, `Rule 17.13`. `Rule 9.5` and `Rule 17.13` require additional support in the CodeQL CLI to ensure the required information is available in the CodeQL database to identify violations of these rules. Note: `Dir 4.14` is covered by the default CodeQL queries, which identify potential security vulnerabilities caused by not validating external input. +[^4]: The unimplemented supportable MISRA C 2012 Amendment 4 rule is `Rule 9.6`. `Rule 9.6` requires additional support in the CodeQL CLI to ensure the required information is available in the CodeQL database to identify violations of this rule. +[^5]: The unimplemented supportable MISRA C 2023 rules are `Rule 9.5`, `Rule 9.6`, `Rule 17.13`. `Rule 9.5`, `Rule 9.6` and `Rule 17.13` require additional support in the CodeQL CLI to ensure the required information is available in the CodeQL database to identify violations of these rules. Note: `Dir 4.14` is covered by the default CodeQL queries, which identify potential security vulnerabilities caused by not validating external input. +[^6]: The rules `5.13.7`, `19.0.1` and `19.1.2` are not planned to be implemented by CodeQL as they are compiler checked in all supported compilers. ## Supported environment From b8b66ae31e67393246afcaf1dce260c5ba8d9c89 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 15 May 2025 21:26:49 +0100 Subject: [PATCH 333/370] Update query suites to reference MISRA C 2023. --- c/misra/src/codeql-suites/misra-c-advisory.qls | 2 +- c/misra/src/codeql-suites/misra-c-audit.qls | 2 +- c/misra/src/codeql-suites/misra-c-default.qls | 2 +- c/misra/src/codeql-suites/misra-c-mandatory.qls | 2 +- c/misra/src/codeql-suites/misra-c-required.qls | 2 +- c/misra/src/codeql-suites/misra-c-strict.qls | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/c/misra/src/codeql-suites/misra-c-advisory.qls b/c/misra/src/codeql-suites/misra-c-advisory.qls index 517f449b13..39df0d6583 100644 --- a/c/misra/src/codeql-suites/misra-c-advisory.qls +++ b/c/misra/src/codeql-suites/misra-c-advisory.qls @@ -1,4 +1,4 @@ -- description: MISRA C 2012 (Advisory) +- description: MISRA C 2023 (Advisory) - qlpack: codeql/misra-c-coding-standards - include: kind: diff --git a/c/misra/src/codeql-suites/misra-c-audit.qls b/c/misra/src/codeql-suites/misra-c-audit.qls index ce1b9fed68..cac9df04ae 100644 --- a/c/misra/src/codeql-suites/misra-c-audit.qls +++ b/c/misra/src/codeql-suites/misra-c-audit.qls @@ -1,4 +1,4 @@ -- description: MISRA C 2012 (Audit) +- description: MISRA C 2023 (Audit) - qlpack: codeql/misra-c-coding-standards - include: kind: diff --git a/c/misra/src/codeql-suites/misra-c-default.qls b/c/misra/src/codeql-suites/misra-c-default.qls index f72a63ba49..cdc6eb65ad 100644 --- a/c/misra/src/codeql-suites/misra-c-default.qls +++ b/c/misra/src/codeql-suites/misra-c-default.qls @@ -1,4 +1,4 @@ -- description: MISRA C 2012 (Default) +- description: MISRA C 2023 (Default) - qlpack: codeql/misra-c-coding-standards - include: kind: diff --git a/c/misra/src/codeql-suites/misra-c-mandatory.qls b/c/misra/src/codeql-suites/misra-c-mandatory.qls index 454b8487ab..09eccdc50c 100644 --- a/c/misra/src/codeql-suites/misra-c-mandatory.qls +++ b/c/misra/src/codeql-suites/misra-c-mandatory.qls @@ -1,4 +1,4 @@ -- description: MISRA C 2012 (Advisory) +- description: MISRA C 2023 (Advisory) - qlpack: codeql/misra-c-coding-standards - include: kind: diff --git a/c/misra/src/codeql-suites/misra-c-required.qls b/c/misra/src/codeql-suites/misra-c-required.qls index ca32b9ca97..f7c77e937a 100644 --- a/c/misra/src/codeql-suites/misra-c-required.qls +++ b/c/misra/src/codeql-suites/misra-c-required.qls @@ -1,4 +1,4 @@ -- description: MISRA C 2012 (Required) +- description: MISRA C 2023 (Required) - qlpack: codeql/misra-c-coding-standards - include: kind: diff --git a/c/misra/src/codeql-suites/misra-c-strict.qls b/c/misra/src/codeql-suites/misra-c-strict.qls index 6fb642424c..b8f4885189 100644 --- a/c/misra/src/codeql-suites/misra-c-strict.qls +++ b/c/misra/src/codeql-suites/misra-c-strict.qls @@ -1,4 +1,4 @@ -- description: MISRA C 2012 (Strict) +- description: MISRA C 2023 (Strict) - qlpack: codeql/misra-c-coding-standards - include: kind: From 837af1f46780fd6c62452c2260ccbc6757c5a183 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 15 May 2025 21:27:43 +0100 Subject: [PATCH 334/370] Add changelog for MISRA C 2023. --- change_notes/2025-05-15-misra-c-2023.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 change_notes/2025-05-15-misra-c-2023.md diff --git a/change_notes/2025-05-15-misra-c-2023.md b/change_notes/2025-05-15-misra-c-2023.md new file mode 100644 index 0000000000..defd2ff823 --- /dev/null +++ b/change_notes/2025-05-15-misra-c-2023.md @@ -0,0 +1,4 @@ + - Support for MISRA C 2023 is now completed. + - The default query suites for MISRA C now target MISRA C 2023. + - The user manual has been updated to list MISRA C 2023 as completed. + - The `misra-c-2012-third-edition-with-amendment-2.qls` query suite can be used to run the queries present in MISRA C 2012 (3rd Edition) and Amendment 2. \ No newline at end of file From e1d028cd93b671a3e775d4dd1fe111b51b1862ce Mon Sep 17 00:00:00 2001 From: knewbury01 Date: Wed, 21 May 2025 18:06:18 +0000 Subject: [PATCH 335/370] Bump version to 2.46.0-dev --- c/cert/src/qlpack.yml | 2 +- c/cert/test/qlpack.yml | 2 +- c/common/src/qlpack.yml | 2 +- c/common/test/qlpack.yml | 2 +- c/misra/src/qlpack.yml | 2 +- c/misra/test/qlpack.yml | 2 +- cpp/autosar/src/qlpack.yml | 2 +- cpp/autosar/test/qlpack.yml | 2 +- cpp/cert/src/qlpack.yml | 2 +- cpp/cert/test/qlpack.yml | 2 +- cpp/common/src/qlpack.yml | 2 +- cpp/common/test/qlpack.yml | 2 +- cpp/misra/src/qlpack.yml | 2 +- cpp/misra/test/qlpack.yml | 2 +- cpp/report/src/qlpack.yml | 2 +- docs/user_manual.md | 12 ++++++------ 16 files changed, 21 insertions(+), 21 deletions(-) diff --git a/c/cert/src/qlpack.yml b/c/cert/src/qlpack.yml index 46124fd7c4..128ac606f8 100644 --- a/c/cert/src/qlpack.yml +++ b/c/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards -version: 2.45.0-dev +version: 2.46.0-dev description: CERT C 2016 suites: codeql-suites license: MIT diff --git a/c/cert/test/qlpack.yml b/c/cert/test/qlpack.yml index f7fe527dab..6920ec1771 100644 --- a/c/cert/test/qlpack.yml +++ b/c/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards-tests -version: 2.45.0-dev +version: 2.46.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/common/src/qlpack.yml b/c/common/src/qlpack.yml index ad3f825a4b..13a994e0a3 100644 --- a/c/common/src/qlpack.yml +++ b/c/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards -version: 2.45.0-dev +version: 2.46.0-dev license: MIT dependencies: codeql/common-cpp-coding-standards: '*' diff --git a/c/common/test/qlpack.yml b/c/common/test/qlpack.yml index cbadd7f238..09640c31c9 100644 --- a/c/common/test/qlpack.yml +++ b/c/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards-tests -version: 2.45.0-dev +version: 2.46.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/misra/src/qlpack.yml b/c/misra/src/qlpack.yml index b5d16e9974..d37d64c88a 100644 --- a/c/misra/src/qlpack.yml +++ b/c/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards -version: 2.45.0-dev +version: 2.46.0-dev description: MISRA C 2012 suites: codeql-suites license: MIT diff --git a/c/misra/test/qlpack.yml b/c/misra/test/qlpack.yml index e6932cc894..a22391774f 100644 --- a/c/misra/test/qlpack.yml +++ b/c/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards-tests -version: 2.45.0-dev +version: 2.46.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/autosar/src/qlpack.yml b/cpp/autosar/src/qlpack.yml index b9cd9b72a8..dd095ff354 100644 --- a/cpp/autosar/src/qlpack.yml +++ b/cpp/autosar/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards -version: 2.45.0-dev +version: 2.46.0-dev description: AUTOSAR C++14 Guidelines R22-11, R21-11, R20-11, R19-11 and R19-03 suites: codeql-suites license: MIT diff --git a/cpp/autosar/test/qlpack.yml b/cpp/autosar/test/qlpack.yml index 0b92541fdf..7182f771d5 100644 --- a/cpp/autosar/test/qlpack.yml +++ b/cpp/autosar/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards-tests -version: 2.45.0-dev +version: 2.46.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/cert/src/qlpack.yml b/cpp/cert/src/qlpack.yml index d23ea8fc34..792575ad6e 100644 --- a/cpp/cert/src/qlpack.yml +++ b/cpp/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards -version: 2.45.0-dev +version: 2.46.0-dev description: CERT C++ 2016 suites: codeql-suites license: MIT diff --git a/cpp/cert/test/qlpack.yml b/cpp/cert/test/qlpack.yml index 1baf2b3fc3..7463027aaf 100644 --- a/cpp/cert/test/qlpack.yml +++ b/cpp/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards-tests -version: 2.45.0-dev +version: 2.46.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/common/src/qlpack.yml b/cpp/common/src/qlpack.yml index 47a116582c..1813fb7fe3 100644 --- a/cpp/common/src/qlpack.yml +++ b/cpp/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards -version: 2.45.0-dev +version: 2.46.0-dev license: MIT dependencies: codeql/cpp-all: 2.1.1 diff --git a/cpp/common/test/qlpack.yml b/cpp/common/test/qlpack.yml index a636b824dc..8912a9c683 100644 --- a/cpp/common/test/qlpack.yml +++ b/cpp/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards-tests -version: 2.45.0-dev +version: 2.46.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/misra/src/qlpack.yml b/cpp/misra/src/qlpack.yml index a98ccfa757..5cb9d79b87 100644 --- a/cpp/misra/src/qlpack.yml +++ b/cpp/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards -version: 2.45.0-dev +version: 2.46.0-dev description: MISRA C++ 2023 default-suite: codeql-suites/misra-cpp-default.qls license: MIT diff --git a/cpp/misra/test/qlpack.yml b/cpp/misra/test/qlpack.yml index aad59493fe..69cd110473 100644 --- a/cpp/misra/test/qlpack.yml +++ b/cpp/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards-tests -version: 2.45.0-dev +version: 2.46.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/report/src/qlpack.yml b/cpp/report/src/qlpack.yml index 731d68dd29..c6f5f7052f 100644 --- a/cpp/report/src/qlpack.yml +++ b/cpp/report/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/report-cpp-coding-standards -version: 2.45.0-dev +version: 2.46.0-dev license: MIT dependencies: codeql/cpp-all: 2.1.1 diff --git a/docs/user_manual.md b/docs/user_manual.md index 4ab3de39c0..a758d3678c 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -36,14 +36,14 @@ ## Release information -This user manual documents release `2.45.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). +This user manual documents release `2.46.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). The release page documents the release notes and contains the following artifacts part of the release: - `coding-standards-codeql-packs-2.37.0-dev.zip`: CodeQL packs that can be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `code-scanning-cpp-query-pack-2.45.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `supported_rules_list_2.45.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. -- `supported_rules_list_2.45.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. -- `user_manual_2.45.0-dev.md`: This user manual. +- `code-scanning-cpp-query-pack-2.46.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. +- `supported_rules_list_2.46.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. +- `supported_rules_list_2.46.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. +- `user_manual_2.46.0-dev.md`: This user manual. - `Source Code (zip)`: A zip archive containing the contents of https://github.com/github/codeql-coding-standards - `Source Code (tar.gz)`: A GZip compressed tar archive containing the contents of https://github.com/github/codeql-coding-standards - `checksums.txt`: A text file containing sha256 checksums for the aforementioned artifacts. @@ -670,7 +670,7 @@ This section describes known failure modes for "CodeQL Coding Standards" and des | | Out of space | Less output. Some files may be only be partially analyzed, or not analyzed at all. | Error reported on the command line. | Increase space. If it remains an issue report space consumption issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False positives | More output. Results are reported which are not violations of the guidelines. | All reported results must be reviewed. | Report false positive issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False negatives | Less output. Violations of the guidelines are not reported. | Other validation and verification processes during software development should be used to complement the analysis performed by CodeQL Coding Standards. | Report false negative issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.45.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | +| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.46.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | | | Incorrect deviation record specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation records with a reason. Ensure that all deviation records are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Incorrect deviation permit specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation permits with a reason. Ensure that all deviation permits are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Unapproved use of a deviation record | Less output. Results for guideline violations are not reported. | Validate that the deviation record use is approved by verifying the approved-by attribute of the deviation record specification. | Ensure that each raised deviation record is approved by an independent approver through an auditable process. | From 985a2d1ed43a32e2446317182627793050f74b36 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 4 Jun 2025 12:22:02 +0100 Subject: [PATCH 336/370] Fix poor performance of sameSource predicate --- .../IOFstreamMissingPositioning.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll b/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll index 547c90daf5..b26421c72c 100644 --- a/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll +++ b/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll @@ -51,7 +51,8 @@ class WriteFunctionCall extends ReadWriteCall { } } -pragma[inline] +bindingset[a, b] +pragma[inline_late] predicate sameSource(FunctionCall a, FunctionCall b) { sameStreamSource(a, b) or sameFileSource(a, b) From e9e7cfa26931911e205f65a47245af6c550ef2e1 Mon Sep 17 00:00:00 2001 From: knewbury01 Date: Wed, 4 Jun 2025 14:12:21 +0000 Subject: [PATCH 337/370] Bump version to 2.47.0-dev --- c/cert/src/qlpack.yml | 2 +- c/cert/test/qlpack.yml | 2 +- c/common/src/qlpack.yml | 2 +- c/common/test/qlpack.yml | 2 +- c/misra/src/qlpack.yml | 2 +- c/misra/test/qlpack.yml | 2 +- cpp/autosar/src/qlpack.yml | 2 +- cpp/autosar/test/qlpack.yml | 2 +- cpp/cert/src/qlpack.yml | 2 +- cpp/cert/test/qlpack.yml | 2 +- cpp/common/src/qlpack.yml | 2 +- cpp/common/test/qlpack.yml | 2 +- cpp/misra/src/qlpack.yml | 2 +- cpp/misra/test/qlpack.yml | 2 +- cpp/report/src/qlpack.yml | 2 +- docs/user_manual.md | 12 ++++++------ 16 files changed, 21 insertions(+), 21 deletions(-) diff --git a/c/cert/src/qlpack.yml b/c/cert/src/qlpack.yml index 128ac606f8..26311dda18 100644 --- a/c/cert/src/qlpack.yml +++ b/c/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards -version: 2.46.0-dev +version: 2.47.0-dev description: CERT C 2016 suites: codeql-suites license: MIT diff --git a/c/cert/test/qlpack.yml b/c/cert/test/qlpack.yml index 6920ec1771..91c2ea4a52 100644 --- a/c/cert/test/qlpack.yml +++ b/c/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards-tests -version: 2.46.0-dev +version: 2.47.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/common/src/qlpack.yml b/c/common/src/qlpack.yml index 13a994e0a3..d088be5639 100644 --- a/c/common/src/qlpack.yml +++ b/c/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards -version: 2.46.0-dev +version: 2.47.0-dev license: MIT dependencies: codeql/common-cpp-coding-standards: '*' diff --git a/c/common/test/qlpack.yml b/c/common/test/qlpack.yml index 09640c31c9..4688b3b1a9 100644 --- a/c/common/test/qlpack.yml +++ b/c/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards-tests -version: 2.46.0-dev +version: 2.47.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/misra/src/qlpack.yml b/c/misra/src/qlpack.yml index d37d64c88a..0607e7456f 100644 --- a/c/misra/src/qlpack.yml +++ b/c/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards -version: 2.46.0-dev +version: 2.47.0-dev description: MISRA C 2012 suites: codeql-suites license: MIT diff --git a/c/misra/test/qlpack.yml b/c/misra/test/qlpack.yml index a22391774f..823d705e51 100644 --- a/c/misra/test/qlpack.yml +++ b/c/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards-tests -version: 2.46.0-dev +version: 2.47.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/autosar/src/qlpack.yml b/cpp/autosar/src/qlpack.yml index dd095ff354..061fcf8df8 100644 --- a/cpp/autosar/src/qlpack.yml +++ b/cpp/autosar/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards -version: 2.46.0-dev +version: 2.47.0-dev description: AUTOSAR C++14 Guidelines R22-11, R21-11, R20-11, R19-11 and R19-03 suites: codeql-suites license: MIT diff --git a/cpp/autosar/test/qlpack.yml b/cpp/autosar/test/qlpack.yml index 7182f771d5..735f300df4 100644 --- a/cpp/autosar/test/qlpack.yml +++ b/cpp/autosar/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards-tests -version: 2.46.0-dev +version: 2.47.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/cert/src/qlpack.yml b/cpp/cert/src/qlpack.yml index 792575ad6e..74fe860570 100644 --- a/cpp/cert/src/qlpack.yml +++ b/cpp/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards -version: 2.46.0-dev +version: 2.47.0-dev description: CERT C++ 2016 suites: codeql-suites license: MIT diff --git a/cpp/cert/test/qlpack.yml b/cpp/cert/test/qlpack.yml index 7463027aaf..58d0db64f0 100644 --- a/cpp/cert/test/qlpack.yml +++ b/cpp/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards-tests -version: 2.46.0-dev +version: 2.47.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/common/src/qlpack.yml b/cpp/common/src/qlpack.yml index 1813fb7fe3..2454592ce7 100644 --- a/cpp/common/src/qlpack.yml +++ b/cpp/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards -version: 2.46.0-dev +version: 2.47.0-dev license: MIT dependencies: codeql/cpp-all: 2.1.1 diff --git a/cpp/common/test/qlpack.yml b/cpp/common/test/qlpack.yml index 8912a9c683..86ad39d46a 100644 --- a/cpp/common/test/qlpack.yml +++ b/cpp/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards-tests -version: 2.46.0-dev +version: 2.47.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/misra/src/qlpack.yml b/cpp/misra/src/qlpack.yml index 5cb9d79b87..999116b3e0 100644 --- a/cpp/misra/src/qlpack.yml +++ b/cpp/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards -version: 2.46.0-dev +version: 2.47.0-dev description: MISRA C++ 2023 default-suite: codeql-suites/misra-cpp-default.qls license: MIT diff --git a/cpp/misra/test/qlpack.yml b/cpp/misra/test/qlpack.yml index 69cd110473..94cad70436 100644 --- a/cpp/misra/test/qlpack.yml +++ b/cpp/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards-tests -version: 2.46.0-dev +version: 2.47.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/report/src/qlpack.yml b/cpp/report/src/qlpack.yml index c6f5f7052f..4814c3e99b 100644 --- a/cpp/report/src/qlpack.yml +++ b/cpp/report/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/report-cpp-coding-standards -version: 2.46.0-dev +version: 2.47.0-dev license: MIT dependencies: codeql/cpp-all: 2.1.1 diff --git a/docs/user_manual.md b/docs/user_manual.md index a758d3678c..7482942dc5 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -36,14 +36,14 @@ ## Release information -This user manual documents release `2.46.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). +This user manual documents release `2.47.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). The release page documents the release notes and contains the following artifacts part of the release: - `coding-standards-codeql-packs-2.37.0-dev.zip`: CodeQL packs that can be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `code-scanning-cpp-query-pack-2.46.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `supported_rules_list_2.46.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. -- `supported_rules_list_2.46.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. -- `user_manual_2.46.0-dev.md`: This user manual. +- `code-scanning-cpp-query-pack-2.47.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. +- `supported_rules_list_2.47.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. +- `supported_rules_list_2.47.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. +- `user_manual_2.47.0-dev.md`: This user manual. - `Source Code (zip)`: A zip archive containing the contents of https://github.com/github/codeql-coding-standards - `Source Code (tar.gz)`: A GZip compressed tar archive containing the contents of https://github.com/github/codeql-coding-standards - `checksums.txt`: A text file containing sha256 checksums for the aforementioned artifacts. @@ -670,7 +670,7 @@ This section describes known failure modes for "CodeQL Coding Standards" and des | | Out of space | Less output. Some files may be only be partially analyzed, or not analyzed at all. | Error reported on the command line. | Increase space. If it remains an issue report space consumption issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False positives | More output. Results are reported which are not violations of the guidelines. | All reported results must be reviewed. | Report false positive issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False negatives | Less output. Violations of the guidelines are not reported. | Other validation and verification processes during software development should be used to complement the analysis performed by CodeQL Coding Standards. | Report false negative issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.46.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | +| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.47.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | | | Incorrect deviation record specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation records with a reason. Ensure that all deviation records are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Incorrect deviation permit specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation permits with a reason. Ensure that all deviation permits are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Unapproved use of a deviation record | Less output. Results for guideline violations are not reported. | Validate that the deviation record use is approved by verifying the approved-by attribute of the deviation record specification. | Ensure that each raised deviation record is approved by an independent approver through an auditable process. | From 7049558f18fabd7a6f515e9ada1cef4aa43b02b3 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 6 Jun 2025 09:52:33 +0100 Subject: [PATCH 338/370] Change note --- change_notes/2025-06-06-same-source-performance.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 change_notes/2025-06-06-same-source-performance.md diff --git a/change_notes/2025-06-06-same-source-performance.md b/change_notes/2025-06-06-same-source-performance.md new file mode 100644 index 0000000000..e0dfc36dea --- /dev/null +++ b/change_notes/2025-06-06-same-source-performance.md @@ -0,0 +1,2 @@ + - `FIO39-C`, `FIO50-CPP`, `A27-0-3`, `RULE-30-0-2`: `IOFstreamMissingPositioning.ql`, `InterleavedInputOutputWithoutPosition.ql`, `InterleavedInputOutputWithoutFlush.ql`, `ReadsAndWritesOnStreamNotSeparatedByPositioning.ql`. + - Improved performance for codebases with large numbers of stream or file accesses. \ No newline at end of file From 6a5aa1f09699c6f1259adf4cc7c2b57bc087e007 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Fri, 13 Jun 2025 08:30:34 -0700 Subject: [PATCH 339/370] Fix compilation error --- .../codingstandards/cpp/types/Compatible.qll | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/types/Compatible.qll b/cpp/common/src/codingstandards/cpp/types/Compatible.qll index 3b77d5caf3..eb0e13101a 100644 --- a/cpp/common/src/codingstandards/cpp/types/Compatible.qll +++ b/cpp/common/src/codingstandards/cpp/types/Compatible.qll @@ -522,29 +522,3 @@ module FunctionDeclarationTypeEquivalence< .getType(), f2.getParameterDeclarationEntry(pragma[only_bind_into](i)).getType()) } } - -/** - * Convenience class to reduce the awkwardness of how `RoutineType` and `FunctionPointerIshType` - * don't have a common ancestor. - */ -private class FunctionType extends Type { - FunctionType() { this instanceof RoutineType or this instanceof FunctionPointerIshType } - - Type getReturnType() { - result = this.(RoutineType).getReturnType() or - result = this.(FunctionPointerIshType).getReturnType() - } - - Type getParameterType(int i) { - result = this.(RoutineType).getParameterType(i) or - result = this.(FunctionPointerIshType).getParameterType(i) - } -} - -private class LeafType extends Type { - LeafType() { - not this instanceof DerivedType and - not this instanceof FunctionType and - not this instanceof FunctionType - } -} From df1bd3a084718b0b554d613dd9f4a7614a95e4d9 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 15 Jun 2025 21:16:11 -0700 Subject: [PATCH 340/370] Add missing CERT-C query tags --- .../DoNotCompareFunctionPointersToConstantValues.ql | 6 ++++++ rule_packages/c/Expressions2.json | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql index d9622b03b9..fecd5450d0 100644 --- a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql +++ b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql @@ -9,6 +9,12 @@ * @tags external/cert/id/exp16-c * correctness * external/cert/obligation/recommendation + * external/cert/severity/low + * external/cert/likelihood/likely + * external/cert/remediation-cost/ + * external/cert/priority/p6 + * external/cert/level/l2 + * external/cert/obligation/recommendation */ import cpp diff --git a/rule_packages/c/Expressions2.json b/rule_packages/c/Expressions2.json index 7eaa2ff2ec..c9e2434f80 100644 --- a/rule_packages/c/Expressions2.json +++ b/rule_packages/c/Expressions2.json @@ -13,7 +13,13 @@ "severity": "error", "short_name": "DoNotCompareFunctionPointersToConstantValues", "tags": [ - "correctness" + "correctness", + "external/cert/obligation/recommendation", + "external/cert/severity/low", + "external/cert/likelihood/likely", + "external/cert/remediation-cost/", + "external/cert/priority/p6", + "external/cert/level/l2" ] } ], From bb7c913eea8391f110f6289db379fea0d96cbd4d Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 15 Jun 2025 21:36:45 -0700 Subject: [PATCH 341/370] Fix remediation cost --- .../EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql | 2 +- rule_packages/c/Expressions2.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql index fecd5450d0..bd2167c925 100644 --- a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql +++ b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql @@ -11,7 +11,7 @@ * external/cert/obligation/recommendation * external/cert/severity/low * external/cert/likelihood/likely - * external/cert/remediation-cost/ + * external/cert/remediation-cost/medium * external/cert/priority/p6 * external/cert/level/l2 * external/cert/obligation/recommendation diff --git a/rule_packages/c/Expressions2.json b/rule_packages/c/Expressions2.json index c9e2434f80..7c78e02fd9 100644 --- a/rule_packages/c/Expressions2.json +++ b/rule_packages/c/Expressions2.json @@ -17,7 +17,7 @@ "external/cert/obligation/recommendation", "external/cert/severity/low", "external/cert/likelihood/likely", - "external/cert/remediation-cost/", + "external/cert/remediation-cost/medium", "external/cert/priority/p6", "external/cert/level/l2" ] From fbf21bd3ae4b630f39b15e2c86866ac0db0772e2 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 15 Jun 2025 21:37:32 -0700 Subject: [PATCH 342/370] Undo accidental deletion of LeafType --- cpp/common/src/codingstandards/cpp/types/Compatible.qll | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cpp/common/src/codingstandards/cpp/types/Compatible.qll b/cpp/common/src/codingstandards/cpp/types/Compatible.qll index eb0e13101a..83983e1df4 100644 --- a/cpp/common/src/codingstandards/cpp/types/Compatible.qll +++ b/cpp/common/src/codingstandards/cpp/types/Compatible.qll @@ -522,3 +522,11 @@ module FunctionDeclarationTypeEquivalence< .getType(), f2.getParameterDeclarationEntry(pragma[only_bind_into](i)).getType()) } } + +private class LeafType extends Type { + LeafType() { + not this instanceof DerivedType and + not this instanceof FunctionType and + not this instanceof FunctionType + } +} From e4121eeb044129a2205162b2dc20326b72491ffe Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Sun, 15 Jun 2025 21:41:35 -0700 Subject: [PATCH 343/370] Remove cert c obligation tag --- .../EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql | 1 - rule_packages/c/Expressions2.json | 1 - 2 files changed, 2 deletions(-) diff --git a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql index bd2167c925..bdd4f1b375 100644 --- a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql +++ b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql @@ -8,7 +8,6 @@ * @problem.severity error * @tags external/cert/id/exp16-c * correctness - * external/cert/obligation/recommendation * external/cert/severity/low * external/cert/likelihood/likely * external/cert/remediation-cost/medium diff --git a/rule_packages/c/Expressions2.json b/rule_packages/c/Expressions2.json index 7c78e02fd9..d639ae2c34 100644 --- a/rule_packages/c/Expressions2.json +++ b/rule_packages/c/Expressions2.json @@ -14,7 +14,6 @@ "short_name": "DoNotCompareFunctionPointersToConstantValues", "tags": [ "correctness", - "external/cert/obligation/recommendation", "external/cert/severity/low", "external/cert/likelihood/likely", "external/cert/remediation-cost/medium", From 0fd3a88fa6ed3317d05243fdf6044fda7cb461ab Mon Sep 17 00:00:00 2001 From: knewbury01 Date: Mon, 16 Jun 2025 19:38:57 +0000 Subject: [PATCH 344/370] Bump version to 2.48.0-dev --- c/cert/src/qlpack.yml | 2 +- c/cert/test/qlpack.yml | 2 +- c/common/src/qlpack.yml | 2 +- c/common/test/qlpack.yml | 2 +- c/misra/src/qlpack.yml | 2 +- c/misra/test/qlpack.yml | 2 +- cpp/autosar/src/qlpack.yml | 2 +- cpp/autosar/test/qlpack.yml | 2 +- cpp/cert/src/qlpack.yml | 2 +- cpp/cert/test/qlpack.yml | 2 +- cpp/common/src/qlpack.yml | 2 +- cpp/common/test/qlpack.yml | 2 +- cpp/misra/src/qlpack.yml | 2 +- cpp/misra/test/qlpack.yml | 2 +- cpp/report/src/qlpack.yml | 2 +- docs/user_manual.md | 12 ++++++------ 16 files changed, 21 insertions(+), 21 deletions(-) diff --git a/c/cert/src/qlpack.yml b/c/cert/src/qlpack.yml index 26311dda18..d2ba0816a3 100644 --- a/c/cert/src/qlpack.yml +++ b/c/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards -version: 2.47.0-dev +version: 2.48.0-dev description: CERT C 2016 suites: codeql-suites license: MIT diff --git a/c/cert/test/qlpack.yml b/c/cert/test/qlpack.yml index 91c2ea4a52..98268c5636 100644 --- a/c/cert/test/qlpack.yml +++ b/c/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards-tests -version: 2.47.0-dev +version: 2.48.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/common/src/qlpack.yml b/c/common/src/qlpack.yml index d088be5639..4bbcb5c730 100644 --- a/c/common/src/qlpack.yml +++ b/c/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards -version: 2.47.0-dev +version: 2.48.0-dev license: MIT dependencies: codeql/common-cpp-coding-standards: '*' diff --git a/c/common/test/qlpack.yml b/c/common/test/qlpack.yml index 4688b3b1a9..ce8d7b3ce7 100644 --- a/c/common/test/qlpack.yml +++ b/c/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards-tests -version: 2.47.0-dev +version: 2.48.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/misra/src/qlpack.yml b/c/misra/src/qlpack.yml index 0607e7456f..02f9dceb48 100644 --- a/c/misra/src/qlpack.yml +++ b/c/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards -version: 2.47.0-dev +version: 2.48.0-dev description: MISRA C 2012 suites: codeql-suites license: MIT diff --git a/c/misra/test/qlpack.yml b/c/misra/test/qlpack.yml index 823d705e51..a720d41779 100644 --- a/c/misra/test/qlpack.yml +++ b/c/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards-tests -version: 2.47.0-dev +version: 2.48.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/autosar/src/qlpack.yml b/cpp/autosar/src/qlpack.yml index 061fcf8df8..65ec603f59 100644 --- a/cpp/autosar/src/qlpack.yml +++ b/cpp/autosar/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards -version: 2.47.0-dev +version: 2.48.0-dev description: AUTOSAR C++14 Guidelines R22-11, R21-11, R20-11, R19-11 and R19-03 suites: codeql-suites license: MIT diff --git a/cpp/autosar/test/qlpack.yml b/cpp/autosar/test/qlpack.yml index 735f300df4..f7b3f9ef3f 100644 --- a/cpp/autosar/test/qlpack.yml +++ b/cpp/autosar/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards-tests -version: 2.47.0-dev +version: 2.48.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/cert/src/qlpack.yml b/cpp/cert/src/qlpack.yml index 74fe860570..999faded05 100644 --- a/cpp/cert/src/qlpack.yml +++ b/cpp/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards -version: 2.47.0-dev +version: 2.48.0-dev description: CERT C++ 2016 suites: codeql-suites license: MIT diff --git a/cpp/cert/test/qlpack.yml b/cpp/cert/test/qlpack.yml index 58d0db64f0..b1c634258a 100644 --- a/cpp/cert/test/qlpack.yml +++ b/cpp/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards-tests -version: 2.47.0-dev +version: 2.48.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/common/src/qlpack.yml b/cpp/common/src/qlpack.yml index 2454592ce7..f7938fef71 100644 --- a/cpp/common/src/qlpack.yml +++ b/cpp/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards -version: 2.47.0-dev +version: 2.48.0-dev license: MIT dependencies: codeql/cpp-all: 2.1.1 diff --git a/cpp/common/test/qlpack.yml b/cpp/common/test/qlpack.yml index 86ad39d46a..84a581eda1 100644 --- a/cpp/common/test/qlpack.yml +++ b/cpp/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards-tests -version: 2.47.0-dev +version: 2.48.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/misra/src/qlpack.yml b/cpp/misra/src/qlpack.yml index 999116b3e0..f6a4e21428 100644 --- a/cpp/misra/src/qlpack.yml +++ b/cpp/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards -version: 2.47.0-dev +version: 2.48.0-dev description: MISRA C++ 2023 default-suite: codeql-suites/misra-cpp-default.qls license: MIT diff --git a/cpp/misra/test/qlpack.yml b/cpp/misra/test/qlpack.yml index 94cad70436..565c630696 100644 --- a/cpp/misra/test/qlpack.yml +++ b/cpp/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards-tests -version: 2.47.0-dev +version: 2.48.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/report/src/qlpack.yml b/cpp/report/src/qlpack.yml index 4814c3e99b..c8a6dd08f8 100644 --- a/cpp/report/src/qlpack.yml +++ b/cpp/report/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/report-cpp-coding-standards -version: 2.47.0-dev +version: 2.48.0-dev license: MIT dependencies: codeql/cpp-all: 2.1.1 diff --git a/docs/user_manual.md b/docs/user_manual.md index 7482942dc5..fae4623443 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -36,14 +36,14 @@ ## Release information -This user manual documents release `2.47.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). +This user manual documents release `2.48.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). The release page documents the release notes and contains the following artifacts part of the release: - `coding-standards-codeql-packs-2.37.0-dev.zip`: CodeQL packs that can be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `code-scanning-cpp-query-pack-2.47.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `supported_rules_list_2.47.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. -- `supported_rules_list_2.47.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. -- `user_manual_2.47.0-dev.md`: This user manual. +- `code-scanning-cpp-query-pack-2.48.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. +- `supported_rules_list_2.48.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. +- `supported_rules_list_2.48.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. +- `user_manual_2.48.0-dev.md`: This user manual. - `Source Code (zip)`: A zip archive containing the contents of https://github.com/github/codeql-coding-standards - `Source Code (tar.gz)`: A GZip compressed tar archive containing the contents of https://github.com/github/codeql-coding-standards - `checksums.txt`: A text file containing sha256 checksums for the aforementioned artifacts. @@ -670,7 +670,7 @@ This section describes known failure modes for "CodeQL Coding Standards" and des | | Out of space | Less output. Some files may be only be partially analyzed, or not analyzed at all. | Error reported on the command line. | Increase space. If it remains an issue report space consumption issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False positives | More output. Results are reported which are not violations of the guidelines. | All reported results must be reviewed. | Report false positive issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False negatives | Less output. Violations of the guidelines are not reported. | Other validation and verification processes during software development should be used to complement the analysis performed by CodeQL Coding Standards. | Report false negative issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.47.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | +| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.48.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | | | Incorrect deviation record specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation records with a reason. Ensure that all deviation records are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Incorrect deviation permit specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation permits with a reason. Ensure that all deviation permits are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Unapproved use of a deviation record | Less output. Results for guideline violations are not reported. | Validate that the deviation record use is approved by verifying the approved-by attribute of the deviation record specification. | Ensure that each raised deviation record is approved by an independent approver through an auditable process. | From 4006b7c5bd4e581865c8134dd4bfa40b210f83d0 Mon Sep 17 00:00:00 2001 From: lcartey <5377966+lcartey@users.noreply.github.com> Date: Thu, 19 Jun 2025 10:05:13 +0000 Subject: [PATCH 345/370] Upgrading `github/codeql` dependency to 2.20.7 --- c/cert/src/codeql-pack.lock.yml | 20 +++++++++---------- c/cert/src/qlpack.yml | 2 +- c/cert/test/codeql-pack.lock.yml | 20 +++++++++---------- c/common/src/codeql-pack.lock.yml | 20 +++++++++---------- c/common/src/qlpack.yml | 2 +- c/common/test/codeql-pack.lock.yml | 20 +++++++++---------- c/misra/src/codeql-pack.lock.yml | 20 +++++++++---------- c/misra/src/qlpack.yml | 2 +- c/misra/test/codeql-pack.lock.yml | 20 +++++++++---------- cpp/autosar/src/codeql-pack.lock.yml | 20 +++++++++---------- cpp/autosar/src/qlpack.yml | 2 +- cpp/autosar/test/codeql-pack.lock.yml | 20 +++++++++---------- cpp/cert/src/codeql-pack.lock.yml | 20 +++++++++---------- cpp/cert/src/qlpack.yml | 2 +- cpp/cert/test/codeql-pack.lock.yml | 20 +++++++++---------- cpp/common/src/codeql-pack.lock.yml | 20 +++++++++---------- cpp/common/src/qlpack.yml | 2 +- cpp/common/test/codeql-pack.lock.yml | 20 +++++++++---------- cpp/misra/src/codeql-pack.lock.yml | 20 +++++++++---------- cpp/misra/src/qlpack.yml | 2 +- cpp/misra/test/codeql-pack.lock.yml | 20 +++++++++---------- cpp/report/src/codeql-pack.lock.yml | 20 +++++++++---------- cpp/report/src/qlpack.yml | 2 +- .../queries/codeql-pack.lock.yml | 20 +++++++++---------- scripts/generate_modules/queries/qlpack.yml | 2 +- supported_codeql_configs.json | 6 +++--- 26 files changed, 172 insertions(+), 172 deletions(-) diff --git a/c/cert/src/codeql-pack.lock.yml b/c/cert/src/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/c/cert/src/codeql-pack.lock.yml +++ b/c/cert/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/c/cert/src/qlpack.yml b/c/cert/src/qlpack.yml index d2ba0816a3..732a855928 100644 --- a/c/cert/src/qlpack.yml +++ b/c/cert/src/qlpack.yml @@ -6,4 +6,4 @@ license: MIT default-suite-file: codeql-suites/cert-c-default.qls dependencies: codeql/common-c-coding-standards: '*' - codeql/cpp-all: 2.1.1 + codeql/cpp-all: 4.0.3 diff --git a/c/cert/test/codeql-pack.lock.yml b/c/cert/test/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/c/cert/test/codeql-pack.lock.yml +++ b/c/cert/test/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/c/common/src/codeql-pack.lock.yml b/c/common/src/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/c/common/src/codeql-pack.lock.yml +++ b/c/common/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/c/common/src/qlpack.yml b/c/common/src/qlpack.yml index 4bbcb5c730..f59d784995 100644 --- a/c/common/src/qlpack.yml +++ b/c/common/src/qlpack.yml @@ -3,4 +3,4 @@ version: 2.48.0-dev license: MIT dependencies: codeql/common-cpp-coding-standards: '*' - codeql/cpp-all: 2.1.1 + codeql/cpp-all: 4.0.3 diff --git a/c/common/test/codeql-pack.lock.yml b/c/common/test/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/c/common/test/codeql-pack.lock.yml +++ b/c/common/test/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/c/misra/src/codeql-pack.lock.yml b/c/misra/src/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/c/misra/src/codeql-pack.lock.yml +++ b/c/misra/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/c/misra/src/qlpack.yml b/c/misra/src/qlpack.yml index 02f9dceb48..a10b00fb51 100644 --- a/c/misra/src/qlpack.yml +++ b/c/misra/src/qlpack.yml @@ -6,4 +6,4 @@ license: MIT default-suite-file: codeql-suites/misra-c-default.qls dependencies: codeql/common-c-coding-standards: '*' - codeql/cpp-all: 2.1.1 + codeql/cpp-all: 4.0.3 diff --git a/c/misra/test/codeql-pack.lock.yml b/c/misra/test/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/c/misra/test/codeql-pack.lock.yml +++ b/c/misra/test/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/cpp/autosar/src/codeql-pack.lock.yml b/cpp/autosar/src/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/cpp/autosar/src/codeql-pack.lock.yml +++ b/cpp/autosar/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/cpp/autosar/src/qlpack.yml b/cpp/autosar/src/qlpack.yml index 65ec603f59..2352408016 100644 --- a/cpp/autosar/src/qlpack.yml +++ b/cpp/autosar/src/qlpack.yml @@ -5,4 +5,4 @@ suites: codeql-suites license: MIT dependencies: codeql/common-cpp-coding-standards: '*' - codeql/cpp-all: 2.1.1 + codeql/cpp-all: 4.0.3 diff --git a/cpp/autosar/test/codeql-pack.lock.yml b/cpp/autosar/test/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/cpp/autosar/test/codeql-pack.lock.yml +++ b/cpp/autosar/test/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/cpp/cert/src/codeql-pack.lock.yml b/cpp/cert/src/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/cpp/cert/src/codeql-pack.lock.yml +++ b/cpp/cert/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/cpp/cert/src/qlpack.yml b/cpp/cert/src/qlpack.yml index 999faded05..4c74256dc9 100644 --- a/cpp/cert/src/qlpack.yml +++ b/cpp/cert/src/qlpack.yml @@ -5,5 +5,5 @@ suites: codeql-suites license: MIT default-suite-file: codeql-suites/cert-cpp-default.qls dependencies: - codeql/cpp-all: 2.1.1 + codeql/cpp-all: 4.0.3 codeql/common-cpp-coding-standards: '*' diff --git a/cpp/cert/test/codeql-pack.lock.yml b/cpp/cert/test/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/cpp/cert/test/codeql-pack.lock.yml +++ b/cpp/cert/test/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/cpp/common/src/codeql-pack.lock.yml b/cpp/common/src/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/cpp/common/src/codeql-pack.lock.yml +++ b/cpp/common/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/cpp/common/src/qlpack.yml b/cpp/common/src/qlpack.yml index f7938fef71..c62e045962 100644 --- a/cpp/common/src/qlpack.yml +++ b/cpp/common/src/qlpack.yml @@ -2,6 +2,6 @@ name: codeql/common-cpp-coding-standards version: 2.48.0-dev license: MIT dependencies: - codeql/cpp-all: 2.1.1 + codeql/cpp-all: 4.0.3 dataExtensions: - ext/*.model.yml diff --git a/cpp/common/test/codeql-pack.lock.yml b/cpp/common/test/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/cpp/common/test/codeql-pack.lock.yml +++ b/cpp/common/test/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/cpp/misra/src/codeql-pack.lock.yml b/cpp/misra/src/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/cpp/misra/src/codeql-pack.lock.yml +++ b/cpp/misra/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/cpp/misra/src/qlpack.yml b/cpp/misra/src/qlpack.yml index f6a4e21428..2c9262fd10 100644 --- a/cpp/misra/src/qlpack.yml +++ b/cpp/misra/src/qlpack.yml @@ -5,4 +5,4 @@ default-suite: codeql-suites/misra-cpp-default.qls license: MIT dependencies: codeql/common-cpp-coding-standards: '*' - codeql/cpp-all: 2.1.1 + codeql/cpp-all: 4.0.3 diff --git a/cpp/misra/test/codeql-pack.lock.yml b/cpp/misra/test/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/cpp/misra/test/codeql-pack.lock.yml +++ b/cpp/misra/test/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/cpp/report/src/codeql-pack.lock.yml b/cpp/report/src/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/cpp/report/src/codeql-pack.lock.yml +++ b/cpp/report/src/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/cpp/report/src/qlpack.yml b/cpp/report/src/qlpack.yml index c8a6dd08f8..268820cc33 100644 --- a/cpp/report/src/qlpack.yml +++ b/cpp/report/src/qlpack.yml @@ -2,4 +2,4 @@ name: codeql/report-cpp-coding-standards version: 2.48.0-dev license: MIT dependencies: - codeql/cpp-all: 2.1.1 + codeql/cpp-all: 4.0.3 diff --git a/scripts/generate_modules/queries/codeql-pack.lock.yml b/scripts/generate_modules/queries/codeql-pack.lock.yml index ab9a39f9c1..a45ea8f438 100644 --- a/scripts/generate_modules/queries/codeql-pack.lock.yml +++ b/scripts/generate_modules/queries/codeql-pack.lock.yml @@ -2,23 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 2.1.1 + version: 4.0.3 codeql/dataflow: - version: 1.1.6 + version: 2.0.3 codeql/mad: - version: 1.0.12 + version: 1.0.19 codeql/rangeanalysis: - version: 1.0.12 + version: 1.0.19 codeql/ssa: - version: 1.0.12 + version: 1.0.19 codeql/tutorial: - version: 1.0.12 + version: 1.0.19 codeql/typeflow: - version: 1.0.12 + version: 1.0.19 codeql/typetracking: - version: 1.0.12 + version: 2.0.3 codeql/util: - version: 1.0.12 + version: 2.0.6 codeql/xml: - version: 1.0.12 + version: 1.0.19 compiled: false diff --git a/scripts/generate_modules/queries/qlpack.yml b/scripts/generate_modules/queries/qlpack.yml index d2c729dfb9..9aabee2562 100644 --- a/scripts/generate_modules/queries/qlpack.yml +++ b/scripts/generate_modules/queries/qlpack.yml @@ -2,4 +2,4 @@ name: codeql/standard-library-extraction-cpp-coding-standards version: 0.0.0 license: MIT dependencies: - codeql/cpp-all: 2.1.1 + codeql/cpp-all: 4.0.3 diff --git a/supported_codeql_configs.json b/supported_codeql_configs.json index 77534bd53d..9b89dd849e 100644 --- a/supported_codeql_configs.json +++ b/supported_codeql_configs.json @@ -1,9 +1,9 @@ { "supported_environment": [ { - "codeql_cli": "2.19.4", - "codeql_standard_library": "codeql-cli/v2.19.4", - "codeql_cli_bundle": "codeql-bundle-v2.19.4" + "codeql_cli": "2.20.7", + "codeql_standard_library": "codeql-cli/v2.20.7", + "codeql_cli_bundle": "codeql-bundle-v2.20.7" } ], "supported_language": [ From e655ed85787c8e301370c9a941f4d7d4f1279cad Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 19 Jun 2025 14:56:50 -0700 Subject: [PATCH 346/370] Exclude if (f) f() from EXP-16-C --- ...CompareFunctionPointersToConstantValues.ql | 31 ++-------- ...eFunctionPointersToConstantValues.expected | 34 ++++++----- c/cert/test/rules/EXP16-C/test.c | 42 ++++++++++++- .../cpp/exprs/FunctionExprs.qll | 59 +++++++++++++++++++ .../src/codingstandards/cpp/exprs/Guards.qll | 34 +++++++++++ 5 files changed, 158 insertions(+), 42 deletions(-) create mode 100644 cpp/common/src/codingstandards/cpp/exprs/FunctionExprs.qll create mode 100644 cpp/common/src/codingstandards/cpp/exprs/Guards.qll diff --git a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql index bdd4f1b375..e65d58a652 100644 --- a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql +++ b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql @@ -17,33 +17,11 @@ */ import cpp +import semmle.code.cpp.controlflow.IRGuards import codingstandards.c.cert import codingstandards.cpp.types.FunctionType -import semmle.code.cpp.controlflow.IRGuards - -class FunctionExpr extends Expr { - Element function; - string funcName; - - FunctionExpr() { - function = this.(FunctionAccess).getTarget() and - funcName = "Function " + function.(Function).getName() - or - this.(VariableAccess).getUnderlyingType() instanceof FunctionType and - function = this and - funcName = "Function pointer variable " + this.(VariableAccess).getTarget().getName() - or - this.getUnderlyingType() instanceof FunctionType and - not this instanceof FunctionAccess and - not this instanceof VariableAccess and - function = this and - funcName = "Expression with function pointer type" - } - - Element getFunction() { result = function } - - string getFuncName() { result = funcName } -} +import codingstandards.cpp.exprs.FunctionExprs +import codingstandards.cpp.exprs.Guards abstract class EffectivelyComparison extends Element { abstract string getExplanation(); @@ -85,6 +63,7 @@ where not isExcluded(comparison, Expressions2Package::doNotCompareFunctionPointersToConstantValuesQuery()) and funcExpr = comparison.getFunctionExpr() and + not exists(NullFunctionCallGuard nullGuard | nullGuard.getFunctionExpr() = funcExpr) and function = funcExpr.getFunction() and - funcName = funcExpr.getFuncName() + funcName = funcExpr.describe() select comparison, comparison.getExplanation(), function, funcName diff --git a/c/cert/test/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.expected b/c/cert/test/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.expected index a18f0d32f6..403d211651 100644 --- a/c/cert/test/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.expected +++ b/c/cert/test/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.expected @@ -1,16 +1,20 @@ -| test.c:17:7:17:13 | ... == ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Function f1 | -| test.c:20:7:20:12 | ... > ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Function f1 | -| test.c:29:7:29:13 | ... == ... | $@ compared to constant value. | test.c:29:7:29:8 | g1 | Function pointer variable g1 | -| test.c:32:7:32:16 | ... == ... | $@ compared to constant value. | test.c:32:7:32:8 | g2 | Function pointer variable g2 | -| test.c:35:7:35:15 | ... != ... | $@ compared to constant value. | test.c:35:7:35:8 | g1 | Function pointer variable g1 | -| test.c:38:7:38:8 | f1 | $@ undergoes implicit constant comparison. | test.c:3:5:3:6 | f1 | Function f1 | -| test.c:41:7:41:8 | g1 | $@ undergoes implicit constant comparison. | test.c:41:7:41:8 | g1 | Function pointer variable g1 | -| test.c:68:7:68:27 | ... == ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Function f1 | -| test.c:71:7:71:18 | ... == ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Function f1 | -| test.c:74:7:76:14 | ... == ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Function f1 | -| test.c:83:3:83:9 | ... == ... | $@ compared to constant value. | test.c:83:3:83:4 | l1 | Function pointer variable l1 | -| test.c:84:3:84:12 | ... == ... | $@ compared to constant value. | test.c:84:3:84:4 | l1 | Function pointer variable l1 | -| test.c:91:3:91:4 | g1 | $@ undergoes implicit constant comparison. | test.c:91:3:91:4 | g1 | Function pointer variable g1 | -| test.c:96:7:96:18 | ... == ... | $@ compared to constant value. | test.c:96:9:96:10 | fp | Function pointer variable fp | -| test.c:102:7:102:22 | ... == ... | $@ compared to constant value. | test.c:14:11:14:21 | get_handler | Function get_handler | +| test.c:17:7:17:13 | ... == ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Address of function f1 | +| test.c:20:7:20:12 | ... > ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Address of function f1 | +| test.c:29:7:29:13 | ... == ... | $@ compared to constant value. | test.c:4:8:4:9 | g1 | Function pointer variable g1 | +| test.c:32:7:32:16 | ... == ... | $@ compared to constant value. | test.c:5:7:5:8 | g2 | Function pointer variable g2 | +| test.c:35:7:35:15 | ... != ... | $@ compared to constant value. | test.c:4:8:4:9 | g1 | Function pointer variable g1 | +| test.c:38:7:38:8 | f1 | $@ undergoes implicit constant comparison. | test.c:3:5:3:6 | f1 | Address of function f1 | +| test.c:41:7:41:8 | g1 | $@ undergoes implicit constant comparison. | test.c:4:8:4:9 | g1 | Function pointer variable g1 | +| test.c:68:7:68:27 | ... == ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Address of function f1 | +| test.c:71:7:71:18 | ... == ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Address of function f1 | +| test.c:74:7:76:14 | ... == ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Address of function f1 | +| test.c:83:3:83:9 | ... == ... | $@ compared to constant value. | test.c:82:10:82:11 | l1 | Function pointer variable l1 | +| test.c:84:3:84:12 | ... == ... | $@ compared to constant value. | test.c:82:10:82:11 | l1 | Function pointer variable l1 | +| test.c:91:3:91:4 | g1 | $@ undergoes implicit constant comparison. | test.c:4:8:4:9 | g1 | Function pointer variable g1 | +| test.c:96:7:96:18 | ... == ... | $@ compared to constant value. | test.c:9:9:9:10 | fp | Function pointer variable fp | +| test.c:102:7:102:22 | ... == ... | $@ compared to constant value. | test.c:14:11:14:21 | get_handler | Address of function get_handler | | test.c:105:7:105:24 | ... == ... | $@ compared to constant value. | test.c:105:7:105:17 | call to get_handler | Expression with function pointer type | +| test.c:121:7:121:13 | ... != ... | $@ compared to constant value. | test.c:3:5:3:6 | f1 | Address of function f1 | +| test.c:133:7:133:13 | ... != ... | $@ compared to constant value. | test.c:4:8:4:9 | g1 | Function pointer variable g1 | +| test.c:139:7:139:13 | ... == ... | $@ compared to constant value. | test.c:4:8:4:9 | g1 | Function pointer variable g1 | +| test.c:149:8:149:9 | g1 | $@ undergoes implicit constant comparison. | test.c:4:8:4:9 | g1 | Function pointer variable g1 | diff --git a/c/cert/test/rules/EXP16-C/test.c b/c/cert/test/rules/EXP16-C/test.c index afc1b1b53e..16dfea9bc2 100644 --- a/c/cert/test/rules/EXP16-C/test.c +++ b/c/cert/test/rules/EXP16-C/test.c @@ -94,7 +94,7 @@ void f6(void) { void f7(void) { struct S s; if (s.fp == NULL) // NON-COMPLIANT - return; + f1(); if (s.fp() == NULL) // COMPLIANT return; @@ -110,4 +110,44 @@ void f7(void) { if (get_handler()() == 0) // COMPLIANT return; +} + +void f8(void) { + // Test instances of where the function pointer check is used to guard calls + // to that function. + + // Technically, this function may perhaps be set to NULL by the linker. But + // it is not a variable that should need to be null-checked at runtime. + if (f1 != 0) // NON-COMPLIANT + { + f1(); + } + + // Check guards a call, so it is compliant. + if (g1 != 0) // COMPLIANT + { + g1(); + } + + // Incorrect check, not compliant. + if (g1 != 0) // NON-COMPLIANT + { + f1(); + } + + // Incorrect check, not compliant. + if (g1 == 0) // NON-COMPLIANT + { + g1(); + } + + if (g1) // COMPLIANT + { + g1(); + } + + if (!g1) // NON-COMPLIANT + { + g1(); + } } \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exprs/FunctionExprs.qll b/cpp/common/src/codingstandards/cpp/exprs/FunctionExprs.qll new file mode 100644 index 0000000000..5c46fce075 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exprs/FunctionExprs.qll @@ -0,0 +1,59 @@ +import cpp +import codingstandards.cpp.types.FunctionType + +/** + * A class representing an expression that has a function pointer type. This can be a function + * access, a variable access, or any expression that has a function pointer type. + */ +abstract class FunctionExpr extends Expr { + /** Any element that could represent the function, for example, a variable or an expression. */ + abstract Element getFunction(); + + /** A name or string that describes the function. */ + abstract string describe(); + + /** Get calls of this function */ + abstract Call getACall(); +} + +/** + * A function access is an an expression of function type where we know the function. + */ +class SimpleFunctionAccess extends FunctionExpr, FunctionAccess { + override Element getFunction() { result = this.getTarget() } + + override string describe() { result = "Address of function " + this.getTarget().getName() } + + override FunctionCall getACall() { result.getTarget() = this.getTarget() } +} + +/** + * An access of a variable that has a function pointer type is also a function expression, for which + * we can track certain properties of the function. + */ +class FunctionVariableAccess extends FunctionExpr, VariableAccess { + FunctionVariableAccess() { this.getUnderlyingType() instanceof FunctionType } + + override Element getFunction() { result = this.getTarget() } + + override string describe() { result = "Function pointer variable " + this.getTarget().getName() } + + override ExprCall getACall() { result.getExpr().(VariableAccess).getTarget() = this.getTarget() } +} + +/** + * A function typed expression that is not a function access or a variable access. + */ +class FunctionTypedExpr extends FunctionExpr { + FunctionTypedExpr() { + this.getUnderlyingType() instanceof FunctionType and + not this instanceof FunctionAccess and + not this instanceof VariableAccess + } + + override Element getFunction() { result = this } + + override string describe() { result = "Expression with function pointer type" } + + override ExprCall getACall() { result.getExpr() = this } +} diff --git a/cpp/common/src/codingstandards/cpp/exprs/Guards.qll b/cpp/common/src/codingstandards/cpp/exprs/Guards.qll new file mode 100644 index 0000000000..73a35ccc6b --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exprs/Guards.qll @@ -0,0 +1,34 @@ +import cpp +import codeql.util.Boolean +import semmle.code.cpp.controlflow.Guards +import codingstandards.cpp.exprs.FunctionExprs + +/** + * A guard of the form: `if (funcPtr) funcPtr();`, e.g., a null check on a function before calling + * that function. + * + * Note this does not consider the above to be a null function call guard if `funcPtr` is a + * function name, as that could only be null via unusual linkage steps, and is not expected to be + * an intentional null check. + */ +class NullFunctionCallGuard extends GuardCondition { + FunctionExpr expr; + + NullFunctionCallGuard() { + exists(BasicBlock block, Call guardedCall | + ( + // Handles 'if (funcPtr != NULL)`: + this.ensuresEq(expr, 0, block, false) + or + // Handles `if (funcPtr)` in C where no implicit conversion to bool exists: + expr = this and + expr.getFunction() instanceof Variable and + this.controls(block, true) + ) and + guardedCall = expr.getACall() and + block.contains(guardedCall) + ) + } + + FunctionExpr getFunctionExpr() { result = expr } +} From 68355b0106b8349db717c0bd2a7c7b1963424b6f Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 8 Jul 2025 22:02:53 +0200 Subject: [PATCH 347/370] Make dataflow imports private in libraries and remove unused imports --- .../VariableLengthArraySizeNotInValidRange.ql | 1 + .../DoNotRelyOnIndeterminateValuesOfErrno.ql | 1 + .../DetectAndHandleStandardLibraryErrors.ql | 1 + .../ResetStringsOnFgetsOrFgetwsFailure.ql | 1 + ...riableLengthArraySizeNotInValidRange.expected | 4 ++-- ...oNotRelyOnIndeterminateValuesOfErrno.expected | 8 ++++---- ...DetectAndHandleStandardLibraryErrors.expected | 2 +- .../ResetStringsOnFgetsOrFgetwsFailure.expected | 6 +++--- c/common/src/codingstandards/c/OutOfBounds.qll | 2 +- c/common/src/codingstandards/c/Signal.qll | 2 +- .../InvalidOperationOnUnlockedMutex.ql | 1 - ...fShallBeComparedWithUnmodifiedReturnValues.ql | 1 + ...BeComparedWithUnmodifiedReturnValues.expected | 16 ++++++++-------- .../InOutParametersDeclaredAsTNotModified.ql | 1 + ...nOutParametersDeclaredAsTNotModified.expected | 4 ++-- .../rules/CTR53-CPP/UseValidIteratorRanges.ql | 1 + .../DoNotUseAnAdditiveOperatorOnAnIterator.ql | 1 + .../CTR53-CPP/UseValidIteratorRanges.expected | 12 ++++++------ ...NotUseAnAdditiveOperatorOnAnIterator.expected | 14 +++++++------- .../src/codingstandards/cpp/AccessPath.qll | 2 +- .../src/codingstandards/cpp/Allocations.qll | 2 +- .../src/codingstandards/cpp/Concurrency.qll | 1 - .../src/codingstandards/cpp/ConstHelpers.qll | 2 +- cpp/common/src/codingstandards/cpp/Expr.qll | 1 + .../codingstandards/cpp/FgetsErrorManagement.qll | 2 +- cpp/common/src/codingstandards/cpp/Iterators.qll | 8 +++++--- cpp/common/src/codingstandards/cpp/Overflow.qll | 2 +- .../src/codingstandards/cpp/ReadErrorsAndEOF.qll | 2 +- .../src/codingstandards/cpp/SideEffect.qll | 2 +- .../src/codingstandards/cpp/SmartPointers.qll | 2 +- .../cpp/concurrency/LockingOperation.qll | 2 +- .../InvalidatedEnvStringPointersWarn.qll | 1 - ...redicateFunctionObjectsShouldNotBeMutable.qll | 1 + .../cpp/standardlibrary/FileStreams.qll | 4 ++-- 34 files changed, 61 insertions(+), 52 deletions(-) diff --git a/c/cert/src/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.ql b/c/cert/src/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.ql index 85fc7b9022..1356777e5f 100644 --- a/c/cert/src/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.ql +++ b/c/cert/src/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.ql @@ -20,6 +20,7 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.Overflow +import semmle.code.cpp.dataflow.TaintTracking /** * Gets the maximum size (in bytes) a variable-length array diff --git a/c/cert/src/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.ql b/c/cert/src/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.ql index c7dfd58c6b..146d0cb30f 100644 --- a/c/cert/src/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.ql +++ b/c/cert/src/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.ql @@ -20,6 +20,7 @@ import codingstandards.c.cert import codingstandards.c.Errno import codingstandards.c.Signal import semmle.code.cpp.controlflow.Guards +import semmle.code.cpp.dataflow.DataFlow /** * A check on `signal` call return value diff --git a/c/cert/src/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.ql b/c/cert/src/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.ql index 01e7b83d13..5e473b226e 100644 --- a/c/cert/src/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.ql +++ b/c/cert/src/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.ql @@ -20,6 +20,7 @@ import cpp import codingstandards.c.cert import semmle.code.cpp.commons.NULL import codingstandards.cpp.ReadErrorsAndEOF +import semmle.code.cpp.dataflow.DataFlow ComparisonOperation getAValidComparison(string spec) { spec = "=0" and result.(EqualityOperation).getAnOperand().getValue() = "0" diff --git a/c/cert/src/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.ql b/c/cert/src/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.ql index b54436c835..9b0882ac66 100644 --- a/c/cert/src/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.ql +++ b/c/cert/src/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.ql @@ -21,6 +21,7 @@ import cpp import codingstandards.cpp.FgetsErrorManagement import codingstandards.cpp.Dereferenced import codingstandards.c.cert +import semmle.code.cpp.dataflow.DataFlow /* * Models calls to `memcpy` `strcpy` `strncpy` and their wrappers diff --git a/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected b/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected index 0b400c5256..1617571bbe 100644 --- a/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected +++ b/c/cert/test/rules/ARR32-C/VariableLengthArraySizeNotInValidRange.expected @@ -1,5 +1,5 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:109,11-19) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:92,5-18) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:110,11-19) +WARNING: module 'TaintTracking' has been deprecated and may be removed in future (VariableLengthArraySizeNotInValidRange.ql:93,5-18) | test.c:14:8:14:8 | VLA declaration | Variable-length array dimension size may be in an invalid range. | | test.c:15:8:15:8 | VLA declaration | Variable-length array dimension size may be in an invalid range. | | test.c:16:8:16:8 | VLA declaration | Variable-length array dimension size may be in an invalid range. | diff --git a/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected b/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected index 1f313cb90d..b79a17ca35 100644 --- a/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected +++ b/c/cert/test/rules/ERR32-C/DoNotRelyOnIndeterminateValuesOfErrno.expected @@ -1,7 +1,7 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:55,7-15) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:55,27-35) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:56,9-17) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:59,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:56,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:56,27-35) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:57,9-17) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotRelyOnIndeterminateValuesOfErrno.ql:60,9-17) | test.c:12:5:12:10 | call to perror | `errno` has indeterminate value after this $@. | test.c:10:21:10:26 | call to signal | call to signal | | test.c:30:5:30:10 | call to perror | `errno` has indeterminate value after this $@. | test.c:26:21:26:26 | call to signal | call to signal | | test.c:49:5:49:10 | call to perror | `errno` has indeterminate value after this $@. | test.c:45:21:45:26 | call to signal | call to signal | diff --git a/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected b/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected index b13f34522c..f4006c013e 100644 --- a/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected +++ b/c/cert/test/rules/ERR33-C/DetectAndHandleStandardLibraryErrors.expected @@ -1,4 +1,4 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleStandardLibraryErrors.ql:458,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DetectAndHandleStandardLibraryErrors.ql:459,5-13) | test.c:18:3:18:11 | call to setlocale | Missing error detection for the call to function `setlocale`. | | test.c:24:23:24:31 | call to setlocale | Missing error detection for the call to function `setlocale`. | | test.c:29:22:29:27 | call to calloc | Missing error detection for the call to function `calloc`. | diff --git a/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected b/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected index 7d3cbe355b..52cb85e5c4 100644 --- a/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected +++ b/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected @@ -1,6 +1,6 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:47,11-19) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:47,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:48,13-21) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:48,11-19) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:48,31-39) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:49,13-21) | test.c:20:10:20:12 | buf | The buffer is not reset before being referenced following a failed $@. | test.c:15:7:15:11 | call to fgets | call to fgets | | test.c:57:10:57:12 | buf | The buffer is not reset before being referenced following a failed $@. | test.c:52:7:52:11 | call to fgets | call to fgets | | test.c:66:18:66:20 | buf | The buffer is not reset before being referenced following a failed $@. | test.c:61:7:61:11 | call to fgets | call to fgets | diff --git a/c/common/src/codingstandards/c/OutOfBounds.qll b/c/common/src/codingstandards/c/OutOfBounds.qll index bb7d1bd124..1f1680f56c 100644 --- a/c/common/src/codingstandards/c/OutOfBounds.qll +++ b/c/common/src/codingstandards/c/OutOfBounds.qll @@ -11,7 +11,7 @@ import codingstandards.cpp.Allocations import codingstandards.cpp.Overflow import codingstandards.cpp.PossiblyUnsafeStringOperation import codingstandards.cpp.SimpleRangeAnalysisCustomizations -import semmle.code.cpp.dataflow.DataFlow +private import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.valuenumbering.GlobalValueNumbering module OOB { diff --git a/c/common/src/codingstandards/c/Signal.qll b/c/common/src/codingstandards/c/Signal.qll index 95b27e2898..2a570b654f 100644 --- a/c/common/src/codingstandards/c/Signal.qll +++ b/c/common/src/codingstandards/c/Signal.qll @@ -1,5 +1,5 @@ import cpp -import semmle.code.cpp.dataflow.DataFlow +private import semmle.code.cpp.dataflow.DataFlow /** * A signal corresponding to a computational exception diff --git a/c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql b/c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql index 252b4a7d9f..d85183a831 100644 --- a/c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql +++ b/c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql @@ -18,7 +18,6 @@ import codingstandards.c.misra import codingstandards.c.SubObjects import codingstandards.cpp.Concurrency import codingstandards.cpp.dominance.BehavioralSet -import semmle.code.cpp.dataflow.new.DataFlow::DataFlow as NewDF /* A call to mtx_unlock() or cnd_wait() or cnd_timedwait(), which require a locked mutex */ class RequiresLockOperation extends FunctionCall { diff --git a/c/misra/src/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.ql b/c/misra/src/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.ql index a29ee7c898..1da495ca28 100644 --- a/c/misra/src/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.ql +++ b/c/misra/src/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.ql @@ -15,6 +15,7 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.ReadErrorsAndEOF +import semmle.code.cpp.dataflow.DataFlow /** * The getchar() return value propagates directly to a check against EOF macro diff --git a/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected b/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected index 83a10a46fb..210a3a9218 100644 --- a/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected +++ b/c/misra/test/rules/RULE-22-7/EofShallBeComparedWithUnmodifiedReturnValues.expected @@ -1,10 +1,10 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:23,28-36) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:24,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:28,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:37,23-31) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:42,17-25) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:51,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:59,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:59,46-54) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:24,28-36) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:25,22-30) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:29,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:38,23-31) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:43,17-25) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:52,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:60,20-28) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (EofShallBeComparedWithUnmodifiedReturnValues.ql:60,46-54) | test.c:6:7:6:20 | ... != ... | The check is not reliable as the type of the return value of $@ is converted. | test.c:5:14:5:20 | call to getchar | call to getchar | | test.c:13:7:13:15 | ... != ... | The check is not reliable as the type of the return value of $@ is converted. | test.c:12:14:12:20 | call to getchar | call to getchar | diff --git a/cpp/autosar/src/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.ql b/cpp/autosar/src/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.ql index 1509ee968a..3b30eb676a 100644 --- a/cpp/autosar/src/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.ql +++ b/cpp/autosar/src/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.ql @@ -21,6 +21,7 @@ import codingstandards.cpp.autosar import codingstandards.cpp.FunctionParameter import codingstandards.cpp.ConstHelpers import codingstandards.cpp.Operator +import semmle.code.cpp.dataflow.DataFlow /** * Non-const T& `Parameter`s to `Function`s diff --git a/cpp/autosar/test/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.expected b/cpp/autosar/test/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.expected index bafa98112f..25fe77d9a5 100644 --- a/cpp/autosar/test/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.expected +++ b/cpp/autosar/test/rules/A8-4-9/InOutParametersDeclaredAsTNotModified.expected @@ -1,5 +1,5 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (InOutParametersDeclaredAsTNotModified.ql:49,7-15) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (InOutParametersDeclaredAsTNotModified.ql:63,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (InOutParametersDeclaredAsTNotModified.ql:50,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (InOutParametersDeclaredAsTNotModified.ql:64,7-15) | test.cpp:4:13:4:13 | i | In-out parameter i that is not written to. | | test.cpp:7:22:7:24 | str | In-out parameter str that is not read from. | | test.cpp:18:14:18:14 | i | In-out parameter i that is not read from. | diff --git a/cpp/cert/src/rules/CTR53-CPP/UseValidIteratorRanges.ql b/cpp/cert/src/rules/CTR53-CPP/UseValidIteratorRanges.ql index 3702cbcd6e..1512a7fd99 100644 --- a/cpp/cert/src/rules/CTR53-CPP/UseValidIteratorRanges.ql +++ b/cpp/cert/src/rules/CTR53-CPP/UseValidIteratorRanges.ql @@ -19,6 +19,7 @@ import cpp import codingstandards.cpp.cert import codingstandards.cpp.Iterators +import semmle.code.cpp.dataflow.DataFlow predicate startEndArgumentsDoNotPointToTheSameContainer( IteratorRangeFunctionCall fc, Expr arg, string reason diff --git a/cpp/cert/src/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.ql b/cpp/cert/src/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.ql index 3f2de63246..c6ea2c4518 100644 --- a/cpp/cert/src/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.ql +++ b/cpp/cert/src/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.ql @@ -20,6 +20,7 @@ import cpp import codingstandards.cpp.cert import codingstandards.cpp.Iterators import semmle.code.cpp.controlflow.Dominance +import semmle.code.cpp.dataflow.DataFlow /** * Models a call to an iterator's `operator+` diff --git a/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected b/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected index 1953314c2f..d25d23185a 100644 --- a/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected +++ b/cpp/cert/test/rules/CTR53-CPP/UseValidIteratorRanges.expected @@ -1,9 +1,9 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:28,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:28,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:29,7-15) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:35,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:35,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:36,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:29,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:29,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:30,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:36,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:36,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (UseValidIteratorRanges.ql:37,7-15) | test.cpp:7:3:7:15 | call to for_each | The $@ of iterator range function does not point to the end of an iterator. | test.cpp:7:28:7:32 | call to begin | argument | | test.cpp:7:3:7:15 | call to for_each | The $@ of iterator range function does not point to the start of an iterator. | test.cpp:7:19:7:21 | call to end | argument | | test.cpp:8:3:8:15 | call to for_each | The $@ of iterator range function does not point to the end of an iterator. | test.cpp:8:30:8:34 | call to begin | argument | diff --git a/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected b/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected index 48da16d208..db3b7358d8 100644 --- a/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected +++ b/cpp/cert/test/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator.expected @@ -1,12 +1,12 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:43,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:43,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:43,51-59) WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:44,5-13) WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:44,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:44,52-60) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:79,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:79,25-33) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:80,7-15) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:44,51-59) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:45,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:45,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:45,52-60) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:80,5-13) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:80,25-33) +WARNING: module 'DataFlow' has been deprecated and may be removed in future (DoNotUseAnAdditiveOperatorOnAnIterator.ql:81,7-15) | test.cpp:8:7:8:7 | i | Increment of iterator may overflow since its bounds are not checked. | | test.cpp:9:9:9:9 | i | Increment of iterator may overflow since its bounds are not checked. | | test.cpp:10:9:10:9 | i | Increment of iterator may overflow since its bounds are not checked. | diff --git a/cpp/common/src/codingstandards/cpp/AccessPath.qll b/cpp/common/src/codingstandards/cpp/AccessPath.qll index ff7601ed4b..3af462e1ec 100644 --- a/cpp/common/src/codingstandards/cpp/AccessPath.qll +++ b/cpp/common/src/codingstandards/cpp/AccessPath.qll @@ -1,5 +1,5 @@ import cpp -import semmle.code.cpp.dataflow.DataFlow +private import semmle.code.cpp.dataflow.DataFlow newtype TFieldQualifier = ExplicitQualifier(VariableAccess v) or diff --git a/cpp/common/src/codingstandards/cpp/Allocations.qll b/cpp/common/src/codingstandards/cpp/Allocations.qll index db47b0b028..decdfe9fc4 100644 --- a/cpp/common/src/codingstandards/cpp/Allocations.qll +++ b/cpp/common/src/codingstandards/cpp/Allocations.qll @@ -7,7 +7,7 @@ import cpp import semmle.code.cpp.controlflow.SSA -import semmle.code.cpp.dataflow.DataFlow +private import semmle.code.cpp.dataflow.DataFlow /** * Holds if `alloc` is a use of `malloc` or `new`. `kind` is diff --git a/cpp/common/src/codingstandards/cpp/Concurrency.qll b/cpp/common/src/codingstandards/cpp/Concurrency.qll index 0e2afb8ece..3f7e5c1af9 100644 --- a/cpp/common/src/codingstandards/cpp/Concurrency.qll +++ b/cpp/common/src/codingstandards/cpp/Concurrency.qll @@ -1,5 +1,4 @@ import cpp -import semmle.code.cpp.dataflow.TaintTracking import codingstandards.cpp.concurrency.Atomic import codingstandards.cpp.concurrency.CConditionOperation import codingstandards.cpp.concurrency.ControlFlow diff --git a/cpp/common/src/codingstandards/cpp/ConstHelpers.qll b/cpp/common/src/codingstandards/cpp/ConstHelpers.qll index a7457dc845..a3d12fd127 100644 --- a/cpp/common/src/codingstandards/cpp/ConstHelpers.qll +++ b/cpp/common/src/codingstandards/cpp/ConstHelpers.qll @@ -4,7 +4,7 @@ import cpp import codingstandards.cpp.SideEffect -import semmle.code.cpp.dataflow.DataFlow +private import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.FunctionParameter /** A variable that can be modified (both the pointer and object pointed to if pointer type) */ diff --git a/cpp/common/src/codingstandards/cpp/Expr.qll b/cpp/common/src/codingstandards/cpp/Expr.qll index 0b650ae41b..54ba86c5b7 100644 --- a/cpp/common/src/codingstandards/cpp/Expr.qll +++ b/cpp/common/src/codingstandards/cpp/Expr.qll @@ -1,4 +1,5 @@ import cpp +private import semmle.code.cpp.dataflow.DataFlow private import semmle.code.cpp.valuenumbering.GlobalValueNumbering import codingstandards.cpp.AccessPath diff --git a/cpp/common/src/codingstandards/cpp/FgetsErrorManagement.qll b/cpp/common/src/codingstandards/cpp/FgetsErrorManagement.qll index 4f99b02e2e..026fd93045 100644 --- a/cpp/common/src/codingstandards/cpp/FgetsErrorManagement.qll +++ b/cpp/common/src/codingstandards/cpp/FgetsErrorManagement.qll @@ -4,7 +4,7 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow +private import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.controlflow.Guards /* diff --git a/cpp/common/src/codingstandards/cpp/Iterators.qll b/cpp/common/src/codingstandards/cpp/Iterators.qll index 76751aa87b..c8c217aea4 100644 --- a/cpp/common/src/codingstandards/cpp/Iterators.qll +++ b/cpp/common/src/codingstandards/cpp/Iterators.qll @@ -3,8 +3,8 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow -import semmle.code.cpp.dataflow.TaintTracking +private import semmle.code.cpp.dataflow.DataFlow +private import semmle.code.cpp.dataflow.TaintTracking import codingstandards.cpp.StdNamespace import codingstandards.cpp.rules.containeraccesswithoutrangecheck.ContainerAccessWithoutRangeCheck as ContainerAccessWithoutRangeCheck import semmle.code.cpp.controlflow.Guards @@ -16,7 +16,9 @@ abstract class ContainerAccess extends VariableAccess { } pragma[noinline, nomagic] -predicate localTaint(DataFlow::Node n1, DataFlow::Node n2) { TaintTracking::localTaint(n1, n2) } +private predicate localTaint(DataFlow::Node n1, DataFlow::Node n2) { + TaintTracking::localTaint(n1, n2) +} // define this as anything with dataflow FROM the vector class ContainerPointerOrReferenceAccess extends ContainerAccess { diff --git a/cpp/common/src/codingstandards/cpp/Overflow.qll b/cpp/common/src/codingstandards/cpp/Overflow.qll index 28a5c0d9db..b81147d6bf 100644 --- a/cpp/common/src/codingstandards/cpp/Overflow.qll +++ b/cpp/common/src/codingstandards/cpp/Overflow.qll @@ -6,7 +6,7 @@ import cpp import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis import SimpleRangeAnalysisCustomizations import semmle.code.cpp.controlflow.Guards -import semmle.code.cpp.dataflow.TaintTracking +private import semmle.code.cpp.dataflow.TaintTracking import semmle.code.cpp.valuenumbering.GlobalValueNumbering import codingstandards.cpp.Expr import codingstandards.cpp.UndefinedBehavior diff --git a/cpp/common/src/codingstandards/cpp/ReadErrorsAndEOF.qll b/cpp/common/src/codingstandards/cpp/ReadErrorsAndEOF.qll index c3c433d20d..94e7f89796 100644 --- a/cpp/common/src/codingstandards/cpp/ReadErrorsAndEOF.qll +++ b/cpp/common/src/codingstandards/cpp/ReadErrorsAndEOF.qll @@ -1,5 +1,5 @@ import cpp -import semmle.code.cpp.dataflow.DataFlow +private import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.standardlibrary.FileAccess /** diff --git a/cpp/common/src/codingstandards/cpp/SideEffect.qll b/cpp/common/src/codingstandards/cpp/SideEffect.qll index d83647ce76..883004e513 100644 --- a/cpp/common/src/codingstandards/cpp/SideEffect.qll +++ b/cpp/common/src/codingstandards/cpp/SideEffect.qll @@ -1,7 +1,7 @@ /** A module to reason about side effects. */ import cpp -import semmle.code.cpp.dataflow.DataFlow +private import semmle.code.cpp.dataflow.DataFlow private import exceptions.ExceptionFlow private import codingstandards.cpp.Expr private import codingstandards.cpp.Variable diff --git a/cpp/common/src/codingstandards/cpp/SmartPointers.qll b/cpp/common/src/codingstandards/cpp/SmartPointers.qll index 0f01d886be..a643b0bc2b 100644 --- a/cpp/common/src/codingstandards/cpp/SmartPointers.qll +++ b/cpp/common/src/codingstandards/cpp/SmartPointers.qll @@ -1,5 +1,5 @@ import cpp -import semmle.code.cpp.dataflow.DataFlow +private import semmle.code.cpp.dataflow.DataFlow // Local cached version of localExprFlow to avoid bad magic cached diff --git a/cpp/common/src/codingstandards/cpp/concurrency/LockingOperation.qll b/cpp/common/src/codingstandards/cpp/concurrency/LockingOperation.qll index 95404b114a..0aab11a269 100644 --- a/cpp/common/src/codingstandards/cpp/concurrency/LockingOperation.qll +++ b/cpp/common/src/codingstandards/cpp/concurrency/LockingOperation.qll @@ -1,5 +1,5 @@ import cpp -import semmle.code.cpp.dataflow.TaintTracking +private import semmle.code.cpp.dataflow.TaintTracking abstract class LockingOperation extends FunctionCall { /** diff --git a/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointerswarn/InvalidatedEnvStringPointersWarn.qll b/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointerswarn/InvalidatedEnvStringPointersWarn.qll index 8bc1b0c920..759bc08deb 100644 --- a/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointerswarn/InvalidatedEnvStringPointersWarn.qll +++ b/cpp/common/src/codingstandards/cpp/rules/invalidatedenvstringpointerswarn/InvalidatedEnvStringPointersWarn.qll @@ -6,7 +6,6 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import semmle.code.cpp.dataflow.DataFlow import codingstandards.cpp.rules.invalidatedenvstringpointers.InvalidatedEnvStringPointers as EnvString abstract class InvalidatedEnvStringPointersWarnSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/predicatefunctionobjectsshouldnotbemutable/PredicateFunctionObjectsShouldNotBeMutable.qll b/cpp/common/src/codingstandards/cpp/rules/predicatefunctionobjectsshouldnotbemutable/PredicateFunctionObjectsShouldNotBeMutable.qll index bf47c1f649..ba2f6ed82a 100644 --- a/cpp/common/src/codingstandards/cpp/rules/predicatefunctionobjectsshouldnotbemutable/PredicateFunctionObjectsShouldNotBeMutable.qll +++ b/cpp/common/src/codingstandards/cpp/rules/predicatefunctionobjectsshouldnotbemutable/PredicateFunctionObjectsShouldNotBeMutable.qll @@ -9,6 +9,7 @@ import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import codingstandards.cpp.SideEffect import codingstandards.cpp.sideeffect.DefaultEffects +import semmle.code.cpp.dataflow.DataFlow abstract class PredicateFunctionObjectsShouldNotBeMutableSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/standardlibrary/FileStreams.qll b/cpp/common/src/codingstandards/cpp/standardlibrary/FileStreams.qll index 709e80dc1a..99eec1f5e0 100644 --- a/cpp/common/src/codingstandards/cpp/standardlibrary/FileStreams.qll +++ b/cpp/common/src/codingstandards/cpp/standardlibrary/FileStreams.qll @@ -10,8 +10,8 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow -import semmle.code.cpp.dataflow.TaintTracking +private import semmle.code.cpp.dataflow.DataFlow +private import semmle.code.cpp.dataflow.TaintTracking private import codingstandards.cpp.Operator /** From 9fa5cb207fd9a5c21fc45727402dc7d1b41ddc2c Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Thu, 10 Jul 2025 14:25:31 -0700 Subject: [PATCH 348/370] Add more test cases - 1. Assigning a char to another char - 1-1. Assigning a char to a char variable - 1-2. Assigning a char to a char member - 1-3. Assigning a char to a char through a pointer - 2. Passing a char argument to a char parameter - 2-1. Passing char argument to a char parameter of a regular function - 2-2. Passing char argument to a char parameter through a template - 2-3. Passing a char argument to a char parameter through a template --- cpp/autosar/test/rules/M5-0-12/test.cpp | 363 +++++++++++++++++++++++- 1 file changed, 353 insertions(+), 10 deletions(-) diff --git a/cpp/autosar/test/rules/M5-0-12/test.cpp b/cpp/autosar/test/rules/M5-0-12/test.cpp index 453c37bf1e..355c9cbc4f 100644 --- a/cpp/autosar/test/rules/M5-0-12/test.cpp +++ b/cpp/autosar/test/rules/M5-0-12/test.cpp @@ -1,16 +1,359 @@ #include -void f1() { - unsigned char a1 = 'c'; // NON_COMPLIANT - unsigned char a2 = 10; - signed char a3 = 'c'; // NON_COMPLIANT - signed char a4 = 10; +template class C1 { +public: + C1() : x(y) {} - std::int8_t a5 = 'c'; // NON_COMPLIANT - std::int8_t a6 = 10; +private: + unsigned char x; +}; - std::uint8_t a7 = 'c'; // NON_COMPLIANT - std::uint8_t a8 = 10; +template class C2 { +public: + C2() : x(y) {} - char a9 = 'c'; +private: + signed char x; +}; + +template class C3 { +public: + C3() : x(y) {} + +private: + unsigned char x; +}; + +template class C4 { +public: + C4() : x(y) {} + +private: + signed char x; +}; + +/* Twin templates for std::uint8_t and std::int8_t */ +template class C9 { +public: + C9() : x(y) {} + +private: + std::uint8_t x; +}; + +template class C10 { +public: + C10() : x(y) {} + +private: + std::int8_t x; +}; + +template class C11 { +public: + C11() : x(y) {} + +private: + std::uint8_t x; +}; + +template class C12 { +public: + C12() : x(y) {} + +private: + std::int8_t x; +}; + +void f1(unsigned char x) {} +void f2(signed char x) {} +void f3(unsigned char x) {} +void f4(signed char x) {} + +/* Twin functions for std::uint8_t and std::int8_t */ +void f9(std::uint8_t x) {} +void f10(std::int8_t x) {} +void f11(std::uint8_t x) {} +void f12(std::int8_t x) {} + +template void f5(T x) { unsigned char y = x; } +template void f6(T x) { signed char y = x; } +template void f7(T x) { signed char y = x; } +template void f8(T x) { signed char y = x; } + +/* Twin template functions for std::uint8_t and std::int8_t */ +template void f13(T x) { std::uint8_t y = x; } +template void f14(T x) { std::int8_t y = x; } +template void f15(T x) { std::int8_t y = x; } +template void f16(T x) { std::int8_t y = x; } + +template class C5 { +public: + C5(T y) : x(y) {} + +private: + unsigned char x; +}; + +template class C6 { +public: + C6(T y) : x(y) {} + +private: + signed char x; +}; + +template class C7 { +public: + C7(T y) : x(y) {} + +private: + signed char x; +}; + +template class C8 { +public: + C8(T y) : x(y) {} + +private: + signed char x; +}; + +/* Twin template classes for std::uint8_t and std::int8_t */ +template class C13 { +public: + C13(T y) : x(y) {} + +private: + std::uint8_t x; +}; + +template class C14 { +public: + C14(T y) : x(y) {} + +private: + std::int8_t x; +}; + +template class C15 { +public: + C15(T y) : x(y) {} + +private: + std::int8_t x; +}; + +template class C16 { +public: + C16(T y) : x(y) {} + +private: + std::int8_t x; +}; + +int main() { + + /* ========== 1. Assigning a char to another char ========== */ + + /* ===== 1-1. Assigning a char to a char variable ===== */ + + unsigned char x1 = 1; + unsigned char y1 = + x1; // COMPLIANT: unsigned char assigned to an unsigned char + + signed char x2 = 1; + signed char y2 = x2; // COMPLIANT: signed char assigned to a signed char + + char x3 = 'x'; + unsigned char y3 = x3; // NON-COMPLIANT: plain char assigned to a unsigned char + + char x4 = 'x'; + signed char y4 = x4; // NON-COMPLIANT: plain char assigned to a signed char + + /* Twin cases with std::uint8_t and std::int8_t */ + std::uint8_t x5 = 1; + std::uint8_t y5 = + x5; // COMPLIANT: std::uint8_t assigned to a std::uint8_t + + std::int8_t x6 = 1; + std::int8_t y6 = x6; // COMPLIANT: std::int8_t assigned to a std::int8_t + + char x7 = 'x'; + std::uint8_t y7 = x7; // NON-COMPLIANT: plain char assigned to a std::uint8_t + + char x8 = 'x'; + std::int8_t y8 = x8; // NON-COMPLIANT: plain char assigned to a std::int8_t + + /* ===== 1-2. Assigning a char to a char member ===== */ + + C1 c1; // COMPLIANT: unsigned char arg passed to an unsigned + // char member through a template + + C2 c2; // COMPLIANT: signed char arg passed to a signed char + // member through a template + + C3 c3; // NON-COMPLIANT: plain char arg passed to a unsigned char + // member through a template + + C4 c4; // NON-COMPLIANT: plain char arg passed to a signed char + // member through a template + + /* Twin cases with std::uint8_t and std::int8_t */ + C9 c9; // COMPLIANT: std::uint8_t arg passed to a std::uint8_t + // member through a template + + C10 c10; // COMPLIANT: std::int8_t arg passed to a std::int8_t + // member through a template + + C11 c11; // NON-COMPLIANT: plain char arg passed to a std::uint8_t + // member through a template + + C12 c12; // NON-COMPLIANT: plain char arg passed to a std::int8_t + // member through a template + + /* ========== 1-3. Assigning a char to a char through a pointer ========== */ + + unsigned char x9 = 1; + unsigned char *y9 = &x9; + signed char z1 = + *y9; // COMPLIANT: unsigned char assigned to a *&unsigned char + + unsigned char x10 = 1; + unsigned char *y10 = &x10; + signed char z2 = *y10; // COMPLIANT: signed char assigned to an *&signed char + + char x11 = 1; + char *y11 = &x11; + unsigned char z3 = + *y11; // NON-COMPLIANT: plain char assigned to an *&unsigned char + + char x12 = 1; + char *y12 = &x12; + signed char z4 = + *y12; // NON-COMPLIANT: plain char assigned to an *&signed char + + /* Twin cases with std::uint8_t and std::int8_t */ + std::uint8_t x13 = 1; + std::uint8_t *y13 = &x13; + std::int8_t z5 = + *y13; // COMPLIANT: std::uint8_t assigned to a *&std::uint8_t + + std::uint8_t x14 = 1; + std::uint8_t *y14 = &x14; + std::int8_t z6 = *y14; // COMPLIANT: std::int8_t assigned to an *&std::int8_t + + char x15 = 1; + char *y15 = &x15; + std::uint8_t z7 = + *y15; // NON-COMPLIANT: plain char assigned to an *&std::uint8_t + + char x16 = 1; + char *y16 = &x16; + std::int8_t z8 = + *y16; // NON-COMPLIANT: plain char assigned to an *&std::int8_t + + /* ========== 2. Passing a char argument to a char parameter ========== */ + + /* ===== 2-1. Passing char argument to a char parameter of a regular function + * ===== */ + + unsigned char a1 = 1; + f1(a1); // COMPLIANT: unsigned char arg passed to an unsigned char parameter + + signed char a2 = 1; + f2(a2); // COMPLIANT: signed char arg passed to a signed char parameter + + char a3 = 'a'; + f3(a3); // NON-COMPLIANT: plain char arg passed to a unsigned char parameter + + char a4 = 'a'; + f4(a4); // NON-COMPLIANT: plain char arg passed to a signed char parameter + + /* Twin cases with std::uint8_t and std::int8_t */ + std::uint8_t a5 = 1; + f9(a5); // COMPLIANT: std::uint8_t arg passed to a std::uint8_t parameter + + std::int8_t a6 = 1; + f10(a6); // COMPLIANT: std::int8_t arg passed to a std::int8_t parameter + + char a7 = 'a'; + f11(a7); // NON-COMPLIANT: plain char arg passed to a std::uint8_t parameter + + char a8 = 'a'; + f12(a8); // NON-COMPLIANT: plain char arg passed to a std::int8_t parameter + + /* ===== 2-2. Passing char argument to a char parameter through a template + * ===== */ + + unsigned char a9 = 'a'; + f5(a9); // COMPLIANT: unsigned char arg passed to an unsigned char parameter + // through a template + + signed char a10 = 'a'; + f6(a10); // COMPLIANT: signed char arg passed to a signed char parameter + // through a template + + char a11 = 'a'; + f7(a11); // NON-COMPLIANT: plain char arg passed to a unsigned char parameter + // through a template + + char a12 = 'a'; + f8(a12); // COMPLIANT: plain char arg passed to a signed char parameter through + // a template + + /* Twin cases with std::uint8_t and std::int8_t */ + std::uint8_t a13 = 'a'; + f13(a13); // COMPLIANT: std::uint8_t arg passed to a std::uint8_t parameter + // through a template + + std::int8_t a14 = 'a'; + f14(a14); // COMPLIANT: std::int8_t arg passed to a std::int8_t parameter + // through a template + + char a15 = 'a'; + f15(a15); // NON-COMPLIANT: plain char arg passed to a std::uint8_t parameter + // through a template + + char a16 = 'a'; + f16(a16); // COMPLIANT: plain char arg passed to a std::int8_t parameter through + // a template + + /* ========== 2-3. Passing a char argument to a char parameter through a + * template ========== */ + + unsigned char a17 = 1; + C5 c5( + a17); // COMPLIANT: unsigned char arg passed to an unsigned char parameter + // of a constructor through a template + + signed char a18 = 1; + C6 c6(a18); // COMPLIANT: signed char arg passed to an signed + // char parameter of a constructor through a template + + char a19 = 'a'; + C7 c7(a19); // NON-COMPLIANT: plain char arg passed to an unsigned char + // parameter of a constructor through a template + + char a20 = 'a'; + C8 c8(a20); // NON-COMPLIANT: plain char arg passed to an signed char + // parameter of a constructor through a template + + /* Twin cases with std::uint8_t and std::int8_t */ + std::uint8_t a21 = 1; + C13 c13( + a21); // COMPLIANT: std::uint8_t arg passed to a std::uint8_t parameter + // of a constructor through a template + + std::int8_t a22 = 1; + C14 c14(a22); // COMPLIANT: std::int8_t arg passed to a std::int8_t + // parameter of a constructor through a template + + char a23 = 'a'; + C15 c15(a23); // NON-COMPLIANT: plain char arg passed to a std::uint8_t + // parameter of a constructor through a template + + char a24 = 'a'; + C16 c16(a24); // NON-COMPLIANT: plain char arg passed to a std::int8_t + // parameter of a constructor through a template } \ No newline at end of file From fb544876bb2ce448934362c7ce5ce495803a807c Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Thu, 10 Jul 2025 14:39:44 -0700 Subject: [PATCH 349/370] Renumber definitions and objects, and fix wrong labels --- cpp/autosar/test/rules/M5-0-12/test.cpp | 70 ++++++++++++------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/cpp/autosar/test/rules/M5-0-12/test.cpp b/cpp/autosar/test/rules/M5-0-12/test.cpp index 355c9cbc4f..57530dae16 100644 --- a/cpp/autosar/test/rules/M5-0-12/test.cpp +++ b/cpp/autosar/test/rules/M5-0-12/test.cpp @@ -33,33 +33,33 @@ template class C4 { }; /* Twin templates for std::uint8_t and std::int8_t */ -template class C9 { +template class C5 { public: - C9() : x(y) {} + C5() : x(y) {} private: std::uint8_t x; }; -template class C10 { +template class C6 { public: - C10() : x(y) {} + C6() : x(y) {} private: std::int8_t x; }; -template class C11 { +template class C7 { public: - C11() : x(y) {} + C7() : x(y) {} private: std::uint8_t x; }; -template class C12 { +template class C8 { public: - C12() : x(y) {} + C8() : x(y) {} private: std::int8_t x; @@ -87,33 +87,33 @@ template void f14(T x) { std::int8_t y = x; } template void f15(T x) { std::int8_t y = x; } template void f16(T x) { std::int8_t y = x; } -template class C5 { +template class C9 { public: - C5(T y) : x(y) {} + C9(T y) : x(y) {} private: unsigned char x; }; -template class C6 { +template class C10 { public: - C6(T y) : x(y) {} + C10(T y) : x(y) {} private: signed char x; }; -template class C7 { +template class C11 { public: - C7(T y) : x(y) {} + C11(T y) : x(y) {} private: signed char x; }; -template class C8 { +template class C12 { public: - C8(T y) : x(y) {} + C12(T y) : x(y) {} private: signed char x; @@ -200,27 +200,27 @@ int main() { // member through a template /* Twin cases with std::uint8_t and std::int8_t */ - C9 c9; // COMPLIANT: std::uint8_t arg passed to a std::uint8_t + C5 c5; // COMPLIANT: std::uint8_t arg passed to a std::uint8_t // member through a template - C10 c10; // COMPLIANT: std::int8_t arg passed to a std::int8_t + C6 c6; // COMPLIANT: std::int8_t arg passed to a std::int8_t // member through a template - C11 c11; // NON-COMPLIANT: plain char arg passed to a std::uint8_t + C7 c7; // NON-COMPLIANT: plain char arg passed to a std::uint8_t // member through a template - C12 c12; // NON-COMPLIANT: plain char arg passed to a std::int8_t + C8 c8; // NON-COMPLIANT: plain char arg passed to a std::int8_t // member through a template /* ========== 1-3. Assigning a char to a char through a pointer ========== */ unsigned char x9 = 1; unsigned char *y9 = &x9; - signed char z1 = + unsigned char z1 = *y9; // COMPLIANT: unsigned char assigned to a *&unsigned char - unsigned char x10 = 1; - unsigned char *y10 = &x10; + signed char x10 = 1; + signed char *y10 = &x10; signed char z2 = *y10; // COMPLIANT: signed char assigned to an *&signed char char x11 = 1; @@ -236,11 +236,11 @@ int main() { /* Twin cases with std::uint8_t and std::int8_t */ std::uint8_t x13 = 1; std::uint8_t *y13 = &x13; - std::int8_t z5 = + std::uint8_t z5 = *y13; // COMPLIANT: std::uint8_t assigned to a *&std::uint8_t - std::uint8_t x14 = 1; - std::uint8_t *y14 = &x14; + std::int8_t x14 = 1; + std::int8_t *y14 = &x14; std::int8_t z6 = *y14; // COMPLIANT: std::int8_t assigned to an *&std::int8_t char x15 = 1; @@ -295,11 +295,11 @@ int main() { // through a template char a11 = 'a'; - f7(a11); // NON-COMPLIANT: plain char arg passed to a unsigned char parameter + f7(a11); // NON-COMPLIANT: plain char arg passed to a signed char parameter // through a template char a12 = 'a'; - f8(a12); // COMPLIANT: plain char arg passed to a signed char parameter through + f8(a12); // NON-COMPLIANT: plain char arg passed to a signed char parameter through // a template /* Twin cases with std::uint8_t and std::int8_t */ @@ -312,31 +312,31 @@ int main() { // through a template char a15 = 'a'; - f15(a15); // NON-COMPLIANT: plain char arg passed to a std::uint8_t parameter + f15(a15); // NON-COMPLIANT: plain char arg passed to a std::int8_t parameter // through a template char a16 = 'a'; - f16(a16); // COMPLIANT: plain char arg passed to a std::int8_t parameter through + f16(a16); // NON-COMPLIANT: plain char arg passed to a std::int8_t parameter through // a template /* ========== 2-3. Passing a char argument to a char parameter through a * template ========== */ unsigned char a17 = 1; - C5 c5( + C9 c9( a17); // COMPLIANT: unsigned char arg passed to an unsigned char parameter // of a constructor through a template signed char a18 = 1; - C6 c6(a18); // COMPLIANT: signed char arg passed to an signed + C10 c10(a18); // COMPLIANT: signed char arg passed to an signed // char parameter of a constructor through a template char a19 = 'a'; - C7 c7(a19); // NON-COMPLIANT: plain char arg passed to an unsigned char + C11 c11(a19); // NON-COMPLIANT: plain char arg passed to a signed char // parameter of a constructor through a template char a20 = 'a'; - C8 c8(a20); // NON-COMPLIANT: plain char arg passed to an signed char + C12 c12(a20); // NON-COMPLIANT: plain char arg passed to an signed char // parameter of a constructor through a template /* Twin cases with std::uint8_t and std::int8_t */ @@ -350,7 +350,7 @@ int main() { // parameter of a constructor through a template char a23 = 'a'; - C15 c15(a23); // NON-COMPLIANT: plain char arg passed to a std::uint8_t + C15 c15(a23); // NON-COMPLIANT: plain char arg passed to a std::int8_t // parameter of a constructor through a template char a24 = 'a'; From 808b5fd13a620c6401af427b676d871861f9b6a5 Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Thu, 10 Jul 2025 14:56:37 -0700 Subject: [PATCH 350/370] Fix cases 1. Change signed char / int8_t case to their opposites. 2. Assign a numeral to the unsigned char / signed char than a character. --- cpp/autosar/test/rules/M5-0-12/test.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cpp/autosar/test/rules/M5-0-12/test.cpp b/cpp/autosar/test/rules/M5-0-12/test.cpp index 57530dae16..99cb995854 100644 --- a/cpp/autosar/test/rules/M5-0-12/test.cpp +++ b/cpp/autosar/test/rules/M5-0-12/test.cpp @@ -78,13 +78,13 @@ void f12(std::int8_t x) {} template void f5(T x) { unsigned char y = x; } template void f6(T x) { signed char y = x; } -template void f7(T x) { signed char y = x; } +template void f7(T x) { unsigned char y = x; } template void f8(T x) { signed char y = x; } /* Twin template functions for std::uint8_t and std::int8_t */ template void f13(T x) { std::uint8_t y = x; } template void f14(T x) { std::int8_t y = x; } -template void f15(T x) { std::int8_t y = x; } +template void f15(T x) { std::uint8_t y = x; } template void f16(T x) { std::int8_t y = x; } template class C9 { @@ -286,16 +286,16 @@ int main() { /* ===== 2-2. Passing char argument to a char parameter through a template * ===== */ - unsigned char a9 = 'a'; + unsigned char a9 = 1; f5(a9); // COMPLIANT: unsigned char arg passed to an unsigned char parameter // through a template - signed char a10 = 'a'; + signed char a10 = 1; f6(a10); // COMPLIANT: signed char arg passed to a signed char parameter // through a template char a11 = 'a'; - f7(a11); // NON-COMPLIANT: plain char arg passed to a signed char parameter + f7(a11); // NON-COMPLIANT: plain char arg passed to an unsigned char parameter // through a template char a12 = 'a'; @@ -303,16 +303,16 @@ int main() { // a template /* Twin cases with std::uint8_t and std::int8_t */ - std::uint8_t a13 = 'a'; + std::uint8_t a13 = 1; f13(a13); // COMPLIANT: std::uint8_t arg passed to a std::uint8_t parameter // through a template - std::int8_t a14 = 'a'; + std::int8_t a14 = 1; f14(a14); // COMPLIANT: std::int8_t arg passed to a std::int8_t parameter // through a template char a15 = 'a'; - f15(a15); // NON-COMPLIANT: plain char arg passed to a std::int8_t parameter + f15(a15); // NON-COMPLIANT: plain char arg passed to a std::uint8_t parameter // through a template char a16 = 'a'; From da92563a2f0d915e6523d79d08ba44a5cd546d40 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 11 Jul 2025 00:19:47 +0200 Subject: [PATCH 351/370] Fix misspelling of asynchronous in SIG30-C --- .../CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql | 8 ++++---- ...allOnlyAsyncSafeFunctionsWithinSignalHandlers.expected | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/c/cert/src/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql b/c/cert/src/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql index 4cc0f9e32c..e5dc33f817 100644 --- a/c/cert/src/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql +++ b/c/cert/src/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql @@ -37,7 +37,7 @@ class AsyncSafeVariableAccess extends VariableAccess { abstract class AsyncSafeFunction extends Function { } /** - * C standard library ayncronous-safe functions + * C standard library asynchronous-safe functions */ class CAsyncSafeFunction extends AsyncSafeFunction { //tion, or the signal function with the first argument equal to the signal number corresponding to the signal that caused the invocation of the handler @@ -45,7 +45,7 @@ class CAsyncSafeFunction extends AsyncSafeFunction { } /** - * POSIX defined ayncronous-safe functions + * POSIX defined asynchronous-safe functions */ class PosixAsyncSafeFunction extends AsyncSafeFunction { PosixAsyncSafeFunction() { @@ -73,7 +73,7 @@ class PosixAsyncSafeFunction extends AsyncSafeFunction { } /** - * Application defined ayncronous-safe functions + * Application defined asynchronous-safe functions */ class ApplicationAsyncSafeFunction extends AsyncSafeFunction { pragma[nomagic] @@ -122,5 +122,5 @@ where or fc instanceof AsyncUnsafeRaiseCall ) -select fc, "Asyncronous-unsafe function calls within a $@ can lead to undefined behavior.", +select fc, "Asynchronous-unsafe function calls within a $@ can lead to undefined behavior.", handler.getRegistration(), "signal handler" diff --git a/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected b/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected index 4898448814..ce13ee69a7 100644 --- a/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected +++ b/c/cert/test/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.expected @@ -1,7 +1,7 @@ WARNING: module 'DataFlow' has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:110,11-19) WARNING: module 'DataFlow' has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:110,31-39) WARNING: module 'DataFlow' has been deprecated and may be removed in future (CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql:111,9-17) -| test.c:10:3:10:18 | call to log_local_unsafe | Asyncronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:16:7:16:12 | call to signal | signal handler | -| test.c:11:3:11:6 | call to free | Asyncronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:16:7:16:12 | call to signal | signal handler | -| test.c:46:3:46:9 | call to longjmp | Asyncronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:50:7:50:12 | call to signal | signal handler | -| test.c:76:7:76:11 | call to raise | Asyncronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:91:7:91:12 | call to signal | signal handler | +| test.c:10:3:10:18 | call to log_local_unsafe | Asynchronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:16:7:16:12 | call to signal | signal handler | +| test.c:11:3:11:6 | call to free | Asynchronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:16:7:16:12 | call to signal | signal handler | +| test.c:46:3:46:9 | call to longjmp | Asynchronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:50:7:50:12 | call to signal | signal handler | +| test.c:76:7:76:11 | call to raise | Asynchronous-unsafe function calls within a $@ can lead to undefined behavior. | test.c:91:7:91:12 | call to signal | signal handler | From 56258d17d63e8017e58bf5d93626297416677756 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 11 Jul 2025 15:31:16 +0200 Subject: [PATCH 352/370] Add change note --- change_notes/2025-07-11-typo-in-alert-message..md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 change_notes/2025-07-11-typo-in-alert-message..md diff --git a/change_notes/2025-07-11-typo-in-alert-message..md b/change_notes/2025-07-11-typo-in-alert-message..md new file mode 100644 index 0000000000..077f2efb66 --- /dev/null +++ b/change_notes/2025-07-11-typo-in-alert-message..md @@ -0,0 +1,2 @@ +- `SIG30-C`: `CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql` + - Fixed a misspelling of "asynchronous" in the alert message. From 80029970d8bf7f242cb4de49e8b0a3c3bbbf9c6e Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Fri, 11 Jul 2025 16:43:26 -0700 Subject: [PATCH 353/370] Add a working draft of the query --- ...eUsedForTheStorageAndUseOfNumericValues.ql | 207 ++++++++++++++++-- 1 file changed, 189 insertions(+), 18 deletions(-) diff --git a/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql b/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql index 3b6e436c56..7ffc47e50f 100644 --- a/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql +++ b/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql @@ -16,23 +16,194 @@ import cpp import codingstandards.cpp.autosar -from Variable v, Expr aexp +newtype TTemplatedElement = + TClassTemplate(TemplateClass c) or + TFunctionTemplate(TemplateFunction f) or + TVariableTemplate(TemplateVariable v) + +class TemplatedElement extends TTemplatedElement { + TemplateClass asTemplateClass() { this = TClassTemplate(result) } + + TemplateFunction asTemplateFunction() { this = TFunctionTemplate(result) } + + TemplateVariable asTemplateVariable() { this = TVariableTemplate(result) } + + string toString() { + result = this.asTemplateClass().toString() or + result = this.asTemplateFunction().toString() or + result = this.asTemplateVariable().toString() + } + + Location getLocation() { + result = this.asTemplateClass().getLocation() or + result = this.asTemplateFunction().getLocation() or + result = this.asTemplateVariable().getLocation() + } + + string getName() { + result = this.asTemplateClass().getName() or + result = this.asTemplateFunction().getName() or + result = this.asTemplateVariable().getName() + } +} + +newtype TTemplateInstantiation = + TClassTemplateInstantiation(ClassTemplateInstantiation c) or + TFunctionTemplateInstantiation(FunctionTemplateInstantiation f) or + TVariableTemplateInstantiation(VariableTemplateInstantiation v) + +class TemplateInstantiation extends TTemplateInstantiation { + ClassTemplateInstantiation asClassTemplateInstantiation() { + this = TClassTemplateInstantiation(result) + } + + FunctionTemplateInstantiation asFunctionTemplateInstantiation() { + this = TFunctionTemplateInstantiation(result) + } + + VariableTemplateInstantiation asVariableTemplateInstantiation() { + this = TVariableTemplateInstantiation(result) + } + + string toString() { + result = this.asClassTemplateInstantiation().toString() or + result = this.asFunctionTemplateInstantiation().toString() or + result = this.asVariableTemplateInstantiation().toString() + } + + Location getLocation() { + result = this.asClassTemplateInstantiation().getLocation() or + result = this.asFunctionTemplateInstantiation().getLocation() or + result = this.asVariableTemplateInstantiation().getLocation() + } + + Element asElement() { + result = this.asClassTemplateInstantiation() or + result = this.asFunctionTemplateInstantiation() or + result = this.asVariableTemplateInstantiation() + } + + TemplatedElement getTemplate() { + result.asTemplateClass() = this.asClassTemplateInstantiation().getTemplate() or + result.asTemplateFunction() = this.asFunctionTemplateInstantiation().getTemplate() or + result.asTemplateVariable() = this.asVariableTemplateInstantiation().getTemplate() + } + + /** + * Gets a use of an instantiation of this template. i.e. + * 1. For a class template, it's where the instantiated type is used by the name. + * 2. For a function template, it's where the instantiated function is called. + * 3. For a variable template, it's where the instantiated variable is initialized. + */ + Element getAUse() { + result = this.asClassTemplateInstantiation().getATypeNameUse() or + result = this.asFunctionTemplateInstantiation().getACallToThisFunction() or + result = this.asVariableTemplateInstantiation() + } +} + +class ImplicitConversionFromPlainCharType extends Conversion { + ImplicitConversionFromPlainCharType() { + this.isImplicit() and + this.getExpr().getUnspecifiedType() instanceof PlainCharType and + ( + this.getUnspecifiedType() instanceof SignedCharType or + this.getUnspecifiedType() instanceof UnsignedCharType + ) + } +} + +newtype TImplicitConversionElement = + TImplicitConversionOutsideTemplate(ImplicitConversionFromPlainCharType implicitConversion) { + not exists(TemplateInstantiation instantiation | + implicitConversion.isFromTemplateInstantiation(instantiation.asElement()) + ) + } or + TInstantiationOfImplicitConversionTemplate( + TemplateInstantiation templateInstantiation, + ImplicitConversionFromPlainCharType implicitConversion + ) { + implicitConversion.getEnclosingElement+() = templateInstantiation.asElement() + } + +class ImplicitConversionLocation extends TImplicitConversionElement { + ImplicitConversionFromPlainCharType asImplicitConversionOutsideTemplate() { + this = TImplicitConversionOutsideTemplate(result) + } + + TemplateInstantiation asInstantiationOfImplicitConversionTemplate( + ImplicitConversionFromPlainCharType implicitConversion + ) { + this = TInstantiationOfImplicitConversionTemplate(result, implicitConversion) + } + + predicate isImplicitConversionOutsideTemplate() { + exists(this.asImplicitConversionOutsideTemplate()) + } + + predicate isInstantiationOfImplicitConversionTemplate() { + exists( + TemplateInstantiation templateInstantiation, + ImplicitConversionFromPlainCharType implicitConversion + | + templateInstantiation = this.asInstantiationOfImplicitConversionTemplate(implicitConversion) + ) + } + + ImplicitConversionFromPlainCharType getImplicitConversion() { + result = this.asImplicitConversionOutsideTemplate() or + exists(TemplateInstantiation templateInstantiation | + this = TInstantiationOfImplicitConversionTemplate(templateInstantiation, result) + ) + } + + string toString() { + result = this.asImplicitConversionOutsideTemplate().toString() or + exists(ImplicitConversionFromPlainCharType implicitConversion | + result = this.asInstantiationOfImplicitConversionTemplate(implicitConversion).toString() + ) + } + + Location getLocation() { + result = this.asImplicitConversionOutsideTemplate().getLocation() or + exists(ImplicitConversionFromPlainCharType implicitConversion | + result = this.asInstantiationOfImplicitConversionTemplate(implicitConversion).getLocation() + ) + } + + Element asElement() { + result = this.asImplicitConversionOutsideTemplate() or + exists(ImplicitConversionFromPlainCharType implicitConversion | + result = this.asInstantiationOfImplicitConversionTemplate(implicitConversion).getAUse() + ) + } +} + +string getMessageTemplate(ImplicitConversionLocation implicitConversionLocation) { + exists(ImplicitConversionFromPlainCharType implicitConversion | + implicitConversion = implicitConversionLocation.getImplicitConversion() + | + implicitConversionLocation.isImplicitConversionOutsideTemplate() and + result = + "Implicit conversion of plain char $@ to " + implicitConversion.getType().getName() + "." + or + implicitConversionLocation.isInstantiationOfImplicitConversionTemplate() and + result = + "Implicit conversion of plain char $@ to " + implicitConversion.getType().getName() + + " from instantiating template '" + + implicitConversionLocation + .asInstantiationOfImplicitConversionTemplate(implicitConversion) + .getTemplate() + .getName() + "'." + ) +} + +from + ImplicitConversionLocation implicitConversionLocation, + ImplicitConversionFromPlainCharType implicitConversion where - not isExcluded(v, + not isExcluded(implicitConversionLocation.asElement(), StringsPackage::signedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValuesQuery()) and - // We find cases where it is an explicitly signed char type with an assignment - // to a non-numeric type. NOTE: This rule addresses cases where the char type - // is used character data only, the rule does not explicitly cover this. - // Please see M5-0-11 for explicit handling of this case. Get types that are - // char, except for ones that are 'plain', meaning the sign is explicit. - ( - v.getUnspecifiedType() instanceof SignedCharType or - v.getUnspecifiedType() instanceof UnsignedCharType - ) and - // Identify places where these explicitly signed types are being assigned to a - // non-numeric type. - aexp = v.getAnAssignedValue() and - aexp.getUnspecifiedType() instanceof CharType -select aexp, - "Assignment of an non-integer type to variable $@ which is a variable with an explicitly signed char type", - v, v.getName() + implicitConversion = implicitConversionLocation.getImplicitConversion() +select implicitConversionLocation.asElement(), getMessageTemplate(implicitConversionLocation), + implicitConversion.getExpr(), "expression" From 2ed4443c02d8e1b31cf2058d8321e61d99573a92 Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Mon, 14 Jul 2025 10:01:00 -0400 Subject: [PATCH 354/370] Deduplicate the test cases and update the expected results. --- ...orTheStorageAndUseOfNumericValues.expected | 28 +++- cpp/autosar/test/rules/M5-0-12/test.cpp | 121 +++++------------- 2 files changed, 54 insertions(+), 95 deletions(-) diff --git a/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected b/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected index 1be5b7b9fc..cafd6c64b2 100644 --- a/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected +++ b/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected @@ -1,4 +1,24 @@ -| test.cpp:4:22:4:24 | 99 | Assignment of an non-integer type to variable $@ which is a variable with an explicitly signed char type | test.cpp:4:17:4:18 | a1 | a1 | -| test.cpp:6:20:6:22 | 99 | Assignment of an non-integer type to variable $@ which is a variable with an explicitly signed char type | test.cpp:6:15:6:16 | a3 | a3 | -| test.cpp:9:20:9:22 | 99 | Assignment of an non-integer type to variable $@ which is a variable with an explicitly signed char type | test.cpp:9:15:9:16 | a5 | a5 | -| test.cpp:12:21:12:23 | 99 | Assignment of an non-integer type to variable $@ which is a variable with an explicitly signed char type | test.cpp:12:16:12:17 | a7 | a7 | +| test.cpp:106:7:106:8 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:106:7:106:8 | x3 | expression | +| test.cpp:109:20:109:21 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:109:20:109:21 | x4 | expression | +| test.cpp:119:21:119:22 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:119:21:119:22 | x7 | expression | +| test.cpp:122:20:122:21 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:122:20:122:21 | x8 | expression | +| test.cpp:132:17:132:18 | definition of c3 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'C1'. | test.cpp:5:12:5:12 | 120 | expression | +| test.cpp:135:17:135:18 | definition of c4 | Implicit conversion of plain char $@ to signed char from instantiating template 'C2'. | test.cpp:13:12:13:12 | 120 | expression | +| test.cpp:145:15:145:16 | definition of c7 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'C5'. | test.cpp:22:12:22:12 | 1 | expression | +| test.cpp:148:15:148:16 | definition of c8 | Implicit conversion of plain char $@ to int8_t from instantiating template 'C6'. | test.cpp:30:12:30:12 | 1 | expression | +| test.cpp:165:7:165:10 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:165:7:165:10 | * ... | expression | +| test.cpp:170:7:170:10 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:170:7:170:10 | * ... | expression | +| test.cpp:185:7:185:10 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:185:7:185:10 | * ... | expression | +| test.cpp:190:7:190:10 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:190:7:190:10 | * ... | expression | +| test.cpp:204:6:204:7 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:204:6:204:7 | a3 | expression | +| test.cpp:207:6:207:7 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:207:6:207:7 | a4 | expression | +| test.cpp:217:7:217:8 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:217:7:217:8 | a7 | expression | +| test.cpp:220:7:220:8 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:220:7:220:8 | a8 | expression | +| test.cpp:234:3:234:4 | call to f7 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'f7'. | test.cpp:49:56:49:56 | x | expression | +| test.cpp:238:3:238:4 | call to f8 | Implicit conversion of plain char $@ to signed char from instantiating template 'f8'. | test.cpp:50:54:50:54 | x | expression | +| test.cpp:251:3:251:5 | call to f15 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'f15'. | test.cpp:55:56:55:56 | x | expression | +| test.cpp:255:3:255:5 | call to f16 | Implicit conversion of plain char $@ to int8_t from instantiating template 'f16'. | test.cpp:56:55:56:55 | x | expression | +| test.cpp:272:12:272:14 | definition of c11 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'C9'. | test.cpp:60:15:60:15 | y | expression | +| test.cpp:277:13:277:15 | definition of c12 | Implicit conversion of plain char $@ to signed char from instantiating template 'C10'. | test.cpp:68:16:68:16 | y | expression | +| test.cpp:292:13:292:15 | definition of c15 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'C13'. | test.cpp:77:16:77:16 | y | expression | +| test.cpp:296:13:296:15 | definition of c16 | Implicit conversion of plain char $@ to int8_t from instantiating template 'C14'. | test.cpp:85:16:85:16 | y | expression | diff --git a/cpp/autosar/test/rules/M5-0-12/test.cpp b/cpp/autosar/test/rules/M5-0-12/test.cpp index 99cb995854..91106b8211 100644 --- a/cpp/autosar/test/rules/M5-0-12/test.cpp +++ b/cpp/autosar/test/rules/M5-0-12/test.cpp @@ -16,22 +16,6 @@ template class C2 { signed char x; }; -template class C3 { -public: - C3() : x(y) {} - -private: - unsigned char x; -}; - -template class C4 { -public: - C4() : x(y) {} - -private: - signed char x; -}; - /* Twin templates for std::uint8_t and std::int8_t */ template class C5 { public: @@ -49,22 +33,6 @@ template class C6 { std::int8_t x; }; -template class C7 { -public: - C7() : x(y) {} - -private: - std::uint8_t x; -}; - -template class C8 { -public: - C8() : x(y) {} - -private: - std::int8_t x; -}; - void f1(unsigned char x) {} void f2(signed char x) {} void f3(unsigned char x) {} @@ -103,22 +71,6 @@ template class C10 { signed char x; }; -template class C11 { -public: - C11(T y) : x(y) {} - -private: - signed char x; -}; - -template class C12 { -public: - C12(T y) : x(y) {} - -private: - signed char x; -}; - /* Twin template classes for std::uint8_t and std::int8_t */ template class C13 { public: @@ -136,22 +88,6 @@ template class C14 { std::int8_t x; }; -template class C15 { -public: - C15(T y) : x(y) {} - -private: - std::int8_t x; -}; - -template class C16 { -public: - C16(T y) : x(y) {} - -private: - std::int8_t x; -}; - int main() { /* ========== 1. Assigning a char to another char ========== */ @@ -166,15 +102,15 @@ int main() { signed char y2 = x2; // COMPLIANT: signed char assigned to a signed char char x3 = 'x'; - unsigned char y3 = x3; // NON-COMPLIANT: plain char assigned to a unsigned char + unsigned char y3 = + x3; // NON-COMPLIANT: plain char assigned to a unsigned char char x4 = 'x'; signed char y4 = x4; // NON-COMPLIANT: plain char assigned to a signed char /* Twin cases with std::uint8_t and std::int8_t */ std::uint8_t x5 = 1; - std::uint8_t y5 = - x5; // COMPLIANT: std::uint8_t assigned to a std::uint8_t + std::uint8_t y5 = x5; // COMPLIANT: std::uint8_t assigned to a std::uint8_t std::int8_t x6 = 1; std::int8_t y6 = x6; // COMPLIANT: std::int8_t assigned to a std::int8_t @@ -193,24 +129,24 @@ int main() { C2 c2; // COMPLIANT: signed char arg passed to a signed char // member through a template - C3 c3; // NON-COMPLIANT: plain char arg passed to a unsigned char + C1 c3; // NON-COMPLIANT: plain char arg passed to a unsigned char // member through a template - C4 c4; // NON-COMPLIANT: plain char arg passed to a signed char + C2 c4; // NON-COMPLIANT: plain char arg passed to a signed char // member through a template /* Twin cases with std::uint8_t and std::int8_t */ - C5 c5; // COMPLIANT: std::uint8_t arg passed to a std::uint8_t - // member through a template + C5 c5; // COMPLIANT: std::uint8_t arg passed to a + // std::uint8_t member through a template C6 c6; // COMPLIANT: std::int8_t arg passed to a std::int8_t - // member through a template + // member through a template - C7 c7; // NON-COMPLIANT: plain char arg passed to a std::uint8_t - // member through a template + C5 c7; // NON-COMPLIANT: plain char arg passed to a + // std::uint8_t member through a template - C8 c8; // NON-COMPLIANT: plain char arg passed to a std::int8_t - // member through a template + C6 c8; // NON-COMPLIANT: plain char arg passed to a std::int8_t + // member through a template /* ========== 1-3. Assigning a char to a char through a pointer ========== */ @@ -299,8 +235,8 @@ int main() { // through a template char a12 = 'a'; - f8(a12); // NON-COMPLIANT: plain char arg passed to a signed char parameter through - // a template + f8(a12); // NON-COMPLIANT: plain char arg passed to a signed char parameter + // through a template /* Twin cases with std::uint8_t and std::int8_t */ std::uint8_t a13 = 1; @@ -316,8 +252,8 @@ int main() { // through a template char a16 = 'a'; - f16(a16); // NON-COMPLIANT: plain char arg passed to a std::int8_t parameter through - // a template + f16(a16); // NON-COMPLIANT: plain char arg passed to a std::int8_t parameter + // through a template /* ========== 2-3. Passing a char argument to a char parameter through a * template ========== */ @@ -328,16 +264,18 @@ int main() { // of a constructor through a template signed char a18 = 1; - C10 c10(a18); // COMPLIANT: signed char arg passed to an signed - // char parameter of a constructor through a template + C10 c10( + a18); // COMPLIANT: signed char arg passed to an signed + // char parameter of a constructor through a template char a19 = 'a'; - C11 c11(a19); // NON-COMPLIANT: plain char arg passed to a signed char - // parameter of a constructor through a template + C9 c11( + a19); // NON-COMPLIANT: plain char arg passed to a unsigned signed char + // parameter of a constructor through a template char a20 = 'a'; - C12 c12(a20); // NON-COMPLIANT: plain char arg passed to an signed char - // parameter of a constructor through a template + C10 c12(a20); // NON-COMPLIANT: plain char arg passed to an signed char + // parameter of a constructor through a template /* Twin cases with std::uint8_t and std::int8_t */ std::uint8_t a21 = 1; @@ -346,14 +284,15 @@ int main() { // of a constructor through a template std::int8_t a22 = 1; - C14 c14(a22); // COMPLIANT: std::int8_t arg passed to a std::int8_t - // parameter of a constructor through a template + C14 c14( + a22); // COMPLIANT: std::int8_t arg passed to a std::int8_t + // parameter of a constructor through a template char a23 = 'a'; - C15 c15(a23); // NON-COMPLIANT: plain char arg passed to a std::int8_t + C13 c15(a23); // NON-COMPLIANT: plain char arg passed to a std::uint8_t // parameter of a constructor through a template char a24 = 'a'; - C16 c16(a24); // NON-COMPLIANT: plain char arg passed to a std::int8_t + C14 c16(a24); // NON-COMPLIANT: plain char arg passed to a std::int8_t // parameter of a constructor through a template -} \ No newline at end of file +} From 11a277f4289d3be792c3c74c34966f703873b2f8 Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Mon, 14 Jul 2025 10:23:11 -0400 Subject: [PATCH 355/370] Deduplicate more test cases and fix expected results --- ...orTheStorageAndUseOfNumericValues.expected | 48 +++++++++---------- cpp/autosar/test/rules/M5-0-12/test.cpp | 24 ++++------ 2 files changed, 32 insertions(+), 40 deletions(-) diff --git a/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected b/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected index cafd6c64b2..d5dc9af7e8 100644 --- a/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected +++ b/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected @@ -1,24 +1,24 @@ -| test.cpp:106:7:106:8 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:106:7:106:8 | x3 | expression | -| test.cpp:109:20:109:21 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:109:20:109:21 | x4 | expression | -| test.cpp:119:21:119:22 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:119:21:119:22 | x7 | expression | -| test.cpp:122:20:122:21 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:122:20:122:21 | x8 | expression | -| test.cpp:132:17:132:18 | definition of c3 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'C1'. | test.cpp:5:12:5:12 | 120 | expression | -| test.cpp:135:17:135:18 | definition of c4 | Implicit conversion of plain char $@ to signed char from instantiating template 'C2'. | test.cpp:13:12:13:12 | 120 | expression | -| test.cpp:145:15:145:16 | definition of c7 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'C5'. | test.cpp:22:12:22:12 | 1 | expression | -| test.cpp:148:15:148:16 | definition of c8 | Implicit conversion of plain char $@ to int8_t from instantiating template 'C6'. | test.cpp:30:12:30:12 | 1 | expression | -| test.cpp:165:7:165:10 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:165:7:165:10 | * ... | expression | -| test.cpp:170:7:170:10 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:170:7:170:10 | * ... | expression | -| test.cpp:185:7:185:10 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:185:7:185:10 | * ... | expression | -| test.cpp:190:7:190:10 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:190:7:190:10 | * ... | expression | -| test.cpp:204:6:204:7 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:204:6:204:7 | a3 | expression | -| test.cpp:207:6:207:7 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:207:6:207:7 | a4 | expression | -| test.cpp:217:7:217:8 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:217:7:217:8 | a7 | expression | -| test.cpp:220:7:220:8 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:220:7:220:8 | a8 | expression | -| test.cpp:234:3:234:4 | call to f7 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'f7'. | test.cpp:49:56:49:56 | x | expression | -| test.cpp:238:3:238:4 | call to f8 | Implicit conversion of plain char $@ to signed char from instantiating template 'f8'. | test.cpp:50:54:50:54 | x | expression | -| test.cpp:251:3:251:5 | call to f15 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'f15'. | test.cpp:55:56:55:56 | x | expression | -| test.cpp:255:3:255:5 | call to f16 | Implicit conversion of plain char $@ to int8_t from instantiating template 'f16'. | test.cpp:56:55:56:55 | x | expression | -| test.cpp:272:12:272:14 | definition of c11 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'C9'. | test.cpp:60:15:60:15 | y | expression | -| test.cpp:277:13:277:15 | definition of c12 | Implicit conversion of plain char $@ to signed char from instantiating template 'C10'. | test.cpp:68:16:68:16 | y | expression | -| test.cpp:292:13:292:15 | definition of c15 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'C13'. | test.cpp:77:16:77:16 | y | expression | -| test.cpp:296:13:296:15 | definition of c16 | Implicit conversion of plain char $@ to int8_t from instantiating template 'C14'. | test.cpp:85:16:85:16 | y | expression | +| test.cpp:98:7:98:8 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:98:7:98:8 | x3 | expression | +| test.cpp:101:20:101:21 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:101:20:101:21 | x4 | expression | +| test.cpp:111:21:111:22 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:111:21:111:22 | x7 | expression | +| test.cpp:114:20:114:21 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:114:20:114:21 | x8 | expression | +| test.cpp:124:17:124:18 | definition of c3 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'C1'. | test.cpp:5:12:5:12 | 120 | expression | +| test.cpp:127:17:127:18 | definition of c4 | Implicit conversion of plain char $@ to signed char from instantiating template 'C2'. | test.cpp:13:12:13:12 | 120 | expression | +| test.cpp:137:15:137:16 | definition of c7 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'C5'. | test.cpp:22:12:22:12 | 1 | expression | +| test.cpp:140:15:140:16 | definition of c8 | Implicit conversion of plain char $@ to int8_t from instantiating template 'C6'. | test.cpp:30:12:30:12 | 1 | expression | +| test.cpp:157:7:157:10 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:157:7:157:10 | * ... | expression | +| test.cpp:162:7:162:10 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:162:7:162:10 | * ... | expression | +| test.cpp:177:7:177:10 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:177:7:177:10 | * ... | expression | +| test.cpp:182:7:182:10 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:182:7:182:10 | * ... | expression | +| test.cpp:196:6:196:7 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:196:6:196:7 | a3 | expression | +| test.cpp:199:6:199:7 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:199:6:199:7 | a4 | expression | +| test.cpp:209:6:209:7 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:209:6:209:7 | a7 | expression | +| test.cpp:212:7:212:8 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:212:7:212:8 | a8 | expression | +| test.cpp:226:3:226:4 | call to f5 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'f5'. | test.cpp:43:56:43:56 | x | expression | +| test.cpp:230:3:230:4 | call to f6 | Implicit conversion of plain char $@ to signed char from instantiating template 'f6'. | test.cpp:44:54:44:54 | x | expression | +| test.cpp:243:3:243:5 | call to f13 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'f13'. | test.cpp:47:56:47:56 | x | expression | +| test.cpp:247:3:247:5 | call to f14 | Implicit conversion of plain char $@ to int8_t from instantiating template 'f14'. | test.cpp:48:55:48:55 | x | expression | +| test.cpp:264:12:264:14 | definition of c11 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'C9'. | test.cpp:52:15:52:15 | y | expression | +| test.cpp:269:13:269:15 | definition of c12 | Implicit conversion of plain char $@ to signed char from instantiating template 'C10'. | test.cpp:60:16:60:16 | y | expression | +| test.cpp:284:13:284:15 | definition of c15 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'C13'. | test.cpp:69:16:69:16 | y | expression | +| test.cpp:288:13:288:15 | definition of c16 | Implicit conversion of plain char $@ to int8_t from instantiating template 'C14'. | test.cpp:77:16:77:16 | y | expression | diff --git a/cpp/autosar/test/rules/M5-0-12/test.cpp b/cpp/autosar/test/rules/M5-0-12/test.cpp index 91106b8211..9687743402 100644 --- a/cpp/autosar/test/rules/M5-0-12/test.cpp +++ b/cpp/autosar/test/rules/M5-0-12/test.cpp @@ -35,25 +35,17 @@ template class C6 { void f1(unsigned char x) {} void f2(signed char x) {} -void f3(unsigned char x) {} -void f4(signed char x) {} /* Twin functions for std::uint8_t and std::int8_t */ void f9(std::uint8_t x) {} void f10(std::int8_t x) {} -void f11(std::uint8_t x) {} -void f12(std::int8_t x) {} template void f5(T x) { unsigned char y = x; } template void f6(T x) { signed char y = x; } -template void f7(T x) { unsigned char y = x; } -template void f8(T x) { signed char y = x; } /* Twin template functions for std::uint8_t and std::int8_t */ template void f13(T x) { std::uint8_t y = x; } template void f14(T x) { std::int8_t y = x; } -template void f15(T x) { std::uint8_t y = x; } -template void f16(T x) { std::int8_t y = x; } template class C9 { public: @@ -201,10 +193,10 @@ int main() { f2(a2); // COMPLIANT: signed char arg passed to a signed char parameter char a3 = 'a'; - f3(a3); // NON-COMPLIANT: plain char arg passed to a unsigned char parameter + f1(a3); // NON-COMPLIANT: plain char arg passed to a unsigned char parameter char a4 = 'a'; - f4(a4); // NON-COMPLIANT: plain char arg passed to a signed char parameter + f2(a4); // NON-COMPLIANT: plain char arg passed to a signed char parameter /* Twin cases with std::uint8_t and std::int8_t */ std::uint8_t a5 = 1; @@ -214,10 +206,10 @@ int main() { f10(a6); // COMPLIANT: std::int8_t arg passed to a std::int8_t parameter char a7 = 'a'; - f11(a7); // NON-COMPLIANT: plain char arg passed to a std::uint8_t parameter + f9(a7); // NON-COMPLIANT: plain char arg passed to a std::uint8_t parameter char a8 = 'a'; - f12(a8); // NON-COMPLIANT: plain char arg passed to a std::int8_t parameter + f10(a8); // NON-COMPLIANT: plain char arg passed to a std::int8_t parameter /* ===== 2-2. Passing char argument to a char parameter through a template * ===== */ @@ -231,11 +223,11 @@ int main() { // through a template char a11 = 'a'; - f7(a11); // NON-COMPLIANT: plain char arg passed to an unsigned char parameter + f5(a11); // NON-COMPLIANT: plain char arg passed to an unsigned char parameter // through a template char a12 = 'a'; - f8(a12); // NON-COMPLIANT: plain char arg passed to a signed char parameter + f6(a12); // NON-COMPLIANT: plain char arg passed to a signed char parameter // through a template /* Twin cases with std::uint8_t and std::int8_t */ @@ -248,11 +240,11 @@ int main() { // through a template char a15 = 'a'; - f15(a15); // NON-COMPLIANT: plain char arg passed to a std::uint8_t parameter + f13(a15); // NON-COMPLIANT: plain char arg passed to a std::uint8_t parameter // through a template char a16 = 'a'; - f16(a16); // NON-COMPLIANT: plain char arg passed to a std::int8_t parameter + f14(a16); // NON-COMPLIANT: plain char arg passed to a std::int8_t parameter // through a template /* ========== 2-3. Passing a char argument to a char parameter through a From 10c3a2c08ab66c1a5749195367b7426b9ba7e44d Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Mon, 14 Jul 2025 10:59:06 -0400 Subject: [PATCH 356/370] Minor label editing --- cpp/autosar/test/rules/M5-0-12/test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/autosar/test/rules/M5-0-12/test.cpp b/cpp/autosar/test/rules/M5-0-12/test.cpp index 9687743402..0fe008436c 100644 --- a/cpp/autosar/test/rules/M5-0-12/test.cpp +++ b/cpp/autosar/test/rules/M5-0-12/test.cpp @@ -121,7 +121,7 @@ int main() { C2 c2; // COMPLIANT: signed char arg passed to a signed char // member through a template - C1 c3; // NON-COMPLIANT: plain char arg passed to a unsigned char + C1 c3; // NON-COMPLIANT: plain char arg passed to an unsigned char // member through a template C2 c4; // NON-COMPLIANT: plain char arg passed to a signed char @@ -145,7 +145,7 @@ int main() { unsigned char x9 = 1; unsigned char *y9 = &x9; unsigned char z1 = - *y9; // COMPLIANT: unsigned char assigned to a *&unsigned char + *y9; // COMPLIANT: unsigned char assigned to an *&unsigned char signed char x10 = 1; signed char *y10 = &x10; @@ -193,7 +193,7 @@ int main() { f2(a2); // COMPLIANT: signed char arg passed to a signed char parameter char a3 = 'a'; - f1(a3); // NON-COMPLIANT: plain char arg passed to a unsigned char parameter + f1(a3); // NON-COMPLIANT: plain char arg passed to an unsigned char parameter char a4 = 'a'; f2(a4); // NON-COMPLIANT: plain char arg passed to a signed char parameter @@ -262,7 +262,7 @@ int main() { char a19 = 'a'; C9 c11( - a19); // NON-COMPLIANT: plain char arg passed to a unsigned signed char + a19); // NON-COMPLIANT: plain char arg passed to an unsigned signed char // parameter of a constructor through a template char a20 = 'a'; From 20a30ccc108c6a781b28b917e9edb729ef94b892 Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Mon, 14 Jul 2025 10:59:21 -0400 Subject: [PATCH 357/370] Attach docstrings to query elements --- ...eUsedForTheStorageAndUseOfNumericValues.ql | 61 ++++++++++++++++--- 1 file changed, 52 insertions(+), 9 deletions(-) diff --git a/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql b/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql index 7ffc47e50f..b81cf2dc64 100644 --- a/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql +++ b/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql @@ -16,17 +16,21 @@ import cpp import codingstandards.cpp.autosar -newtype TTemplatedElement = - TClassTemplate(TemplateClass c) or - TFunctionTemplate(TemplateFunction f) or - TVariableTemplate(TemplateVariable v) +newtype TTemplateElement = + TTemplateClass(TemplateClass c) or + TTemplateFunction(TemplateFunction f) or + TTemplateVariable(TemplateVariable v) -class TemplatedElement extends TTemplatedElement { - TemplateClass asTemplateClass() { this = TClassTemplate(result) } +/** + * A templated element. These are either templated classes, templated functions, + * or templated variables. + */ +class TemplateElement extends TTemplateElement { + TemplateClass asTemplateClass() { this = TTemplateClass(result) } - TemplateFunction asTemplateFunction() { this = TFunctionTemplate(result) } + TemplateFunction asTemplateFunction() { this = TTemplateFunction(result) } - TemplateVariable asTemplateVariable() { this = TVariableTemplate(result) } + TemplateVariable asTemplateVariable() { this = TTemplateVariable(result) } string toString() { result = this.asTemplateClass().toString() or @@ -52,6 +56,10 @@ newtype TTemplateInstantiation = TFunctionTemplateInstantiation(FunctionTemplateInstantiation f) or TVariableTemplateInstantiation(VariableTemplateInstantiation v) +/** + * An instantiation of a templated element, either a templated class, templated + * function, or templated variable. + */ class TemplateInstantiation extends TTemplateInstantiation { ClassTemplateInstantiation asClassTemplateInstantiation() { this = TClassTemplateInstantiation(result) @@ -83,7 +91,11 @@ class TemplateInstantiation extends TTemplateInstantiation { result = this.asVariableTemplateInstantiation() } - TemplatedElement getTemplate() { + /** + * Gets the template this instantiation is from, depending on the kind of the element + * this instantiation is for. + */ + TemplateElement getTemplate() { result.asTemplateClass() = this.asClassTemplateInstantiation().getTemplate() or result.asTemplateFunction() = this.asFunctionTemplateInstantiation().getTemplate() or result.asTemplateVariable() = this.asVariableTemplateInstantiation().getTemplate() @@ -102,6 +114,13 @@ class TemplateInstantiation extends TTemplateInstantiation { } } +/** + * An implicit conversion from a plain char type to an explicitly signed or unsigned char + * type. `std::uint8_t` and `std::int8_t` are also considered as these char types. + * + * Note that this class only includes implicit conversions and does not include explicit + * type conversions, i.e. casts. + */ class ImplicitConversionFromPlainCharType extends Conversion { ImplicitConversionFromPlainCharType() { this.isImplicit() and @@ -126,6 +145,16 @@ newtype TImplicitConversionElement = implicitConversion.getEnclosingElement+() = templateInstantiation.asElement() } +/** + * The locations where the implicit conversion from a plain char to an explicitly signed / unsigned + * char is taking place on a high level. It splits case on whether the conversion is caused by + * instantiating a template: + * + * - For conversions not due to template usage (i.e. outside a templated element), this refers to + * the same element as the one associated with the conversion. + * - For conversions due to template usage, this refers to the element that uses the instantiation + * of a template where an implicit char conversion happens. + */ class ImplicitConversionLocation extends TImplicitConversionElement { ImplicitConversionFromPlainCharType asImplicitConversionOutsideTemplate() { this = TImplicitConversionOutsideTemplate(result) @@ -137,10 +166,17 @@ class ImplicitConversionLocation extends TImplicitConversionElement { this = TInstantiationOfImplicitConversionTemplate(result, implicitConversion) } + /** + * Holds if this is a location of a conversion happening outside of a template. + */ predicate isImplicitConversionOutsideTemplate() { exists(this.asImplicitConversionOutsideTemplate()) } + /** + * Holds if this is a location of a conversion happening due to instantiating a + * template. + */ predicate isInstantiationOfImplicitConversionTemplate() { exists( TemplateInstantiation templateInstantiation, @@ -150,6 +186,13 @@ class ImplicitConversionLocation extends TImplicitConversionElement { ) } + /** + * Gets the implicit conversion that this location is associated with. + * - In cases of conversions not involving a template, this is the same as the + * location associated with the conversion. + * - In cases of conversions due to using a template, this is the conversion that + * happens in the instantiated template. + */ ImplicitConversionFromPlainCharType getImplicitConversion() { result = this.asImplicitConversionOutsideTemplate() or exists(TemplateInstantiation templateInstantiation | From f3cee16926b6b78f14da4680e8c5b10a052f0fed Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Mon, 14 Jul 2025 11:13:11 -0400 Subject: [PATCH 358/370] Add cases of template variable instantiation --- ...orTheStorageAndUseOfNumericValues.expected | 52 ++++++++++--------- cpp/autosar/test/rules/M5-0-12/test.cpp | 23 ++++++++ 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected b/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected index d5dc9af7e8..d0aeaebd41 100644 --- a/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected +++ b/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected @@ -1,24 +1,28 @@ -| test.cpp:98:7:98:8 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:98:7:98:8 | x3 | expression | -| test.cpp:101:20:101:21 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:101:20:101:21 | x4 | expression | -| test.cpp:111:21:111:22 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:111:21:111:22 | x7 | expression | -| test.cpp:114:20:114:21 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:114:20:114:21 | x8 | expression | -| test.cpp:124:17:124:18 | definition of c3 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'C1'. | test.cpp:5:12:5:12 | 120 | expression | -| test.cpp:127:17:127:18 | definition of c4 | Implicit conversion of plain char $@ to signed char from instantiating template 'C2'. | test.cpp:13:12:13:12 | 120 | expression | -| test.cpp:137:15:137:16 | definition of c7 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'C5'. | test.cpp:22:12:22:12 | 1 | expression | -| test.cpp:140:15:140:16 | definition of c8 | Implicit conversion of plain char $@ to int8_t from instantiating template 'C6'. | test.cpp:30:12:30:12 | 1 | expression | -| test.cpp:157:7:157:10 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:157:7:157:10 | * ... | expression | -| test.cpp:162:7:162:10 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:162:7:162:10 | * ... | expression | -| test.cpp:177:7:177:10 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:177:7:177:10 | * ... | expression | -| test.cpp:182:7:182:10 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:182:7:182:10 | * ... | expression | -| test.cpp:196:6:196:7 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:196:6:196:7 | a3 | expression | -| test.cpp:199:6:199:7 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:199:6:199:7 | a4 | expression | -| test.cpp:209:6:209:7 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:209:6:209:7 | a7 | expression | -| test.cpp:212:7:212:8 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:212:7:212:8 | a8 | expression | -| test.cpp:226:3:226:4 | call to f5 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'f5'. | test.cpp:43:56:43:56 | x | expression | -| test.cpp:230:3:230:4 | call to f6 | Implicit conversion of plain char $@ to signed char from instantiating template 'f6'. | test.cpp:44:54:44:54 | x | expression | -| test.cpp:243:3:243:5 | call to f13 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'f13'. | test.cpp:47:56:47:56 | x | expression | -| test.cpp:247:3:247:5 | call to f14 | Implicit conversion of plain char $@ to int8_t from instantiating template 'f14'. | test.cpp:48:55:48:55 | x | expression | -| test.cpp:264:12:264:14 | definition of c11 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'C9'. | test.cpp:52:15:52:15 | y | expression | -| test.cpp:269:13:269:15 | definition of c12 | Implicit conversion of plain char $@ to signed char from instantiating template 'C10'. | test.cpp:60:16:60:16 | y | expression | -| test.cpp:284:13:284:15 | definition of c15 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'C13'. | test.cpp:69:16:69:16 | y | expression | -| test.cpp:288:13:288:15 | definition of c16 | Implicit conversion of plain char $@ to int8_t from instantiating template 'C14'. | test.cpp:77:16:77:16 | y | expression | +| test.cpp:93:7:93:9 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:93:7:93:9 | 118 | expression | +| test.cpp:94:21:94:23 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:94:21:94:23 | 118 | expression | +| test.cpp:102:7:102:9 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:102:7:102:9 | 118 | expression | +| test.cpp:103:21:103:23 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:103:21:103:23 | 118 | expression | +| test.cpp:121:7:121:8 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:121:7:121:8 | x3 | expression | +| test.cpp:124:20:124:21 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:124:20:124:21 | x4 | expression | +| test.cpp:134:21:134:22 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:134:21:134:22 | x7 | expression | +| test.cpp:137:20:137:21 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:137:20:137:21 | x8 | expression | +| test.cpp:147:17:147:18 | definition of c3 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'C1'. | test.cpp:5:12:5:12 | 120 | expression | +| test.cpp:150:17:150:18 | definition of c4 | Implicit conversion of plain char $@ to signed char from instantiating template 'C2'. | test.cpp:13:12:13:12 | 120 | expression | +| test.cpp:160:15:160:16 | definition of c7 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'C5'. | test.cpp:22:12:22:12 | 1 | expression | +| test.cpp:163:15:163:16 | definition of c8 | Implicit conversion of plain char $@ to int8_t from instantiating template 'C6'. | test.cpp:30:12:30:12 | 1 | expression | +| test.cpp:180:7:180:10 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:180:7:180:10 | * ... | expression | +| test.cpp:185:7:185:10 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:185:7:185:10 | * ... | expression | +| test.cpp:200:7:200:10 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:200:7:200:10 | * ... | expression | +| test.cpp:205:7:205:10 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:205:7:205:10 | * ... | expression | +| test.cpp:219:6:219:7 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:219:6:219:7 | a3 | expression | +| test.cpp:222:6:222:7 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:222:6:222:7 | a4 | expression | +| test.cpp:232:6:232:7 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:232:6:232:7 | a7 | expression | +| test.cpp:235:7:235:8 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:235:7:235:8 | a8 | expression | +| test.cpp:249:3:249:4 | call to f5 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'f5'. | test.cpp:43:56:43:56 | x | expression | +| test.cpp:253:3:253:4 | call to f6 | Implicit conversion of plain char $@ to signed char from instantiating template 'f6'. | test.cpp:44:54:44:54 | x | expression | +| test.cpp:266:3:266:5 | call to f13 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'f13'. | test.cpp:47:56:47:56 | x | expression | +| test.cpp:270:3:270:5 | call to f14 | Implicit conversion of plain char $@ to int8_t from instantiating template 'f14'. | test.cpp:48:55:48:55 | x | expression | +| test.cpp:287:12:287:14 | definition of c11 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'C9'. | test.cpp:52:15:52:15 | y | expression | +| test.cpp:292:13:292:15 | definition of c12 | Implicit conversion of plain char $@ to signed char from instantiating template 'C10'. | test.cpp:60:16:60:16 | y | expression | +| test.cpp:307:13:307:15 | definition of c15 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'C13'. | test.cpp:69:16:69:16 | y | expression | +| test.cpp:311:13:311:15 | definition of c16 | Implicit conversion of plain char $@ to int8_t from instantiating template 'C14'. | test.cpp:77:16:77:16 | y | expression | diff --git a/cpp/autosar/test/rules/M5-0-12/test.cpp b/cpp/autosar/test/rules/M5-0-12/test.cpp index 0fe008436c..037c57da13 100644 --- a/cpp/autosar/test/rules/M5-0-12/test.cpp +++ b/cpp/autosar/test/rules/M5-0-12/test.cpp @@ -80,6 +80,29 @@ template class C14 { std::int8_t x; }; +template T v1; +template T v2; + +void instantiateTemplateVariables() { + v1 = + 1; // COMPLIANT: unsigned char assigned to an unsigned char + v2 = 1; // COMPLIANT: signed char assigned to a signed char + v2 = 'v'; // COMPLIANT: signed char assigned to a signed char + + v1 = + 'v'; // NON-COMPLIANT: plain char assigned to an unsigned char + v2 = 'v'; // NON-COMPLIANT: plain char assigned to a signed char + + /* Twin cases with std::uint8_t and std::int8_t */ + v1 = 1; // COMPLIANT: std::uint8_t assigned to a std::uint8_t + v2 = 1; // COMPLIANT: std::int8_t assigned to a std::int8_t + v2 = 'v'; // COMPLIANT: signed char assigned to a signed char + + v1 = + 'v'; // NON-COMPLIANT: plain char assigned to a std::uint8_t + v2 = 'v'; // NON-COMPLIANT: plain char assigned to a std::int8_t +} + int main() { /* ========== 1. Assigning a char to another char ========== */ From bb2ad888ad067ff3b75dad57a5516d92ca04830b Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Mon, 14 Jul 2025 11:18:29 -0400 Subject: [PATCH 359/370] Surround type name with single quotes in alert message --- ...eUsedForTheStorageAndUseOfNumericValues.ql | 6 +- ...orTheStorageAndUseOfNumericValues.expected | 56 +++++++++---------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql b/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql index b81cf2dc64..e6852d7d39 100644 --- a/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql +++ b/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql @@ -228,12 +228,12 @@ string getMessageTemplate(ImplicitConversionLocation implicitConversionLocation) | implicitConversionLocation.isImplicitConversionOutsideTemplate() and result = - "Implicit conversion of plain char $@ to " + implicitConversion.getType().getName() + "." + "Implicit conversion of plain char $@ to '" + implicitConversion.getType().getName() + "'." or implicitConversionLocation.isInstantiationOfImplicitConversionTemplate() and result = - "Implicit conversion of plain char $@ to " + implicitConversion.getType().getName() + - " from instantiating template '" + + "Implicit conversion of plain char $@ to '" + implicitConversion.getType().getName() + + "' from instantiating template '" + implicitConversionLocation .asInstantiationOfImplicitConversionTemplate(implicitConversion) .getTemplate() diff --git a/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected b/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected index d0aeaebd41..ad1f57935e 100644 --- a/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected +++ b/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected @@ -1,28 +1,28 @@ -| test.cpp:93:7:93:9 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:93:7:93:9 | 118 | expression | -| test.cpp:94:21:94:23 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:94:21:94:23 | 118 | expression | -| test.cpp:102:7:102:9 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:102:7:102:9 | 118 | expression | -| test.cpp:103:21:103:23 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:103:21:103:23 | 118 | expression | -| test.cpp:121:7:121:8 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:121:7:121:8 | x3 | expression | -| test.cpp:124:20:124:21 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:124:20:124:21 | x4 | expression | -| test.cpp:134:21:134:22 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:134:21:134:22 | x7 | expression | -| test.cpp:137:20:137:21 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:137:20:137:21 | x8 | expression | -| test.cpp:147:17:147:18 | definition of c3 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'C1'. | test.cpp:5:12:5:12 | 120 | expression | -| test.cpp:150:17:150:18 | definition of c4 | Implicit conversion of plain char $@ to signed char from instantiating template 'C2'. | test.cpp:13:12:13:12 | 120 | expression | -| test.cpp:160:15:160:16 | definition of c7 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'C5'. | test.cpp:22:12:22:12 | 1 | expression | -| test.cpp:163:15:163:16 | definition of c8 | Implicit conversion of plain char $@ to int8_t from instantiating template 'C6'. | test.cpp:30:12:30:12 | 1 | expression | -| test.cpp:180:7:180:10 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:180:7:180:10 | * ... | expression | -| test.cpp:185:7:185:10 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:185:7:185:10 | * ... | expression | -| test.cpp:200:7:200:10 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:200:7:200:10 | * ... | expression | -| test.cpp:205:7:205:10 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:205:7:205:10 | * ... | expression | -| test.cpp:219:6:219:7 | (unsigned char)... | Implicit conversion of plain char $@ to unsigned char. | test.cpp:219:6:219:7 | a3 | expression | -| test.cpp:222:6:222:7 | (signed char)... | Implicit conversion of plain char $@ to signed char. | test.cpp:222:6:222:7 | a4 | expression | -| test.cpp:232:6:232:7 | (uint8_t)... | Implicit conversion of plain char $@ to uint8_t. | test.cpp:232:6:232:7 | a7 | expression | -| test.cpp:235:7:235:8 | (int8_t)... | Implicit conversion of plain char $@ to int8_t. | test.cpp:235:7:235:8 | a8 | expression | -| test.cpp:249:3:249:4 | call to f5 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'f5'. | test.cpp:43:56:43:56 | x | expression | -| test.cpp:253:3:253:4 | call to f6 | Implicit conversion of plain char $@ to signed char from instantiating template 'f6'. | test.cpp:44:54:44:54 | x | expression | -| test.cpp:266:3:266:5 | call to f13 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'f13'. | test.cpp:47:56:47:56 | x | expression | -| test.cpp:270:3:270:5 | call to f14 | Implicit conversion of plain char $@ to int8_t from instantiating template 'f14'. | test.cpp:48:55:48:55 | x | expression | -| test.cpp:287:12:287:14 | definition of c11 | Implicit conversion of plain char $@ to unsigned char from instantiating template 'C9'. | test.cpp:52:15:52:15 | y | expression | -| test.cpp:292:13:292:15 | definition of c12 | Implicit conversion of plain char $@ to signed char from instantiating template 'C10'. | test.cpp:60:16:60:16 | y | expression | -| test.cpp:307:13:307:15 | definition of c15 | Implicit conversion of plain char $@ to uint8_t from instantiating template 'C13'. | test.cpp:69:16:69:16 | y | expression | -| test.cpp:311:13:311:15 | definition of c16 | Implicit conversion of plain char $@ to int8_t from instantiating template 'C14'. | test.cpp:77:16:77:16 | y | expression | +| test.cpp:93:7:93:9 | (unsigned char)... | Implicit conversion of plain char $@ to 'unsigned char'. | test.cpp:93:7:93:9 | 118 | expression | +| test.cpp:94:21:94:23 | (signed char)... | Implicit conversion of plain char $@ to 'signed char'. | test.cpp:94:21:94:23 | 118 | expression | +| test.cpp:102:7:102:9 | (unsigned char)... | Implicit conversion of plain char $@ to 'unsigned char'. | test.cpp:102:7:102:9 | 118 | expression | +| test.cpp:103:21:103:23 | (signed char)... | Implicit conversion of plain char $@ to 'signed char'. | test.cpp:103:21:103:23 | 118 | expression | +| test.cpp:121:7:121:8 | (unsigned char)... | Implicit conversion of plain char $@ to 'unsigned char'. | test.cpp:121:7:121:8 | x3 | expression | +| test.cpp:124:20:124:21 | (signed char)... | Implicit conversion of plain char $@ to 'signed char'. | test.cpp:124:20:124:21 | x4 | expression | +| test.cpp:134:21:134:22 | (uint8_t)... | Implicit conversion of plain char $@ to 'uint8_t'. | test.cpp:134:21:134:22 | x7 | expression | +| test.cpp:137:20:137:21 | (int8_t)... | Implicit conversion of plain char $@ to 'int8_t'. | test.cpp:137:20:137:21 | x8 | expression | +| test.cpp:147:17:147:18 | definition of c3 | Implicit conversion of plain char $@ to 'unsigned char' from instantiating template 'C1'. | test.cpp:5:12:5:12 | 120 | expression | +| test.cpp:150:17:150:18 | definition of c4 | Implicit conversion of plain char $@ to 'signed char' from instantiating template 'C2'. | test.cpp:13:12:13:12 | 120 | expression | +| test.cpp:160:15:160:16 | definition of c7 | Implicit conversion of plain char $@ to 'uint8_t' from instantiating template 'C5'. | test.cpp:22:12:22:12 | 1 | expression | +| test.cpp:163:15:163:16 | definition of c8 | Implicit conversion of plain char $@ to 'int8_t' from instantiating template 'C6'. | test.cpp:30:12:30:12 | 1 | expression | +| test.cpp:180:7:180:10 | (unsigned char)... | Implicit conversion of plain char $@ to 'unsigned char'. | test.cpp:180:7:180:10 | * ... | expression | +| test.cpp:185:7:185:10 | (signed char)... | Implicit conversion of plain char $@ to 'signed char'. | test.cpp:185:7:185:10 | * ... | expression | +| test.cpp:200:7:200:10 | (uint8_t)... | Implicit conversion of plain char $@ to 'uint8_t'. | test.cpp:200:7:200:10 | * ... | expression | +| test.cpp:205:7:205:10 | (int8_t)... | Implicit conversion of plain char $@ to 'int8_t'. | test.cpp:205:7:205:10 | * ... | expression | +| test.cpp:219:6:219:7 | (unsigned char)... | Implicit conversion of plain char $@ to 'unsigned char'. | test.cpp:219:6:219:7 | a3 | expression | +| test.cpp:222:6:222:7 | (signed char)... | Implicit conversion of plain char $@ to 'signed char'. | test.cpp:222:6:222:7 | a4 | expression | +| test.cpp:232:6:232:7 | (uint8_t)... | Implicit conversion of plain char $@ to 'uint8_t'. | test.cpp:232:6:232:7 | a7 | expression | +| test.cpp:235:7:235:8 | (int8_t)... | Implicit conversion of plain char $@ to 'int8_t'. | test.cpp:235:7:235:8 | a8 | expression | +| test.cpp:249:3:249:4 | call to f5 | Implicit conversion of plain char $@ to 'unsigned char' from instantiating template 'f5'. | test.cpp:43:56:43:56 | x | expression | +| test.cpp:253:3:253:4 | call to f6 | Implicit conversion of plain char $@ to 'signed char' from instantiating template 'f6'. | test.cpp:44:54:44:54 | x | expression | +| test.cpp:266:3:266:5 | call to f13 | Implicit conversion of plain char $@ to 'uint8_t' from instantiating template 'f13'. | test.cpp:47:56:47:56 | x | expression | +| test.cpp:270:3:270:5 | call to f14 | Implicit conversion of plain char $@ to 'int8_t' from instantiating template 'f14'. | test.cpp:48:55:48:55 | x | expression | +| test.cpp:287:12:287:14 | definition of c11 | Implicit conversion of plain char $@ to 'unsigned char' from instantiating template 'C9'. | test.cpp:52:15:52:15 | y | expression | +| test.cpp:292:13:292:15 | definition of c12 | Implicit conversion of plain char $@ to 'signed char' from instantiating template 'C10'. | test.cpp:60:16:60:16 | y | expression | +| test.cpp:307:13:307:15 | definition of c15 | Implicit conversion of plain char $@ to 'uint8_t' from instantiating template 'C13'. | test.cpp:69:16:69:16 | y | expression | +| test.cpp:311:13:311:15 | definition of c16 | Implicit conversion of plain char $@ to 'int8_t' from instantiating template 'C14'. | test.cpp:77:16:77:16 | y | expression | From a474ded139a11efb51548d2fd45ef8310f7f050e Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Mon, 14 Jul 2025 12:12:13 -0400 Subject: [PATCH 360/370] Minor editing of label --- cpp/autosar/test/rules/M5-0-12/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/autosar/test/rules/M5-0-12/test.cpp b/cpp/autosar/test/rules/M5-0-12/test.cpp index 037c57da13..3e9a21ae17 100644 --- a/cpp/autosar/test/rules/M5-0-12/test.cpp +++ b/cpp/autosar/test/rules/M5-0-12/test.cpp @@ -87,7 +87,7 @@ void instantiateTemplateVariables() { v1 = 1; // COMPLIANT: unsigned char assigned to an unsigned char v2 = 1; // COMPLIANT: signed char assigned to a signed char - v2 = 'v'; // COMPLIANT: signed char assigned to a signed char + v2 = 'v'; // COMPLIANT: plain char assigned to a plain char v1 = 'v'; // NON-COMPLIANT: plain char assigned to an unsigned char @@ -96,7 +96,7 @@ void instantiateTemplateVariables() { /* Twin cases with std::uint8_t and std::int8_t */ v1 = 1; // COMPLIANT: std::uint8_t assigned to a std::uint8_t v2 = 1; // COMPLIANT: std::int8_t assigned to a std::int8_t - v2 = 'v'; // COMPLIANT: signed char assigned to a signed char + v2 = 'v'; // COMPLIANT: plain char assigned to a plain char v1 = 'v'; // NON-COMPLIANT: plain char assigned to a std::uint8_t From 2991f6f8ab337f63127f5d5a60e4812068d86315 Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Tue, 15 Jul 2025 12:21:30 -0400 Subject: [PATCH 361/370] Remove handling of template cases --- ...eUsedForTheStorageAndUseOfNumericValues.ql | 245 +----------------- 1 file changed, 13 insertions(+), 232 deletions(-) diff --git a/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql b/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql index e6852d7d39..bc3563559b 100644 --- a/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql +++ b/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql @@ -16,237 +16,18 @@ import cpp import codingstandards.cpp.autosar -newtype TTemplateElement = - TTemplateClass(TemplateClass c) or - TTemplateFunction(TemplateFunction f) or - TTemplateVariable(TemplateVariable v) - -/** - * A templated element. These are either templated classes, templated functions, - * or templated variables. - */ -class TemplateElement extends TTemplateElement { - TemplateClass asTemplateClass() { this = TTemplateClass(result) } - - TemplateFunction asTemplateFunction() { this = TTemplateFunction(result) } - - TemplateVariable asTemplateVariable() { this = TTemplateVariable(result) } - - string toString() { - result = this.asTemplateClass().toString() or - result = this.asTemplateFunction().toString() or - result = this.asTemplateVariable().toString() - } - - Location getLocation() { - result = this.asTemplateClass().getLocation() or - result = this.asTemplateFunction().getLocation() or - result = this.asTemplateVariable().getLocation() - } - - string getName() { - result = this.asTemplateClass().getName() or - result = this.asTemplateFunction().getName() or - result = this.asTemplateVariable().getName() - } -} - -newtype TTemplateInstantiation = - TClassTemplateInstantiation(ClassTemplateInstantiation c) or - TFunctionTemplateInstantiation(FunctionTemplateInstantiation f) or - TVariableTemplateInstantiation(VariableTemplateInstantiation v) - -/** - * An instantiation of a templated element, either a templated class, templated - * function, or templated variable. - */ -class TemplateInstantiation extends TTemplateInstantiation { - ClassTemplateInstantiation asClassTemplateInstantiation() { - this = TClassTemplateInstantiation(result) - } - - FunctionTemplateInstantiation asFunctionTemplateInstantiation() { - this = TFunctionTemplateInstantiation(result) - } - - VariableTemplateInstantiation asVariableTemplateInstantiation() { - this = TVariableTemplateInstantiation(result) - } - - string toString() { - result = this.asClassTemplateInstantiation().toString() or - result = this.asFunctionTemplateInstantiation().toString() or - result = this.asVariableTemplateInstantiation().toString() - } - - Location getLocation() { - result = this.asClassTemplateInstantiation().getLocation() or - result = this.asFunctionTemplateInstantiation().getLocation() or - result = this.asVariableTemplateInstantiation().getLocation() - } - - Element asElement() { - result = this.asClassTemplateInstantiation() or - result = this.asFunctionTemplateInstantiation() or - result = this.asVariableTemplateInstantiation() - } - - /** - * Gets the template this instantiation is from, depending on the kind of the element - * this instantiation is for. - */ - TemplateElement getTemplate() { - result.asTemplateClass() = this.asClassTemplateInstantiation().getTemplate() or - result.asTemplateFunction() = this.asFunctionTemplateInstantiation().getTemplate() or - result.asTemplateVariable() = this.asVariableTemplateInstantiation().getTemplate() - } - - /** - * Gets a use of an instantiation of this template. i.e. - * 1. For a class template, it's where the instantiated type is used by the name. - * 2. For a function template, it's where the instantiated function is called. - * 3. For a variable template, it's where the instantiated variable is initialized. - */ - Element getAUse() { - result = this.asClassTemplateInstantiation().getATypeNameUse() or - result = this.asFunctionTemplateInstantiation().getACallToThisFunction() or - result = this.asVariableTemplateInstantiation() - } -} - -/** - * An implicit conversion from a plain char type to an explicitly signed or unsigned char - * type. `std::uint8_t` and `std::int8_t` are also considered as these char types. - * - * Note that this class only includes implicit conversions and does not include explicit - * type conversions, i.e. casts. - */ -class ImplicitConversionFromPlainCharType extends Conversion { - ImplicitConversionFromPlainCharType() { - this.isImplicit() and - this.getExpr().getUnspecifiedType() instanceof PlainCharType and - ( - this.getUnspecifiedType() instanceof SignedCharType or - this.getUnspecifiedType() instanceof UnsignedCharType - ) - } -} - -newtype TImplicitConversionElement = - TImplicitConversionOutsideTemplate(ImplicitConversionFromPlainCharType implicitConversion) { - not exists(TemplateInstantiation instantiation | - implicitConversion.isFromTemplateInstantiation(instantiation.asElement()) - ) - } or - TInstantiationOfImplicitConversionTemplate( - TemplateInstantiation templateInstantiation, - ImplicitConversionFromPlainCharType implicitConversion - ) { - implicitConversion.getEnclosingElement+() = templateInstantiation.asElement() - } - -/** - * The locations where the implicit conversion from a plain char to an explicitly signed / unsigned - * char is taking place on a high level. It splits case on whether the conversion is caused by - * instantiating a template: - * - * - For conversions not due to template usage (i.e. outside a templated element), this refers to - * the same element as the one associated with the conversion. - * - For conversions due to template usage, this refers to the element that uses the instantiation - * of a template where an implicit char conversion happens. - */ -class ImplicitConversionLocation extends TImplicitConversionElement { - ImplicitConversionFromPlainCharType asImplicitConversionOutsideTemplate() { - this = TImplicitConversionOutsideTemplate(result) - } - - TemplateInstantiation asInstantiationOfImplicitConversionTemplate( - ImplicitConversionFromPlainCharType implicitConversion - ) { - this = TInstantiationOfImplicitConversionTemplate(result, implicitConversion) - } - - /** - * Holds if this is a location of a conversion happening outside of a template. - */ - predicate isImplicitConversionOutsideTemplate() { - exists(this.asImplicitConversionOutsideTemplate()) - } - - /** - * Holds if this is a location of a conversion happening due to instantiating a - * template. - */ - predicate isInstantiationOfImplicitConversionTemplate() { - exists( - TemplateInstantiation templateInstantiation, - ImplicitConversionFromPlainCharType implicitConversion - | - templateInstantiation = this.asInstantiationOfImplicitConversionTemplate(implicitConversion) - ) - } - - /** - * Gets the implicit conversion that this location is associated with. - * - In cases of conversions not involving a template, this is the same as the - * location associated with the conversion. - * - In cases of conversions due to using a template, this is the conversion that - * happens in the instantiated template. - */ - ImplicitConversionFromPlainCharType getImplicitConversion() { - result = this.asImplicitConversionOutsideTemplate() or - exists(TemplateInstantiation templateInstantiation | - this = TInstantiationOfImplicitConversionTemplate(templateInstantiation, result) - ) - } - - string toString() { - result = this.asImplicitConversionOutsideTemplate().toString() or - exists(ImplicitConversionFromPlainCharType implicitConversion | - result = this.asInstantiationOfImplicitConversionTemplate(implicitConversion).toString() - ) - } - - Location getLocation() { - result = this.asImplicitConversionOutsideTemplate().getLocation() or - exists(ImplicitConversionFromPlainCharType implicitConversion | - result = this.asInstantiationOfImplicitConversionTemplate(implicitConversion).getLocation() - ) - } - - Element asElement() { - result = this.asImplicitConversionOutsideTemplate() or - exists(ImplicitConversionFromPlainCharType implicitConversion | - result = this.asInstantiationOfImplicitConversionTemplate(implicitConversion).getAUse() - ) - } -} - -string getMessageTemplate(ImplicitConversionLocation implicitConversionLocation) { - exists(ImplicitConversionFromPlainCharType implicitConversion | - implicitConversion = implicitConversionLocation.getImplicitConversion() - | - implicitConversionLocation.isImplicitConversionOutsideTemplate() and - result = - "Implicit conversion of plain char $@ to '" + implicitConversion.getType().getName() + "'." - or - implicitConversionLocation.isInstantiationOfImplicitConversionTemplate() and - result = - "Implicit conversion of plain char $@ to '" + implicitConversion.getType().getName() + - "' from instantiating template '" + - implicitConversionLocation - .asInstantiationOfImplicitConversionTemplate(implicitConversion) - .getTemplate() - .getName() + "'." - ) -} - -from - ImplicitConversionLocation implicitConversionLocation, - ImplicitConversionFromPlainCharType implicitConversion +from Conversion c where - not isExcluded(implicitConversionLocation.asElement(), + not isExcluded(c, StringsPackage::signedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValuesQuery()) and - implicitConversion = implicitConversionLocation.getImplicitConversion() -select implicitConversionLocation.asElement(), getMessageTemplate(implicitConversionLocation), - implicitConversion.getExpr(), "expression" + /* 1. Focus on implicit conversions only (explicit conversions are acceptable). */ + c.isImplicit() and + /* 2. The target type is explicitly signed or unsigned char. */ + ( + c.getUnspecifiedType() instanceof SignedCharType or + c.getUnspecifiedType() instanceof UnsignedCharType + ) and + /* 3. Check if the source expression is a plain char type, i.e. not explicitly signed / unsigned. */ + c.getExpr().getUnspecifiedType() instanceof PlainCharType +select c, "Implicit conversion of plain char type to $@ with an explicitly signed char type", c, + c.getUnspecifiedType().getName() From 8dbaa1baa2735f1c2724cd58f743df50cfcbbc43 Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Tue, 15 Jul 2025 12:50:14 -0400 Subject: [PATCH 362/370] Remove templates from the coverage of the query Templates are tricky issue; we'd like to address this in a different PR. --- ...eUsedForTheStorageAndUseOfNumericValues.ql | 5 +- ...orTheStorageAndUseOfNumericValues.expected | 44 ++-- cpp/autosar/test/rules/M5-0-12/test.cpp | 193 +++--------------- 3 files changed, 44 insertions(+), 198 deletions(-) diff --git a/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql b/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql index bc3563559b..8e48c05ada 100644 --- a/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql +++ b/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql @@ -29,5 +29,6 @@ where ) and /* 3. Check if the source expression is a plain char type, i.e. not explicitly signed / unsigned. */ c.getExpr().getUnspecifiedType() instanceof PlainCharType -select c, "Implicit conversion of plain char type to $@ with an explicitly signed char type", c, - c.getUnspecifiedType().getName() +select c, + "This expression of plain char type is implicitly converted to '" + + c.getUnspecifiedType().getName() + "'." diff --git a/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected b/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected index ad1f57935e..b23be388c6 100644 --- a/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected +++ b/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected @@ -1,28 +1,16 @@ -| test.cpp:93:7:93:9 | (unsigned char)... | Implicit conversion of plain char $@ to 'unsigned char'. | test.cpp:93:7:93:9 | 118 | expression | -| test.cpp:94:21:94:23 | (signed char)... | Implicit conversion of plain char $@ to 'signed char'. | test.cpp:94:21:94:23 | 118 | expression | -| test.cpp:102:7:102:9 | (unsigned char)... | Implicit conversion of plain char $@ to 'unsigned char'. | test.cpp:102:7:102:9 | 118 | expression | -| test.cpp:103:21:103:23 | (signed char)... | Implicit conversion of plain char $@ to 'signed char'. | test.cpp:103:21:103:23 | 118 | expression | -| test.cpp:121:7:121:8 | (unsigned char)... | Implicit conversion of plain char $@ to 'unsigned char'. | test.cpp:121:7:121:8 | x3 | expression | -| test.cpp:124:20:124:21 | (signed char)... | Implicit conversion of plain char $@ to 'signed char'. | test.cpp:124:20:124:21 | x4 | expression | -| test.cpp:134:21:134:22 | (uint8_t)... | Implicit conversion of plain char $@ to 'uint8_t'. | test.cpp:134:21:134:22 | x7 | expression | -| test.cpp:137:20:137:21 | (int8_t)... | Implicit conversion of plain char $@ to 'int8_t'. | test.cpp:137:20:137:21 | x8 | expression | -| test.cpp:147:17:147:18 | definition of c3 | Implicit conversion of plain char $@ to 'unsigned char' from instantiating template 'C1'. | test.cpp:5:12:5:12 | 120 | expression | -| test.cpp:150:17:150:18 | definition of c4 | Implicit conversion of plain char $@ to 'signed char' from instantiating template 'C2'. | test.cpp:13:12:13:12 | 120 | expression | -| test.cpp:160:15:160:16 | definition of c7 | Implicit conversion of plain char $@ to 'uint8_t' from instantiating template 'C5'. | test.cpp:22:12:22:12 | 1 | expression | -| test.cpp:163:15:163:16 | definition of c8 | Implicit conversion of plain char $@ to 'int8_t' from instantiating template 'C6'. | test.cpp:30:12:30:12 | 1 | expression | -| test.cpp:180:7:180:10 | (unsigned char)... | Implicit conversion of plain char $@ to 'unsigned char'. | test.cpp:180:7:180:10 | * ... | expression | -| test.cpp:185:7:185:10 | (signed char)... | Implicit conversion of plain char $@ to 'signed char'. | test.cpp:185:7:185:10 | * ... | expression | -| test.cpp:200:7:200:10 | (uint8_t)... | Implicit conversion of plain char $@ to 'uint8_t'. | test.cpp:200:7:200:10 | * ... | expression | -| test.cpp:205:7:205:10 | (int8_t)... | Implicit conversion of plain char $@ to 'int8_t'. | test.cpp:205:7:205:10 | * ... | expression | -| test.cpp:219:6:219:7 | (unsigned char)... | Implicit conversion of plain char $@ to 'unsigned char'. | test.cpp:219:6:219:7 | a3 | expression | -| test.cpp:222:6:222:7 | (signed char)... | Implicit conversion of plain char $@ to 'signed char'. | test.cpp:222:6:222:7 | a4 | expression | -| test.cpp:232:6:232:7 | (uint8_t)... | Implicit conversion of plain char $@ to 'uint8_t'. | test.cpp:232:6:232:7 | a7 | expression | -| test.cpp:235:7:235:8 | (int8_t)... | Implicit conversion of plain char $@ to 'int8_t'. | test.cpp:235:7:235:8 | a8 | expression | -| test.cpp:249:3:249:4 | call to f5 | Implicit conversion of plain char $@ to 'unsigned char' from instantiating template 'f5'. | test.cpp:43:56:43:56 | x | expression | -| test.cpp:253:3:253:4 | call to f6 | Implicit conversion of plain char $@ to 'signed char' from instantiating template 'f6'. | test.cpp:44:54:44:54 | x | expression | -| test.cpp:266:3:266:5 | call to f13 | Implicit conversion of plain char $@ to 'uint8_t' from instantiating template 'f13'. | test.cpp:47:56:47:56 | x | expression | -| test.cpp:270:3:270:5 | call to f14 | Implicit conversion of plain char $@ to 'int8_t' from instantiating template 'f14'. | test.cpp:48:55:48:55 | x | expression | -| test.cpp:287:12:287:14 | definition of c11 | Implicit conversion of plain char $@ to 'unsigned char' from instantiating template 'C9'. | test.cpp:52:15:52:15 | y | expression | -| test.cpp:292:13:292:15 | definition of c12 | Implicit conversion of plain char $@ to 'signed char' from instantiating template 'C10'. | test.cpp:60:16:60:16 | y | expression | -| test.cpp:307:13:307:15 | definition of c15 | Implicit conversion of plain char $@ to 'uint8_t' from instantiating template 'C13'. | test.cpp:69:16:69:16 | y | expression | -| test.cpp:311:13:311:15 | definition of c16 | Implicit conversion of plain char $@ to 'int8_t' from instantiating template 'C14'. | test.cpp:77:16:77:16 | y | expression | +| test.cpp:58:7:58:8 | (unsigned char)... | This expression of plain char type is implicitly converted to 'unsigned char'. | +| test.cpp:61:20:61:21 | (signed char)... | This expression of plain char type is implicitly converted to 'signed char'. | +| test.cpp:71:21:71:22 | (uint8_t)... | This expression of plain char type is implicitly converted to 'unsigned char'. | +| test.cpp:74:20:74:21 | (int8_t)... | This expression of plain char type is implicitly converted to 'signed char'. | +| test.cpp:84:9:84:11 | (unsigned char)... | This expression of plain char type is implicitly converted to 'unsigned char'. | +| test.cpp:87:9:87:11 | (signed char)... | This expression of plain char type is implicitly converted to 'signed char'. | +| test.cpp:97:9:97:11 | (unsigned char)... | This expression of plain char type is implicitly converted to 'unsigned char'. | +| test.cpp:100:9:100:11 | (signed char)... | This expression of plain char type is implicitly converted to 'signed char'. | +| test.cpp:117:7:117:10 | (unsigned char)... | This expression of plain char type is implicitly converted to 'unsigned char'. | +| test.cpp:122:7:122:10 | (signed char)... | This expression of plain char type is implicitly converted to 'signed char'. | +| test.cpp:137:7:137:10 | (uint8_t)... | This expression of plain char type is implicitly converted to 'unsigned char'. | +| test.cpp:142:7:142:10 | (int8_t)... | This expression of plain char type is implicitly converted to 'signed char'. | +| test.cpp:153:6:153:7 | (unsigned char)... | This expression of plain char type is implicitly converted to 'unsigned char'. | +| test.cpp:156:6:156:7 | (signed char)... | This expression of plain char type is implicitly converted to 'signed char'. | +| test.cpp:166:6:166:7 | (uint8_t)... | This expression of plain char type is implicitly converted to 'unsigned char'. | +| test.cpp:169:7:169:8 | (int8_t)... | This expression of plain char type is implicitly converted to 'signed char'. | diff --git a/cpp/autosar/test/rules/M5-0-12/test.cpp b/cpp/autosar/test/rules/M5-0-12/test.cpp index 3e9a21ae17..036db12b04 100644 --- a/cpp/autosar/test/rules/M5-0-12/test.cpp +++ b/cpp/autosar/test/rules/M5-0-12/test.cpp @@ -1,33 +1,33 @@ #include -template class C1 { +class C1 { public: - C1() : x(y) {} + C1(unsigned char y) : x(y) {} private: unsigned char x; }; -template class C2 { +class C2 { public: - C2() : x(y) {} + C2(signed char y) : x(y) {} private: signed char x; }; -/* Twin templates for std::uint8_t and std::int8_t */ -template class C5 { +/* Twin classes for std::uint8_t and std::int8_t */ +class C5 { public: - C5() : x(y) {} + C5(unsigned char y) : x(y) {} private: std::uint8_t x; }; -template class C6 { +class C6 { public: - C6() : x(y) {} + C6(signed char y) : x(y) {} private: std::int8_t x; @@ -40,69 +40,6 @@ void f2(signed char x) {} void f9(std::uint8_t x) {} void f10(std::int8_t x) {} -template void f5(T x) { unsigned char y = x; } -template void f6(T x) { signed char y = x; } - -/* Twin template functions for std::uint8_t and std::int8_t */ -template void f13(T x) { std::uint8_t y = x; } -template void f14(T x) { std::int8_t y = x; } - -template class C9 { -public: - C9(T y) : x(y) {} - -private: - unsigned char x; -}; - -template class C10 { -public: - C10(T y) : x(y) {} - -private: - signed char x; -}; - -/* Twin template classes for std::uint8_t and std::int8_t */ -template class C13 { -public: - C13(T y) : x(y) {} - -private: - std::uint8_t x; -}; - -template class C14 { -public: - C14(T y) : x(y) {} - -private: - std::int8_t x; -}; - -template T v1; -template T v2; - -void instantiateTemplateVariables() { - v1 = - 1; // COMPLIANT: unsigned char assigned to an unsigned char - v2 = 1; // COMPLIANT: signed char assigned to a signed char - v2 = 'v'; // COMPLIANT: plain char assigned to a plain char - - v1 = - 'v'; // NON-COMPLIANT: plain char assigned to an unsigned char - v2 = 'v'; // NON-COMPLIANT: plain char assigned to a signed char - - /* Twin cases with std::uint8_t and std::int8_t */ - v1 = 1; // COMPLIANT: std::uint8_t assigned to a std::uint8_t - v2 = 1; // COMPLIANT: std::int8_t assigned to a std::int8_t - v2 = 'v'; // COMPLIANT: plain char assigned to a plain char - - v1 = - 'v'; // NON-COMPLIANT: plain char assigned to a std::uint8_t - v2 = 'v'; // NON-COMPLIANT: plain char assigned to a std::int8_t -} - int main() { /* ========== 1. Assigning a char to another char ========== */ @@ -138,30 +75,30 @@ int main() { /* ===== 1-2. Assigning a char to a char member ===== */ - C1 c1; // COMPLIANT: unsigned char arg passed to an unsigned - // char member through a template + C1 c1(1); // COMPLIANT: unsigned char arg passed to an unsigned + // char member - C2 c2; // COMPLIANT: signed char arg passed to a signed char - // member through a template + C2 c2(1); // COMPLIANT: signed char arg passed to a signed char + // member - C1 c3; // NON-COMPLIANT: plain char arg passed to an unsigned char - // member through a template + C1 c3('x'); // NON-COMPLIANT: plain char arg passed to an unsigned char + // member - C2 c4; // NON-COMPLIANT: plain char arg passed to a signed char - // member through a template + C2 c4('x'); // NON-COMPLIANT: plain char arg passed to a signed char + // member /* Twin cases with std::uint8_t and std::int8_t */ - C5 c5; // COMPLIANT: std::uint8_t arg passed to a - // std::uint8_t member through a template + C5 c5(1); // COMPLIANT: std::uint8_t arg passed to a + // std::uint8_t member - C6 c6; // COMPLIANT: std::int8_t arg passed to a std::int8_t - // member through a template + C6 c6(1); // COMPLIANT: std::int8_t arg passed to a std::int8_t + // member - C5 c7; // NON-COMPLIANT: plain char arg passed to a - // std::uint8_t member through a template + C5 c7('x'); // NON-COMPLIANT: plain char arg passed to a + // std::uint8_t member - C6 c8; // NON-COMPLIANT: plain char arg passed to a std::int8_t - // member through a template + C6 c8('x'); // NON-COMPLIANT: plain char arg passed to a std::int8_t + // member /* ========== 1-3. Assigning a char to a char through a pointer ========== */ @@ -206,9 +143,6 @@ int main() { /* ========== 2. Passing a char argument to a char parameter ========== */ - /* ===== 2-1. Passing char argument to a char parameter of a regular function - * ===== */ - unsigned char a1 = 1; f1(a1); // COMPLIANT: unsigned char arg passed to an unsigned char parameter @@ -233,81 +167,4 @@ int main() { char a8 = 'a'; f10(a8); // NON-COMPLIANT: plain char arg passed to a std::int8_t parameter - - /* ===== 2-2. Passing char argument to a char parameter through a template - * ===== */ - - unsigned char a9 = 1; - f5(a9); // COMPLIANT: unsigned char arg passed to an unsigned char parameter - // through a template - - signed char a10 = 1; - f6(a10); // COMPLIANT: signed char arg passed to a signed char parameter - // through a template - - char a11 = 'a'; - f5(a11); // NON-COMPLIANT: plain char arg passed to an unsigned char parameter - // through a template - - char a12 = 'a'; - f6(a12); // NON-COMPLIANT: plain char arg passed to a signed char parameter - // through a template - - /* Twin cases with std::uint8_t and std::int8_t */ - std::uint8_t a13 = 1; - f13(a13); // COMPLIANT: std::uint8_t arg passed to a std::uint8_t parameter - // through a template - - std::int8_t a14 = 1; - f14(a14); // COMPLIANT: std::int8_t arg passed to a std::int8_t parameter - // through a template - - char a15 = 'a'; - f13(a15); // NON-COMPLIANT: plain char arg passed to a std::uint8_t parameter - // through a template - - char a16 = 'a'; - f14(a16); // NON-COMPLIANT: plain char arg passed to a std::int8_t parameter - // through a template - - /* ========== 2-3. Passing a char argument to a char parameter through a - * template ========== */ - - unsigned char a17 = 1; - C9 c9( - a17); // COMPLIANT: unsigned char arg passed to an unsigned char parameter - // of a constructor through a template - - signed char a18 = 1; - C10 c10( - a18); // COMPLIANT: signed char arg passed to an signed - // char parameter of a constructor through a template - - char a19 = 'a'; - C9 c11( - a19); // NON-COMPLIANT: plain char arg passed to an unsigned signed char - // parameter of a constructor through a template - - char a20 = 'a'; - C10 c12(a20); // NON-COMPLIANT: plain char arg passed to an signed char - // parameter of a constructor through a template - - /* Twin cases with std::uint8_t and std::int8_t */ - std::uint8_t a21 = 1; - C13 c13( - a21); // COMPLIANT: std::uint8_t arg passed to a std::uint8_t parameter - // of a constructor through a template - - std::int8_t a22 = 1; - C14 c14( - a22); // COMPLIANT: std::int8_t arg passed to a std::int8_t - // parameter of a constructor through a template - - char a23 = 'a'; - C13 c15(a23); // NON-COMPLIANT: plain char arg passed to a std::uint8_t - // parameter of a constructor through a template - - char a24 = 'a'; - C14 c16(a24); // NON-COMPLIANT: plain char arg passed to a std::int8_t - // parameter of a constructor through a template } From 7d1b27cc0f1914ed8979ca8b5b125fc73c42280c Mon Sep 17 00:00:00 2001 From: knewbury01 Date: Tue, 15 Jul 2025 19:02:45 +0000 Subject: [PATCH 363/370] Bump version to 2.49.0-dev --- c/cert/src/qlpack.yml | 2 +- c/cert/test/qlpack.yml | 2 +- c/common/src/qlpack.yml | 2 +- c/common/test/qlpack.yml | 2 +- c/misra/src/qlpack.yml | 2 +- c/misra/test/qlpack.yml | 2 +- cpp/autosar/src/qlpack.yml | 2 +- cpp/autosar/test/qlpack.yml | 2 +- cpp/cert/src/qlpack.yml | 2 +- cpp/cert/test/qlpack.yml | 2 +- cpp/common/src/qlpack.yml | 2 +- cpp/common/test/qlpack.yml | 2 +- cpp/misra/src/qlpack.yml | 2 +- cpp/misra/test/qlpack.yml | 2 +- cpp/report/src/qlpack.yml | 2 +- docs/user_manual.md | 12 ++++++------ 16 files changed, 21 insertions(+), 21 deletions(-) diff --git a/c/cert/src/qlpack.yml b/c/cert/src/qlpack.yml index d2ba0816a3..cff1e79631 100644 --- a/c/cert/src/qlpack.yml +++ b/c/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards -version: 2.48.0-dev +version: 2.49.0-dev description: CERT C 2016 suites: codeql-suites license: MIT diff --git a/c/cert/test/qlpack.yml b/c/cert/test/qlpack.yml index 98268c5636..9f5f21ba1b 100644 --- a/c/cert/test/qlpack.yml +++ b/c/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-c-coding-standards-tests -version: 2.48.0-dev +version: 2.49.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/common/src/qlpack.yml b/c/common/src/qlpack.yml index 4bbcb5c730..39adc407b9 100644 --- a/c/common/src/qlpack.yml +++ b/c/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards -version: 2.48.0-dev +version: 2.49.0-dev license: MIT dependencies: codeql/common-cpp-coding-standards: '*' diff --git a/c/common/test/qlpack.yml b/c/common/test/qlpack.yml index ce8d7b3ce7..da30625ddb 100644 --- a/c/common/test/qlpack.yml +++ b/c/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-c-coding-standards-tests -version: 2.48.0-dev +version: 2.49.0-dev extractor: cpp license: MIT dependencies: diff --git a/c/misra/src/qlpack.yml b/c/misra/src/qlpack.yml index 02f9dceb48..613cb22b26 100644 --- a/c/misra/src/qlpack.yml +++ b/c/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards -version: 2.48.0-dev +version: 2.49.0-dev description: MISRA C 2012 suites: codeql-suites license: MIT diff --git a/c/misra/test/qlpack.yml b/c/misra/test/qlpack.yml index a720d41779..08e5f579a3 100644 --- a/c/misra/test/qlpack.yml +++ b/c/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-c-coding-standards-tests -version: 2.48.0-dev +version: 2.49.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/autosar/src/qlpack.yml b/cpp/autosar/src/qlpack.yml index 65ec603f59..4130f08079 100644 --- a/cpp/autosar/src/qlpack.yml +++ b/cpp/autosar/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards -version: 2.48.0-dev +version: 2.49.0-dev description: AUTOSAR C++14 Guidelines R22-11, R21-11, R20-11, R19-11 and R19-03 suites: codeql-suites license: MIT diff --git a/cpp/autosar/test/qlpack.yml b/cpp/autosar/test/qlpack.yml index f7b3f9ef3f..46f06bed50 100644 --- a/cpp/autosar/test/qlpack.yml +++ b/cpp/autosar/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/autosar-cpp-coding-standards-tests -version: 2.48.0-dev +version: 2.49.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/cert/src/qlpack.yml b/cpp/cert/src/qlpack.yml index 999faded05..a89ed8a905 100644 --- a/cpp/cert/src/qlpack.yml +++ b/cpp/cert/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards -version: 2.48.0-dev +version: 2.49.0-dev description: CERT C++ 2016 suites: codeql-suites license: MIT diff --git a/cpp/cert/test/qlpack.yml b/cpp/cert/test/qlpack.yml index b1c634258a..8634569355 100644 --- a/cpp/cert/test/qlpack.yml +++ b/cpp/cert/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cert-cpp-coding-standards-tests -version: 2.48.0-dev +version: 2.49.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/common/src/qlpack.yml b/cpp/common/src/qlpack.yml index f7938fef71..07a8dc4136 100644 --- a/cpp/common/src/qlpack.yml +++ b/cpp/common/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards -version: 2.48.0-dev +version: 2.49.0-dev license: MIT dependencies: codeql/cpp-all: 2.1.1 diff --git a/cpp/common/test/qlpack.yml b/cpp/common/test/qlpack.yml index 84a581eda1..cb54217f76 100644 --- a/cpp/common/test/qlpack.yml +++ b/cpp/common/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/common-cpp-coding-standards-tests -version: 2.48.0-dev +version: 2.49.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/misra/src/qlpack.yml b/cpp/misra/src/qlpack.yml index f6a4e21428..44baf3efbe 100644 --- a/cpp/misra/src/qlpack.yml +++ b/cpp/misra/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards -version: 2.48.0-dev +version: 2.49.0-dev description: MISRA C++ 2023 default-suite: codeql-suites/misra-cpp-default.qls license: MIT diff --git a/cpp/misra/test/qlpack.yml b/cpp/misra/test/qlpack.yml index 565c630696..fb0cc1201c 100644 --- a/cpp/misra/test/qlpack.yml +++ b/cpp/misra/test/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/misra-cpp-coding-standards-tests -version: 2.48.0-dev +version: 2.49.0-dev extractor: cpp license: MIT dependencies: diff --git a/cpp/report/src/qlpack.yml b/cpp/report/src/qlpack.yml index c8a6dd08f8..e563299482 100644 --- a/cpp/report/src/qlpack.yml +++ b/cpp/report/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/report-cpp-coding-standards -version: 2.48.0-dev +version: 2.49.0-dev license: MIT dependencies: codeql/cpp-all: 2.1.1 diff --git a/docs/user_manual.md b/docs/user_manual.md index fae4623443..f4449082c7 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -36,14 +36,14 @@ ## Release information -This user manual documents release `2.48.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). +This user manual documents release `2.49.0-dev` of the coding standards located at [https://github.com/github/codeql-coding-standards](https://github.com/github/codeql-coding-standards). The release page documents the release notes and contains the following artifacts part of the release: - `coding-standards-codeql-packs-2.37.0-dev.zip`: CodeQL packs that can be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `code-scanning-cpp-query-pack-2.48.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `supported_rules_list_2.48.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. -- `supported_rules_list_2.48.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. -- `user_manual_2.48.0-dev.md`: This user manual. +- `code-scanning-cpp-query-pack-2.49.0-dev.zip`: Legacy packaging for the queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. +- `supported_rules_list_2.49.0-dev.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. +- `supported_rules_list_2.49.0-dev.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. +- `user_manual_2.49.0-dev.md`: This user manual. - `Source Code (zip)`: A zip archive containing the contents of https://github.com/github/codeql-coding-standards - `Source Code (tar.gz)`: A GZip compressed tar archive containing the contents of https://github.com/github/codeql-coding-standards - `checksums.txt`: A text file containing sha256 checksums for the aforementioned artifacts. @@ -670,7 +670,7 @@ This section describes known failure modes for "CodeQL Coding Standards" and des | | Out of space | Less output. Some files may be only be partially analyzed, or not analyzed at all. | Error reported on the command line. | Increase space. If it remains an issue report space consumption issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False positives | More output. Results are reported which are not violations of the guidelines. | All reported results must be reviewed. | Report false positive issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | | | False negatives | Less output. Violations of the guidelines are not reported. | Other validation and verification processes during software development should be used to complement the analysis performed by CodeQL Coding Standards. | Report false negative issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.48.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | +| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_2.49.0-dev.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | | | Incorrect deviation record specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation records with a reason. Ensure that all deviation records are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Incorrect deviation permit specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation permits with a reason. Ensure that all deviation permits are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | | | Unapproved use of a deviation record | Less output. Results for guideline violations are not reported. | Validate that the deviation record use is approved by verifying the approved-by attribute of the deviation record specification. | Ensure that each raised deviation record is approved by an independent approver through an auditable process. | From a9c412d9fc2c4034393a4cf8b982d2f7b2f7d6cf Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 15 Jul 2025 20:57:29 -0700 Subject: [PATCH 364/370] Fix bad joins on function names and unnecessarily large relation on integer constant macros --- .../IncompatibleFunctionDeclarations.ql | 26 +++++++++++-------- ...rectlySizedIntegerConstantMacroArgument.ql | 1 + .../CompatibleDeclarationFunctionDefined.ql | 15 +++++------ ...5-7-15-fix-performance-issues-in-2.20.7.md | 4 +++ 4 files changed, 26 insertions(+), 20 deletions(-) create mode 100644 change_notes/2025-7-15-fix-performance-issues-in-2.20.7.md diff --git a/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql b/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql index 8c25fe3350..3811d4e417 100644 --- a/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql +++ b/c/cert/src/rules/DCL40-C/IncompatibleFunctionDeclarations.ql @@ -24,28 +24,32 @@ import codingstandards.c.cert import codingstandards.cpp.types.Compatible import ExternalIdentifiers -predicate interestedInFunctions(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { +predicate interestedInFunctions( + FunctionDeclarationEntry f1, FunctionDeclarationEntry f2, ExternalIdentifiers d +) { not f1 = f2 and - f1.getDeclaration() = f2.getDeclaration() and - f1.getName() = f2.getName() + d = f1.getDeclaration() and + d = f2.getDeclaration() +} + +predicate interestedInFunctions(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { + interestedInFunctions(f1, f2, _) } +module FuncDeclEquiv = + FunctionDeclarationTypeEquivalence; + from ExternalIdentifiers d, FunctionDeclarationEntry f1, FunctionDeclarationEntry f2 where not isExcluded(f1, Declarations2Package::incompatibleFunctionDeclarationsQuery()) and not isExcluded(f2, Declarations2Package::incompatibleFunctionDeclarationsQuery()) and - not f1 = f2 and - f1.getDeclaration() = d and - f2.getDeclaration() = d and - f1.getName() = f2.getName() and + interestedInFunctions(f1, f2, d) and ( //return type check - not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, - f2) + not FuncDeclEquiv::equalReturnTypes(f1, f2) or //parameter type check - not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, - f2) + not FuncDeclEquiv::equalParameterTypes(f1, f2) ) and // Apply ordering on start line, trying to avoid the optimiser applying this join too early // in the pipeline diff --git a/c/misra/src/rules/RULE-7-5/IncorrectlySizedIntegerConstantMacroArgument.ql b/c/misra/src/rules/RULE-7-5/IncorrectlySizedIntegerConstantMacroArgument.ql index 87c945d6b6..1fe052aaae 100644 --- a/c/misra/src/rules/RULE-7-5/IncorrectlySizedIntegerConstantMacroArgument.ql +++ b/c/misra/src/rules/RULE-7-5/IncorrectlySizedIntegerConstantMacroArgument.ql @@ -20,6 +20,7 @@ predicate matchesSign(IntegerConstantMacro macro, PossiblyNegativeLiteral litera literal.isNegative() implies macro.isSigned() } +bindingset[literal] predicate matchesSize(IntegerConstantMacro macro, PossiblyNegativeLiteral literal) { literal.getRawValue() <= macro.maxValue() and literal.getRawValue() >= macro.minValue() diff --git a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql index 73abc1e048..e7eba7e42a 100644 --- a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql +++ b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql @@ -23,13 +23,14 @@ predicate interestedInFunctions(FunctionDeclarationEntry f1, FunctionDeclaration f1.getDeclaration() instanceof ExternalIdentifiers and f1.isDefinition() and f1.getDeclaration() = f2.getDeclaration() and - // This condition should always hold, but removing it affects join order performance. - f1.getName() = f2.getName() and not f2.isDefinition() and not f1.isFromTemplateInstantiation(_) and not f2.isFromTemplateInstantiation(_) } +module FunDeclEquiv = + FunctionDeclarationTypeEquivalence; + from FunctionDeclarationEntry f1 where not isExcluded(f1, Declarations4Package::compatibleDeclarationFunctionDefinedQuery()) and @@ -44,17 +45,13 @@ where or //or one exists that is close but incompatible in some way exists(FunctionDeclarationEntry f2 | - f1.getName() = f2.getName() and - not f2.isDefinition() and - f2.getDeclaration() = f1.getDeclaration() and + interestedInFunctions(f1, f2) and ( //return types differ - not FunctionDeclarationTypeEquivalence::equalReturnTypes(f1, - f2) + not FunDeclEquiv::equalReturnTypes(f1, f2) or //parameter types differ - not FunctionDeclarationTypeEquivalence::equalParameterTypes(f1, - f2) + not FunDeclEquiv::equalParameterTypes(f1, f2) or //parameter names differ parameterNamesUnmatched(f1, f2) diff --git a/change_notes/2025-7-15-fix-performance-issues-in-2.20.7.md b/change_notes/2025-7-15-fix-performance-issues-in-2.20.7.md new file mode 100644 index 0000000000..a936579a97 --- /dev/null +++ b/change_notes/2025-7-15-fix-performance-issues-in-2.20.7.md @@ -0,0 +1,4 @@ + - `DCL40-C`, `RULE-8-4`: `IncompatibleFunctionDeclarations.ql`, `CompatibleDeclarationFunctionDefined.ql`. + - Fixed performance issues introduced when upgrading to CodeQL `2.20.7` by removing unnecessary check that matching function declarations have matching names. + - `RULE-7-5`: `IncorrectlySizedIntegerConstantMacroArgument.ql`. + - Added a `bindingset` to improve performance when checking if a literal matches the size of an integer constant macro. \ No newline at end of file From cfdc0d15f5e517ec6e28ebb8a14e214735203904 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 17 Jul 2025 17:03:56 +0100 Subject: [PATCH 365/370] A7-1-7: Address performance issue on 2.20.7 Poor join ordering on locations. --- ...erDeclarationAndInitializationNotOnSeparateLines.ql | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cpp/autosar/src/rules/A7-1-7/IdentifierDeclarationAndInitializationNotOnSeparateLines.ql b/cpp/autosar/src/rules/A7-1-7/IdentifierDeclarationAndInitializationNotOnSeparateLines.ql index ac98fe699d..addd8af697 100644 --- a/cpp/autosar/src/rules/A7-1-7/IdentifierDeclarationAndInitializationNotOnSeparateLines.ql +++ b/cpp/autosar/src/rules/A7-1-7/IdentifierDeclarationAndInitializationNotOnSeparateLines.ql @@ -55,11 +55,9 @@ where //omit the cases where there is one struct identifier on a struct var line used with typedef not exists(Struct s | s.getADeclarationEntry() = e1 and e1 instanceof TypeDeclarationEntry) and not exists(Struct s | s.getATypeNameUse() = e1 and e1 instanceof TypeDeclarationEntry) and - exists(Location l1, Location l2 | - e1.getLocation() = l1 and - e2.getLocation() = l2 and - not l1 = l2 and - l1.getFile() = l2.getFile() and - l1.getStartLine() = l2.getStartLine() + exists(string file, int startline | + e1.getLocation().hasLocationInfo(file, startline, _, _, _) and + e2.getLocation().hasLocationInfo(file, startline, _, _, _) and + not e1.getLocation() = e2.getLocation() ) select e1, "Expression statement and identifier are on the same line." From df2247ef350ed5fb7e4fa46a3e8d679a12afd89d Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 17 Jul 2025 17:46:54 +0100 Subject: [PATCH 366/370] A2-7-3: Address performance issues on upgrade to 2.20.7 - Only consider declarations within user code - as results in system headers will be thrown away, and significantly bloat the interemediate relation sizes. - Inline the function scope exclusion to documentable declaration. - Extract utility predicates for determining if there's a documented definition, or whether there are only definitions. --- .../A2-7-3/UndocumentedUserDefinedType.ql | 81 +++++++++++-------- 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/cpp/autosar/src/rules/A2-7-3/UndocumentedUserDefinedType.ql b/cpp/autosar/src/rules/A2-7-3/UndocumentedUserDefinedType.ql index f2dd0dc8bc..020d1d4ee1 100644 --- a/cpp/autosar/src/rules/A2-7-3/UndocumentedUserDefinedType.ql +++ b/cpp/autosar/src/rules/A2-7-3/UndocumentedUserDefinedType.ql @@ -65,30 +65,46 @@ class DocumentableDeclaration extends Declaration { string declarationType; DocumentableDeclaration() { - this instanceof UserType and - declarationType = "user-defined type" and - // Exclude template parameter types. - not this.(UserType).involvesTemplateParameter() - or - this instanceof Function and - declarationType = "function" and - // Exclude compiler generated functions, which cannot reasonably be documented. - not this.(Function).isCompilerGenerated() and - // Exclude instantiated template functions, which cannot reasonably be documented. - not this.(Function).isFromTemplateInstantiation(_) and - // Exclude anonymous lambda functions. - not exists(LambdaExpression lc | lc.getLambdaFunction() = this) and - //Exclude friend functions (because they have 2 entries in the database), and only one shows documented truly - not exists(FriendDecl d | - d.getFriend().(Function).getDefinition() = this.getADeclarationEntry() + // Within the users codebase, not a system header + exists(this.getFile().getRelativePath()) and + // Not required to be documented, as used within same scope + not isInFunctionScope(this) and + ( + this instanceof UserType and + declarationType = "user-defined type" and + // Exclude template parameter types. + not this.(UserType).involvesTemplateParameter() + or + this instanceof Function and + declarationType = "function" and + // Exclude compiler generated functions, which cannot reasonably be documented. + not this.(Function).isCompilerGenerated() and + // Exclude instantiated template functions, which cannot reasonably be documented. + not this.(Function).isFromTemplateInstantiation(_) and + // Exclude anonymous lambda functions. + not exists(LambdaExpression lc | lc.getLambdaFunction() = this) and + //Exclude friend functions (because they have 2 entries in the database), and only one shows documented truly + not exists(FriendDecl d | + d.getFriend().(Function).getDefinition() = this.getADeclarationEntry() + ) + or + this instanceof MemberVariable and + declarationType = "member variable" and + // Exclude memeber variables in instantiated templates, which cannot reasonably be documented. + not this.(MemberVariable).isFromTemplateInstantiation(_) and + // Exclude compiler generated variables, such as those for anonymous lambda functions + not this.(MemberVariable).isCompilerGenerated() ) - or - this instanceof MemberVariable and - declarationType = "member variable" and - // Exclude memeber variables in instantiated templates, which cannot reasonably be documented. - not this.(MemberVariable).isFromTemplateInstantiation(_) and - // Exclude compiler generated variables, such as those for anonymous lambda functions - not this.(MemberVariable).isCompilerGenerated() + } + + private predicate hasDocumentedDefinition() { + // Check if the declaration has a documented definition + exists(DeclarationEntry de | de = getADeclarationEntry() and isDocumented(de)) + } + + private predicate hasOnlyDefinitions() { + // Check if the declaration has only definitions, i.e., no non-definition entries + not exists(DeclarationEntry de | de = getADeclarationEntry() and not de.isDefinition()) } /** Gets a `DeclarationEntry` for this declaration that should be documented. */ @@ -96,20 +112,16 @@ class DocumentableDeclaration extends Declaration { // Find a declaration entry that is not documented result = getADeclarationEntry() and not isDocumented(result) and - ( - // Report any non definition DeclarationEntry that is not documented - // as long as there is no corresponding documented definition (which must be for a forward declaration) - not result.isDefinition() and - not exists(DeclarationEntry de | - de = getADeclarationEntry() and de.isDefinition() and isDocumented(de) - ) - or + if result.isDefinition() + then // Report the definition DeclarationEntry, only if there are no non-definition `DeclarationEntry`'s // The rationale here is that documenting both the non-definition and definition declaration entries // is redundant - result.isDefinition() and - not exists(DeclarationEntry de | de = getADeclarationEntry() and not de.isDefinition()) - ) + hasOnlyDefinitions() + else + // Report any non definition DeclarationEntry that is not documented + // as long as there is no corresponding documented definition (which must be for a forward declaration) + not hasDocumentedDefinition() } /** Gets a string describing the type of declaration. */ @@ -144,7 +156,6 @@ from DocumentableDeclaration d, DeclarationEntry de where not isExcluded(de, CommentsPackage::undocumentedUserDefinedTypeQuery()) and not isExcluded(d, CommentsPackage::undocumentedUserDefinedTypeQuery()) and - not isInFunctionScope(d) and d.getAnUndocumentedDeclarationEntry() = de select de, "Declaration entry for " + d.getDeclarationType() + " " + d.getName() + From 1f4654ec5cd027934b0052e3c2f1e3e6a60028b7 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 17 Jul 2025 23:04:08 +0100 Subject: [PATCH 367/370] RecursiveFunctions: Address performance issues with 2.20.7 Avoid cross-product on function. --- ...llThemselvesEitherDirectlyOrIndirectly.qll | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/rules/functionscallthemselveseitherdirectlyorindirectly/FunctionsCallThemselvesEitherDirectlyOrIndirectly.qll b/cpp/common/src/codingstandards/cpp/rules/functionscallthemselveseitherdirectlyorindirectly/FunctionsCallThemselvesEitherDirectlyOrIndirectly.qll index 87f27c134f..e54e4378e9 100644 --- a/cpp/common/src/codingstandards/cpp/rules/functionscallthemselveseitherdirectlyorindirectly/FunctionsCallThemselvesEitherDirectlyOrIndirectly.qll +++ b/cpp/common/src/codingstandards/cpp/rules/functionscallthemselveseitherdirectlyorindirectly/FunctionsCallThemselvesEitherDirectlyOrIndirectly.qll @@ -19,17 +19,17 @@ class RecursiveCall extends FunctionCall { } } -query predicate problems(FunctionCall fc, string message, Function f, string f_name) { - exists(RecursiveCall call | - not isExcluded(call, getQuery()) and - f = fc.getTarget() and - f_name = fc.getTarget().getName() and - fc.getTarget() = call.getTarget() and - if fc.getTarget() = fc.getEnclosingFunction() - then message = "This call directly invokes its containing function $@." - else - message = - "The function " + fc.getEnclosingFunction() + - " is indirectly recursive via this call to $@." - ) +class RecursiveFunction extends Function { + RecursiveFunction() { exists(RecursiveCall fc | fc.getEnclosingFunction() = this) } +} + +query predicate problems(FunctionCall fc, string message, RecursiveFunction f, string functionName) { + not isExcluded(fc, getQuery()) and + f = fc.getTarget() and + functionName = f.getName() and + if f = fc.getEnclosingFunction() + then message = "This call directly invokes its containing function $@." + else + message = + "The function " + fc.getEnclosingFunction() + " is indirectly recursive via this call to $@." } From fe9a48da4d8ed2fc43794726a3bb5f560624f355 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Fri, 18 Jul 2025 08:05:34 +0100 Subject: [PATCH 368/370] EXP16-C: Address compilation error --- .../DoNotCompareFunctionPointersToConstantValues.ql | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql index e65d58a652..5f347d817a 100644 --- a/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql +++ b/c/cert/src/rules/EXP16-C/DoNotCompareFunctionPointersToConstantValues.ql @@ -23,13 +23,17 @@ import codingstandards.cpp.types.FunctionType import codingstandards.cpp.exprs.FunctionExprs import codingstandards.cpp.exprs.Guards -abstract class EffectivelyComparison extends Element { +final class FinalElement = Element; + +abstract class EffectivelyComparison extends FinalElement { abstract string getExplanation(); abstract FunctionExpr getFunctionExpr(); } -class ExplicitComparison extends EffectivelyComparison, ComparisonOperation { +final class FinalComparisonOperation = ComparisonOperation; + +class ExplicitComparison extends EffectivelyComparison, FinalComparisonOperation { Expr constantExpr; FunctionExpr funcExpr; From d078e04d54876f51559d029b1b9eb691c9ece086 Mon Sep 17 00:00:00 2001 From: Luke Cartey <5377966+lcartey@users.noreply.github.com> Date: Tue, 29 Jul 2025 09:15:15 +0100 Subject: [PATCH 369/370] Create misra-c++-2023-help.md.template --- .../templates/misra-c++-2023-help.md.template | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 scripts/generate_rules/templates/misra-c++-2023-help.md.template diff --git a/scripts/generate_rules/templates/misra-c++-2023-help.md.template b/scripts/generate_rules/templates/misra-c++-2023-help.md.template new file mode 100644 index 0000000000..4fb7b17ee8 --- /dev/null +++ b/scripts/generate_rules/templates/misra-c++-2023-help.md.template @@ -0,0 +1,49 @@ +# {{ rule_id }}: {{ name }} + +This query implements the {{ standard_name | escape }} rule {{ rule_id | escape }}: + +> {{ rule_title }} + +## Classification + +** REPLACE THIS WITH THE CORRECT CLASSIFICATION ** +* required +* implementation +* automated + +## Rationale + +**REPLACE THIS WITH RATIONAL, IF ANY** + +## Exception + +**REPLACE THIS WITH EXCEPTION, IF ANY** + +## Example + +```cpp +// REPLACE THIS WITH C++ EXAMPLE, IF ANY +``` + +## See more + +** REPLACE THIS WITH THE ANY SEE MORE REFERENCES ** + +## Implementation notes + +{% if implementation_scope is defined %} +{{ implementation_scope["description"] }} +{% if implementation_scope["items"] is iterable %} +{% for implementation_scope_entry in implementation_scope["items"] %} +* {{ implementation_scope_entry }} +{% endfor %} +{% endif %} +{% else %} +None +{% endif %} + +## References + +{% if standard_title | length %} +* {{ standard_title | escape }}: [{{ rule_id }}: {{ rule_title }}]({{ standard_url }}) +{% endif %} From 9ea891af74447a22b2540ab95f7e3fff9fd2531a Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Fri, 1 Aug 2025 17:09:31 -0400 Subject: [PATCH 370/370] Change occurrence of `std::iterator<...>` to `__iterator` Also prefix the member type with `const` depending on the iterator. --- cpp/common/test/includes/standard-library/array | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/common/test/includes/standard-library/array b/cpp/common/test/includes/standard-library/array index ca4d3291ad..9465ccba97 100644 --- a/cpp/common/test/includes/standard-library/array +++ b/cpp/common/test/includes/standard-library/array @@ -8,8 +8,8 @@ namespace std { template struct array { typedef T &reference; typedef const T &const_reference; - typedef std::iterator iterator; - typedef std::iterator const_iterator; + typedef __iterator iterator; + typedef __iterator const_iterator; typedef size_t size_type; typedef ptrdiff_t difference_type;