Skip to content

Fix False Positives of M5-0-12 #925

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open

Conversation

jeongsoolee09
Copy link
Contributor

@jeongsoolee09 jeongsoolee09 commented Jul 10, 2025

Description

Fix false positives of M5-0-12 (Closes #541).

Change request type

  • Release or process automation (GitHub workflows, internal scripts)
  • Internal documentation
  • External documentation
  • Query files (.ql, .qll, .qls or unit tests)
  • External scripts (analysis report or other code shipped as part of a release)

Rules with added or modified queries

  • No rules added
  • Queries have been added for the following rules:
    • rule number here
  • Queries have been modified for the following rules:
    • rule number here

Release change checklist

A change note (development_handbook.md#change-notes) is required for any pull request which modifies:

  • The structure or layout of the release artifacts.
  • The evaluation performance (memory, execution time) of an existing query.
  • The results of an existing query in any circumstance.

If you are only adding new rule queries, a change note is not required.

Author: Is a change note required?

  • Yes
  • No

🚨🚨🚨
Reviewer: Confirm that format of shared queries (not the .qll file, the
.ql file that imports it) is valid by running them within VS Code.

  • Confirmed

Reviewer: Confirm that either a change note is not required or the change note is required and has been added.

  • Confirmed

Query development review checklist

For PRs that add new queries or modify existing queries, the following checklist should be completed by both the author and reviewer:

Author

  • Have all the relevant rule package description files been checked in?
  • Have you verified that the metadata properties of each new query is set appropriately?
  • Do all the unit tests contain both "COMPLIANT" and "NON_COMPLIANT" cases?
  • Are the alert messages properly formatted and consistent with the style guide?
  • Have you run the queries on OpenPilot and verified that the performance and results are acceptable?
    As a rule of thumb, predicates specific to the query should take no more than 1 minute, and for simple queries be under 10 seconds. If this is not the case, this should be highlighted and agreed in the code review process.
  • Does the query have an appropriate level of in-query comments/documentation?
  • Have you considered/identified possible edge cases?
  • Does the query not reinvent features in the standard library?
  • Can the query be simplified further (not golfed!)

Reviewer

  • Have all the relevant rule package description files been checked in?
  • Have you verified that the metadata properties of each new query is set appropriately?
  • Do all the unit tests contain both "COMPLIANT" and "NON_COMPLIANT" cases?
  • Are the alert messages properly formatted and consistent with the style guide?
  • Have you run the queries on OpenPilot and verified that the performance and results are acceptable?
    As a rule of thumb, predicates specific to the query should take no more than 1 minute, and for simple queries be under 10 seconds. If this is not the case, this should be highlighted and agreed in the code review process.
  • Does the query have an appropriate level of in-query comments/documentation?
  • Have you considered/identified possible edge cases?
  • Does the query not reinvent features in the standard library?
  • Can the query be simplified further (not golfed!)

- 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
1. Change signed char / int8_t case to their opposites.
2. Assign a numeral to the unsigned char / signed char than a character.
@jeongsoolee09 jeongsoolee09 self-assigned this Jul 10, 2025
@jeongsoolee09
Copy link
Contributor Author

This query runs on openpilot-72d1744 in 17 seconds (on an M1 Max MacBook), and produces one true positive result.

@jeongsoolee09 jeongsoolee09 marked this pull request as ready for review July 14, 2025 19:49
@Copilot Copilot AI review requested due to automatic review settings July 14, 2025 19:49
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes false positives in rule M5-0-12 by improving the detection of implicit conversions from plain char to explicitly signed/unsigned char types. The fix addresses scenarios involving templates and provides more accurate reporting of where violations occur.

Key Changes:

  • Complete rewrite of the query logic to handle template instantiations properly
  • Enhanced test coverage with comprehensive template scenarios
  • Updated expected results to reflect accurate violation detection

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql Complete rewrite with new classes to handle template instantiations and implicit conversions
test.cpp Extensive expansion of test cases covering templates, function calls, and various char type scenarios
SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected Updated expected results reflecting the improved detection logic
Comments suppressed due to low confidence (2)

cpp/autosar/test/rules/M5-0-12/test.cpp:92

  • [nitpick] The variable names 'v1' and 'v2' are not descriptive. Consider using more meaningful names like 'templateVarUnsigned' and 'templateVarSigned'.
  v1<unsigned char> =

TemplateInstantiation templateInstantiation,
ImplicitConversionFromPlainCharType implicitConversion
) {
implicitConversion.getEnclosingElement+() = templateInstantiation.asElement()
Copy link
Preview

Copilot AI Jul 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of getEnclosingElement+() (transitive closure) could be expensive and may match unintended nested elements. Consider using a more specific predicate or adding bounds to limit the scope.

Copilot uses AI. Check for mistakes.

Copy link
Contributor

@MichaelRFairhurst MichaelRFairhurst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!!

result = this.asTemplateVariable().toString()
}

Location getLocation() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you added Element getElement() then this could be getElement().getLocation(), and toString() could be getElement().toString()

@@ -16,23 +16,237 @@
import cpp
import codingstandards.cpp.autosar

from Variable v, Expr aexp
newtype TTemplateElement =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love that you're solving this directly. I think this type (and TemplateElement) could be moved into cpp/common/src/codinstandards/cpp under a qll (like Templates.qll or something).

I think it also might be less verbose if you made a common Element subclass, like TemplateElement extends Element with characteristic predicate this instanceof TemplateClass or this instanceof TemplateFunction or ....

newtype TTemplateInstantiation =
TClassTemplateInstantiation(ClassTemplateInstantiation c) or
TFunctionTemplateInstantiation(FunctionTemplateInstantiation f) or
TVariableTemplateInstantiation(VariableTemplateInstantiation v)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, awesome and could be in a shared qll! And I think these could also be a class that extends Element?

}

