-
Notifications
You must be signed in to change notification settings - Fork 68
Implement Conversions
rule package
#919
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
base: main
Are you sure you want to change the base?
Conversation
Detects implicit and explicit conversions from type bool to other types, preventing potential confusion between bitwise and logical operators and ensuring clear type usage. [a]
- Simplify query implementation - Format test code
Detects implicit conversions to bool type from fundamental types, unscoped enumerations, and pointers that may lead to unintended behavior in conditional expressions.
Detects inappropriate assignments between numeric types that violate type compatibility requirements, including implicit conversions that may cause information loss or unexpected behavior changes. [a]
- Add additional test cases - Allow name qualifiers - Prohibit explicit casts (inc. parameters)
Reference types can be numeric types according to the rule. In addition to making NumericTypes reference types, we also add a helper predicate which gets the size of the real type (rather than the size of the reference).
Migrate conversion generic code to a shared library.
- Add extra testing - Support signed bitfields
- Exclude booleans and chars from our determination of numeric types. - Deduplicate integer types deduced for bitfields - identifying a canonical set of integer types.
The `getValue()` provided in the database applies the conversions, which can be unhelpful when trying to write rules the refer to conversions.
- Use IntegerConstantExpr to determine both the expressions which are constant, and the BigInt value of those constants (before final conversion). - Implement a BigInt type upper/lower bound to determine whether a constant assignment is valid.
- Support assignment to pointer to members - Support pointer-to-member function calls
Overload independence should consider what parameters are default.
Consider the conversion as the source, not the pre-conversion value.
Detects inappropriate implicit conversions from function type to pointer-to-function type outside of static_cast or assignment contexts. Prevents ambiguous code where function pointer usage in boolean or arithmetic expressions may contradict developer intent. [a]
Adds a query that identifies when a numerical value of a character has been used. Also fixes a character type category bug, exposed getBuiltinType and provide a CharacterType class.
Detects integral promotions and arithmetic conversions that change the signedness or type category of operands, preventing unexpected behavior from implicit type conversions. [a]
For determining the size of int on the given platform.
Not all integer promotions or usual arithmetic conversions are actually Conversions in our model.
- More shift testing - Mixed signed/unsigned
AssignOperations do not include a Conversion in the database for lvalues, so create new classes to capture those cases.
Rule 7.0.4 is now in the Conversions package. Rules 8.x in the Conversions package are now moved to Conversions2. This is to avoid having too many complex queries in one package, and because 7.0.4 is more closely related to the other 7.x rules.
Detects inappropriate operands for bitwise and shift operators that violate type requirements. Identifies signed operands in bitwise operations and improper shift operand types that may cause undefined behavior. [a]
Preprocessor directives are not currently supported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cpp conversion model is very subtle and tricky. I definitely did a very careful review here. Hopefully the comments aren't off base, and easily resolved. Please do timebox any quality-of-life changes, the goal was to keep small useful suggestions, not to introduce any annoyances or tricky cases.
Overall nicely done, I kept thinking of edge cases and seeing you addressed them cleanly, often much more cleanly than what I pictured would be necessary. A pleasure to review!
@@ -0,0 +1,97 @@ | |||
import cpp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider making a new subdirectory cpp/common/.../ast/
for this and Call.qll
etc.
or | ||
result = this.(EnumConstantAccess).getTarget().getValue().toBigInt() | ||
or | ||
result = -this.(UnaryMinusExpr).getOperand().getFullyConverted().getValue().toBigInt() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these cases be recursive? e.g.
result = this.(NotExpr).getOperand().getFullyConverted().(IntegerConstantExpr).getConstantValue().bitNot()
or | ||
result = this.(UnaryPlusExpr).getOperand().getFullyConverted().getValue().toBigInt() | ||
or | ||
result = this.(NotExpr).getOperand().getFullyConverted().getValue().toBigInt().bitNot() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks incorrect, like its performing the ~
binary operation instead of boolean casted !
.
/** | ||
* An integer constant expression as defined by the C++17 standard. | ||
*/ | ||
class IntegerConstantExpr extends FinalExpr { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👀 if we import qtil this can be 👀
class IntegerConstantExpr extends Final<Expr>::Type {
@@ -0,0 +1,290 @@ | |||
/** | |||
* A library for utility classes related to the built-in type rules in MISRA C++ 2023 (Section 4.7.0). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider wrapping this file's contents in a namespace such as MisraCpp23
to make certain types/predicates/concepts slightly clearer such as CharacterType
.
|
||
override NumericType getToType() { | ||
// Only report the canonical type - e.g. `int` not `signed int` | ||
result = result.(IntegralType).getCanonicalArithmeticType() and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result instanceof CanonicalArithmeticType ?
|
||
class IntegerPromotion extends RelevantRealConversion { | ||
IntegerPromotion() { | ||
// Exclude integer promotions combined with usual arithmetic conversions, which are handled separately |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see where these are handled separately?
candidateType instanceof LongType or | ||
candidateType instanceof LongLongType | ||
) and | ||
fromType.getIntegralUpperBound() <= candidateType.getIntegralUpperBound() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this could hold for both LongType
and LongLongType
right, as you identified earlier?
} | ||
|
||
class UsualArithmeticConversion extends RelevantRealConversion { | ||
UsualArithmeticConversion() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just noting that this class will match some cases that aren't usual arithmetic conversions. I think harmlessly.
For example, ArrayToPointerConversion
, ReferenceDereferenceExpr
(in the odd scenario of performing binary operations on int&
).
Description
This PR adds support for an updated
Conversions
package.As a number of the early rules in the original conversions package - particularly Rule 7.0.6 - turned out to be more complex than expected, I've created a
Conversions2
package and shuffled around the queries in the following way:Conversions
package.Conversions
fromPreconditions
- as the rule concepts related more closely to the otherConversions
queries than to preconditions.Conversions2
.Implementation notes:
BigInt
type, to help support analysis of larger integer constants. In CodeQL CLI 2.19.4, this feature is considered "experimental". Therefore, I would recommend we merge the PR to upgrade the CodeQL dependency to 2.20.7 (Upgradegithub/codeql
dependency to 2.20.7 #913) before we merge this PR.BuiltInTypeRules
CodeQL library, which implements the behaviour described in the section4.7.0 The built-in type rules
of MISRA C++ 2023. These are similar in purpose to the essential type rules from MISRA C, but different enough that we needed to provide a clean implementation.Change request type
.ql
,.qll
,.qls
or unit tests)Rules with added or modified queries
RULE-7-0-1
RULE-7-0-2
RULE-7-0-3
RULE-7-0-4
RULE-7-0-5
RULE-7-0-6
RULE-7-11-3
Release change checklist
A change note (development_handbook.md#change-notes) is required for any pull request which modifies:
If you are only adding new rule queries, a change note is not required.
Author: Is a change note required?
🚨🚨🚨
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.
Reviewer: Confirm that either a change note is not required or the change note is required and has been added.
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
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.
Reviewer
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.