Skip to content

Commit bf43554

Browse files
Handle cases where AST/extractor give us incomplete/messy information.
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
1 parent b70f2e1 commit bf43554

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

c/misra/src/rules/RULE-7-5/InvalidLiteralForIntegerConstantMacroArgument.ql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ import codingstandards.cpp.Literals
2323
predicate validLiteralType(PossiblyNegativeLiteral literal) {
2424
literal.getBaseLiteral() instanceof Cpp14Literal::DecimalLiteral or
2525
literal.getBaseLiteral() instanceof Cpp14Literal::OctalLiteral or
26-
literal.getBaseLiteral() instanceof Cpp14Literal::HexLiteral
26+
literal.getBaseLiteral() instanceof Cpp14Literal::HexLiteral or
27+
// Ignore cases where the AST/extractor don't give us enough information:
28+
literal.getBaseLiteral() instanceof Cpp14Literal::UnrecognizedNumericLiteral
2729
}
2830

2931
/**

c/misra/test/rules/RULE-7-5/test.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,11 @@ int_least64_t g8[] = {
157157
INT64_C(-0x8000000000000000), // COMPLIANT
158158
INT64_C(-0x8000000000000001), // NON-COMPLIANT[FALSE NEGATIVE]
159159
INT64_C(-0x8001000000000000), // NON-COMPLIANT
160-
};
160+
};
161+
162+
// Other edge cases:
163+
void f(void) {
164+
uint32_t l1 = 1;
165+
// `UnrecognizedNumericLiteral` case:
166+
int64_t l2 = ((int32_t)UINT64_C(0x1b2) * (l1)); // COMPLIANT
167+
}

cpp/common/src/codingstandards/cpp/Cpp14Literal.qll

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ module Cpp14Literal {
99
/** An numeric literal. */
1010
abstract class NumericLiteral extends StandardLibrary::Literal { }
1111

12+
/** Convenience for implementing class `UnrecognizedNumericLiteral` */
13+
abstract private class RecognizedNumericLiteral extends StandardLibrary::Literal { }
14+
1215
/** An integer literal. */
1316
abstract class IntegerLiteral extends NumericLiteral {
1417
predicate isSigned() { not isUnsigned() }
@@ -23,7 +26,7 @@ module Cpp14Literal {
2326
* ```
2427
* Octal literals must always start with the digit `0`.
2528
*/
26-
class OctalLiteral extends IntegerLiteral {
29+
class OctalLiteral extends IntegerLiteral, RecognizedNumericLiteral {
2730
OctalLiteral() { getValueText().regexpMatch("\\s*0[0-7']*[uUlL]*\\s*") }
2831

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

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

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

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

89+
/**
90+
* Literal values with conversions and macros cannot always be trivially
91+
* parsed from `Literal.getValueText()`, and have loss of required
92+
* information in `Literal.getValue()`. This class covers cases that appear
93+
* to be `NumericLiteral`s but cannot be determined to be a hex, decimal,
94+
* octal, binary, or float literal, but still are parsed as a Literal with a
95+
* number value.
96+
*/
97+
class UnrecognizedNumericLiteral extends NumericLiteral {
98+
UnrecognizedNumericLiteral() {
99+
this.getValue().regexpMatch("[0-9.e]+") and
100+
not this instanceof RecognizedNumericLiteral
101+
}
102+
}
103+
104+
predicate test(RecognizedNumericLiteral r, string valueText) { valueText = r.getValueText() }
105+
86106
/**
87107
* A character literal. For example:
88108
* ```

0 commit comments

Comments
 (0)