Skip to content

Commit

Permalink
Handle cases where AST/extractor give us incomplete/messy information.
Browse files Browse the repository at this point in the history
Add a new UnrecognizedNumericLiteral class in Literal.qll which matches literals
that have a numeric value but don't match any regexes for the literal types
(hex, decimal, float, octal, binary). Exclude that from results in
InvalidLiteralForIntegerConstantMacroArgument.ql
  • Loading branch information
MichaelRFairhurst committed Oct 1, 2024
1 parent b70f2e1 commit bf43554
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ import codingstandards.cpp.Literals
predicate validLiteralType(PossiblyNegativeLiteral literal) {
literal.getBaseLiteral() instanceof Cpp14Literal::DecimalLiteral or
literal.getBaseLiteral() instanceof Cpp14Literal::OctalLiteral or
literal.getBaseLiteral() instanceof Cpp14Literal::HexLiteral
literal.getBaseLiteral() instanceof Cpp14Literal::HexLiteral or
// Ignore cases where the AST/extractor don't give us enough information:
literal.getBaseLiteral() instanceof Cpp14Literal::UnrecognizedNumericLiteral
}

/**
Expand Down
9 changes: 8 additions & 1 deletion c/misra/test/rules/RULE-7-5/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,11 @@ int_least64_t g8[] = {
INT64_C(-0x8000000000000000), // COMPLIANT
INT64_C(-0x8000000000000001), // NON-COMPLIANT[FALSE NEGATIVE]
INT64_C(-0x8001000000000000), // NON-COMPLIANT
};
};

// Other edge cases:
void f(void) {
uint32_t l1 = 1;
// `UnrecognizedNumericLiteral` case:
int64_t l2 = ((int32_t)UINT64_C(0x1b2) * (l1)); // COMPLIANT
}
30 changes: 25 additions & 5 deletions cpp/common/src/codingstandards/cpp/Cpp14Literal.qll
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ module Cpp14Literal {
/** An numeric literal. */
abstract class NumericLiteral extends StandardLibrary::Literal { }

/** Convenience for implementing class `UnrecognizedNumericLiteral` */
abstract private class RecognizedNumericLiteral extends StandardLibrary::Literal { }

/** An integer literal. */
abstract class IntegerLiteral extends NumericLiteral {
predicate isSigned() { not isUnsigned() }
Expand All @@ -23,7 +26,7 @@ module Cpp14Literal {
* ```
* Octal literals must always start with the digit `0`.
*/
class OctalLiteral extends IntegerLiteral {
class OctalLiteral extends IntegerLiteral, RecognizedNumericLiteral {
OctalLiteral() { getValueText().regexpMatch("\\s*0[0-7']*[uUlL]*\\s*") }

override string getAPrimaryQlClass() { result = "OctalLiteral" }
Expand All @@ -35,7 +38,7 @@ module Cpp14Literal {
* unsigned int32_t minus2 = 0xfffffffe;
* ```
*/
class HexLiteral extends IntegerLiteral {
class HexLiteral extends IntegerLiteral, RecognizedNumericLiteral {
HexLiteral() { getValueText().regexpMatch("\\s*0[xX][0-9a-fA-F']+[uUlL]*\\s*") }

override string getAPrimaryQlClass() { result = "HexLiteral" }
Expand All @@ -47,7 +50,7 @@ module Cpp14Literal {
* unsigned int32_t binary = 0b101010;
* ```
*/
class BinaryLiteral extends IntegerLiteral {
class BinaryLiteral extends IntegerLiteral, RecognizedNumericLiteral {
BinaryLiteral() { getValueText().regexpMatch("\\s*0[bB][0-1']*[uUlL]*\\s*") }

override string getAPrimaryQlClass() { result = "BinaryLiteral" }
Expand All @@ -59,7 +62,7 @@ module Cpp14Literal {
* unsigned int32_t decimal = 10340923;
* ```
*/
class DecimalLiteral extends IntegerLiteral {
class DecimalLiteral extends IntegerLiteral, RecognizedNumericLiteral {
DecimalLiteral() { getValueText().regexpMatch("\\s*[1-9][0-9']*[uUlL]*\\s*") }

override string getAPrimaryQlClass() { result = "DecimalLiteral" }
Expand All @@ -71,7 +74,7 @@ module Cpp14Literal {
* double floating = 1.340923e-19;
* ```
*/
class FloatingLiteral extends NumericLiteral {
class FloatingLiteral extends RecognizedNumericLiteral {
FloatingLiteral() {
getValueText().regexpMatch("\\s*[0-9][0-9']*(\\.[0-9']+)?([eE][\\+\\-]?[0-9']+)?[flFL]?\\s*") and
// A decimal literal takes precedent
Expand All @@ -83,6 +86,23 @@ module Cpp14Literal {
override string getAPrimaryQlClass() { result = "FloatingLiteral" }
}

/**
* Literal values with conversions and macros cannot always be trivially
* parsed from `Literal.getValueText()`, and have loss of required
* information in `Literal.getValue()`. This class covers cases that appear
* to be `NumericLiteral`s but cannot be determined to be a hex, decimal,
* octal, binary, or float literal, but still are parsed as a Literal with a
* number value.
*/
class UnrecognizedNumericLiteral extends NumericLiteral {
UnrecognizedNumericLiteral() {
this.getValue().regexpMatch("[0-9.e]+") and
not this instanceof RecognizedNumericLiteral
}
}

predicate test(RecognizedNumericLiteral r, string valueText) { valueText = r.getValueText() }

/**
* A character literal. For example:
* ```
Expand Down

0 comments on commit bf43554

Please sign in to comment.