string toString() {
result = this.asClassTemplateInstantiation().toString() or
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This member predicate (and getLocation()) could be result = this.asElement().toString()/.getLocation().

this.getExpr().getUnspecifiedType() instanceof PlainCharType and
(
this.getUnspecifiedType() instanceof SignedCharType or
this.getUnspecifiedType() instanceof UnsignedCharType
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice on using .getUnspecifiedType()! I forgot to mention this quirk of writing cpp queries.

}
}

newtype TImplicitConversionElement =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is cool, nicely done.

In theory I think what you've written here could be used even more widely too. In the future, this could be a module under cpp/common/src/codingstandards/cpp/alertreporting with a parameterized module e.g.

signature class ElementSig = Element;
module TemplatableElement<ElementSig Elem> {
  newtype TTemplatableElement = TElementOutsideTemplate(Elem elem) { ... }
  or
  TElementInsideTemplate(TemplateInstantiation templateInstantiation, Elem elem) { ... };
  ...


string toString() {
result = this.asImplicitConversionOutsideTemplate().toString() or
exists(ImplicitConversionFromPlainCharType implicitConversion |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can just be result = this.asInstantiationOfImplicitConversionTemplate(_).toString(), both here and in a few other spots

)
}

Element asElement() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this name is a bit confusing, since I wouldn't expect it to call getAUse in the templated case. I might just name this getAUse() or maybe getAnOccurrence() or something like that?

A comment would suffice too!

"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),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

select implicitConversionLocation, ... might also work, since you define getLocation()

Templates are tricky issue; we'd like to address
this in a different PR.
@jeongsoolee09
Copy link
Contributor Author

I have reduced the scope of this query to only deal with cases that does not involve templates, as templates are difficult topic and deserves a discussion of its own. Subsequently, both the test cases and the results are trimmed down.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

M5-0-12: Incorrect alerts on assignments of valid numerical values
2 participants