Skip to content

Commit 508cb3d

Browse files
Implement Types2 package.
Break up integer constant macro rules into several queries to make it easier to handle exceptions and deviations.
1 parent 6e6c79b commit 508cb3d

16 files changed

+410
-211
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* @id c/misra/incorrectly-sized-integer-constant-macro-argument
3+
* @name RULE-7-5: The argument of an integer constant macro shall have an appropriate size
4+
* @description Integer constant macros argument values should be values of a compatible size
5+
* @kind problem
6+
* @precision very-high
7+
* @problem.severity error
8+
* @tags external/misra/id/rule-7-5
9+
* correctness
10+
* external/misra/obligation/required
11+
*/
12+
13+
import cpp
14+
import codingstandards.c.misra
15+
import codingstandards.cpp.IntegerConstantMacro
16+
import codingstandards.cpp.Literals
17+
18+
predicate matchesSign(IntegerConstantMacro macro, PossiblyNegativeLiteral literal) {
19+
literal.isNegative() implies macro.isSigned()
20+
}
21+
22+
predicate matchesSize(IntegerConstantMacro macro, PossiblyNegativeLiteral literal) {
23+
// Wait for BigInt support to check 64 bit macro types.
24+
(macro.getSize() < 64 and matchesSign(macro, literal))
25+
implies
26+
(
27+
literal.getRawValue() <= macro.maxValue() and
28+
literal.getRawValue() >= macro.minValue()
29+
)
30+
}
31+
32+
from
33+
PossiblyNegativeLiteral literal, MacroInvocation invoke, IntegerConstantMacro macro,
34+
string explanation
35+
where
36+
not isExcluded(invoke, Types2Package::incorrectlySizedIntegerConstantMacroArgumentQuery()) and
37+
invoke.getMacro() = macro and
38+
literal = invoke.getExpr() and
39+
(
40+
not matchesSign(macro, invoke.getExpr()) and explanation = "cannot be negative"
41+
or
42+
not matchesSize(macro, invoke.getExpr()) and explanation = "is too large for the specified type"
43+
)
44+
select invoke.getExpr(), "Integer constant macro value " + explanation
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* @id c/misra/integer-constant-macro-argument-uses-suffix
3+
* @name RULE-7-5: The argument of an integer constant macro shall not use literal suffixes u, l, or ul
4+
* @description Integer constant macros should be used integer literal values with no u/l suffix.
5+
* @kind problem
6+
* @precision very-high
7+
* @problem.severity error
8+
* @tags external/misra/id/rule-7-5
9+
* readability
10+
* maintainability
11+
* external/misra/obligation/required
12+
*/
13+
14+
import cpp
15+
import codingstandards.c.misra
16+
import codingstandards.cpp.IntegerConstantMacro
17+
import codingstandards.cpp.Literals
18+
19+
predicate usesSuffix(MacroInvocation invoke) {
20+
invoke.getUnexpandedArgument(0).regexpMatch(".*[uUlL]")
21+
}
22+
23+
from MacroInvocation invoke, PossiblyNegativeLiteral argument
24+
where
25+
not isExcluded(invoke, Types2Package::integerConstantMacroArgumentUsesSuffixQuery()) and
26+
invoke.getMacro() instanceof IntegerConstantMacro and
27+
invoke.getExpr() = argument and
28+
usesSuffix(invoke)
29+
select invoke.getExpr(), "Integer constant macro arguments should not have 'u'/'l' suffix."
Lines changed: 21 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
/**
22
* @id c/misra/invalid-integer-constant-macro-argument
3-
* @name RULE-7-5: The argument of an integer constant macro shall have an appropriate form
4-
* @description Integer constant macros should be given appropriate values for the size of the
5-
* integer type.
3+
* @name RULE-7-5: The argument of an integer constant macro shall be a literal
4+
* @description Integer constant macros should be given a literal value as an argument
65
* @kind problem
76
* @precision very-high
87
* @problem.severity error
@@ -14,73 +13,29 @@
1413
import cpp
1514
import codingstandards.c.misra
1615
import codingstandards.cpp.IntegerConstantMacro
17-
import codingstandards.cpp.Cpp14Literal
16+
import codingstandards.cpp.Literals
1817
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
1918

20-
abstract class PossiblyNegativeLiteral extends Expr {
21-
abstract Cpp14Literal::IntegerLiteral getBaseLiteral();
22-
23-
predicate isNegative() {
24-
this instanceof NegativeLiteral
25-
}
26-
}
27-
28-
class NegativeLiteral extends PossiblyNegativeLiteral, UnaryMinusExpr {
29-
Cpp14Literal::IntegerLiteral literal;
30-
31-
NegativeLiteral() {
32-
literal = getOperand()
33-
}
34-
35-
override Cpp14Literal::IntegerLiteral getBaseLiteral() {
36-
result = literal
37-
}
38-
}
39-
40-
class PositiveLiteral extends PossiblyNegativeLiteral, Cpp14Literal::IntegerLiteral {
41-
PositiveLiteral() {
42-
not exists(UnaryMinusExpr l | l.getOperand() = this)
43-
}
44-
45-
override Cpp14Literal::IntegerLiteral getBaseLiteral() {
46-
result = this
47-
}
48-
}
49-
50-
predicate validExpr(Expr expr) {
51-
expr instanceof PossiblyNegativeLiteral
52-
}
53-
54-
predicate usesSuffix(MacroInvocation invoke) {
55-
invoke.getUnexpandedArgument(0).regexpMatch(".*[uUlL]")
56-
}
57-
58-
predicate matchedSign(IntegerConstantMacro macro, PossiblyNegativeLiteral literal) {
59-
literal.isNegative() implies macro.isSigned()
60-
}
61-
62-
predicate validLiteralType(PossiblyNegativeLiteral expr) {
63-
expr.getBaseLiteral() instanceof Cpp14Literal::DecimalLiteral or
64-
expr.getBaseLiteral() instanceof Cpp14Literal::OctalLiteral or
65-
expr.getBaseLiteral() instanceof Cpp14Literal::HexLiteral
66-
}
67-
68-
predicate matchesSize(IntegerConstantMacro macro, PossiblyNegativeLiteral literal) {
69-
// Note: upperBound should equal lowerBound.
70-
upperBound(literal) <= macro.maxValue() and
71-
lowerBound(literal) >= macro.minValue() and exists("123".toBigInt())
19+
/**
20+
* The max negative 64 bit signed integer is one less than the negative of the
21+
* max positive signed 64 bit integer. The only way to create a "negative"
22+
* literal is to use unary- negation of a positive literal. Therefore, clang
23+
* (and likely other compilers) rejects `INT64_C(-92233...808)` but accepts
24+
* `INT64_C(-92233...807 - 1)`. Therefore, in this case allow non-literal
25+
* expressions.
26+
*/
27+
predicate specialMaxNegative64Exception(IntegerConstantMacro macro, Expr expr) {
28+
macro.getSize() = 64 and
29+
macro.isSigned() and
30+
// Set a cutoff with precision, fix once BigInt library is available.
31+
upperBound(expr) < macro.minValue() * 0.999999999 and
32+
upperBound(expr) > macro.minValue() * 1.000000001
7233
}
7334

74-
from MacroInvocation invoke, IntegerConstantMacro macro, string explanation
35+
from MacroInvocation invoke, IntegerConstantMacro macro
7536
where
7637
not isExcluded(invoke, Types2Package::invalidIntegerConstantMacroArgumentQuery()) and
7738
invoke.getMacro() = macro and
78-
(
79-
(not validExpr(invoke.getExpr()) and explanation = "invalid expression") or
80-
(validLiteralType(invoke.getExpr()) and explanation = "invalid literal type" + invoke.getExpr().getAQlClass()) or
81-
(usesSuffix(invoke) and explanation = "literal suffixes not allowed") or
82-
(not matchedSign(macro, invoke.getExpr()) and explanation = "signed/unsigned mismatch") or
83-
(not matchesSize(macro, invoke.getExpr()) and explanation = "invalid size")
84-
)
85-
86-
select invoke.getExpr(), "Invalid integer constant macro: " + explanation
39+
not invoke.getExpr() instanceof PossiblyNegativeLiteral and
40+
not specialMaxNegative64Exception(macro, invoke.getExpr())
41+
select invoke.getExpr(), "Integer constant macro argument must be an integer literal."
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* @id c/misra/invalid-literal-for-integer-constant-macro-argument
3+
* @name RULE-7-5: The argument of an integer constant macro shall be a decimal, hex, or octal literal
4+
* @description Integer constant macro arguments should be a decimal, hex, or octal literal
5+
* @kind problem
6+
* @precision very-high
7+
* @problem.severity error
8+
* @tags external/misra/id/rule-7-5
9+
* correctness
10+
* external/misra/obligation/required
11+
*/
12+
13+
import cpp
14+
import codingstandards.c.misra
15+
import codingstandards.cpp.IntegerConstantMacro
16+
import codingstandards.cpp.Literals
17+
18+
/**
19+
* Floating point literals are not allowed. Neither are char or string
20+
* literals, although those are not `NumericLiteral`s and therefore detected in
21+
* `InvalidIntegerConstantMacroArgument.ql`.
22+
*/
23+
predicate validLiteralType(PossiblyNegativeLiteral literal) {
24+
literal.getBaseLiteral() instanceof Cpp14Literal::DecimalLiteral or
25+
literal.getBaseLiteral() instanceof Cpp14Literal::OctalLiteral or
26+
literal.getBaseLiteral() instanceof Cpp14Literal::HexLiteral
27+
}
28+
29+
/**
30+
* Clang accepts `xINTsize_C(0b01)`, and expands the argument into a decimal
31+
* literal. Binary literals are not standard c nor are they allowed by rule 7-5.
32+
* Detect this pattern before macro expansion.
33+
*/
34+
predicate seemsBinaryLiteral(MacroInvocation invoke) {
35+
invoke.getUnexpandedArgument(0).regexpMatch("0[bB][01]+")
36+
}
37+
38+
from MacroInvocation invoke, PossiblyNegativeLiteral literal
39+
where
40+
not isExcluded(invoke, Types2Package::invalidLiteralForIntegerConstantMacroArgumentQuery()) and
41+
invoke.getMacro() instanceof IntegerConstantMacro and
42+
literal = invoke.getExpr() and
43+
(
44+
not validLiteralType(literal) or
45+
seemsBinaryLiteral(invoke)
46+
)
47+
select literal, "Integer constant macro arguments must be a decimal, octal, or hex integer literal."
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
| test.c:26:13:26:15 | 256 | Integer constant macro value is too large for the specified type |
2+
| test.c:27:13:27:16 | 256 | Integer constant macro value is too large for the specified type |
3+
| test.c:28:13:28:17 | 256 | Integer constant macro value is too large for the specified type |
4+
| test.c:31:13:31:14 | - ... | Integer constant macro value cannot be negative |
5+
| test.c:32:13:32:15 | - ... | Integer constant macro value cannot be negative |
6+
| test.c:33:13:33:15 | - ... | Integer constant macro value cannot be negative |
7+
| test.c:34:13:34:17 | - ... | Integer constant macro value cannot be negative |
8+
| test.c:55:12:55:14 | 128 | Integer constant macro value is too large for the specified type |
9+
| test.c:56:12:56:15 | 128 | Integer constant macro value is too large for the specified type |
10+
| test.c:57:12:57:15 | 128 | Integer constant macro value is too large for the specified type |
11+
| test.c:61:12:61:15 | - ... | Integer constant macro value is too large for the specified type |
12+
| test.c:62:12:62:16 | - ... | Integer constant macro value is too large for the specified type |
13+
| test.c:63:12:63:16 | - ... | Integer constant macro value is too large for the specified type |
14+
| test.c:76:14:76:18 | 65536 | Integer constant macro value is too large for the specified type |
15+
| test.c:77:14:77:20 | 65536 | Integer constant macro value is too large for the specified type |
16+
| test.c:78:14:78:20 | 65536 | Integer constant macro value is too large for the specified type |
17+
| test.c:91:13:91:17 | 32768 | Integer constant macro value is too large for the specified type |
18+
| test.c:92:13:92:19 | 32768 | Integer constant macro value is too large for the specified type |
19+
| test.c:93:13:93:18 | 32768 | Integer constant macro value is too large for the specified type |
20+
| test.c:97:13:97:18 | - ... | Integer constant macro value is too large for the specified type |
21+
| test.c:98:13:98:20 | - ... | Integer constant macro value is too large for the specified type |
22+
| test.c:99:13:99:19 | - ... | Integer constant macro value is too large for the specified type |
23+
| test.c:109:14:109:24 | 4294967296 | Integer constant macro value is too large for the specified type |
24+
| test.c:110:14:110:25 | 4294967296 | Integer constant macro value is too large for the specified type |
25+
| test.c:120:13:120:22 | 2147483648 | Integer constant macro value is too large for the specified type |
26+
| test.c:121:13:121:22 | 2147483648 | Integer constant macro value is too large for the specified type |
27+
| test.c:124:13:124:23 | - ... | Integer constant macro value is too large for the specified type |
28+
| test.c:125:13:125:23 | - ... | Integer constant macro value is too large for the specified type |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-7-5/IncorrectlySizedIntegerConstantMacroArgument.ql
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
| test.c:16:13:16:14 | 1 | Integer constant macro arguments should not have 'u'/'l' suffix. |
2+
| test.c:17:13:17:14 | 2 | Integer constant macro arguments should not have 'u'/'l' suffix. |
3+
| test.c:18:13:18:14 | 3 | Integer constant macro arguments should not have 'u'/'l' suffix. |
4+
| test.c:19:13:19:14 | 4 | Integer constant macro arguments should not have 'u'/'l' suffix. |
5+
| test.c:20:13:20:15 | 5 | Integer constant macro arguments should not have 'u'/'l' suffix. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-7-5/IntegerConstantMacroArgumentUsesSuffix.ql
Lines changed: 5 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,5 @@
1-
| test.c:12:13:12:15 | 1.0 | Invalid integer constant macro: invalid literal type |
2-
| test.c:13:13:12:15 | 0b111 | Invalid integer constant macro: invalid literal type |
3-
| test.c:16:13:16:14 | 1 | Invalid integer constant macro: literal suffixes not allowed |
4-
| test.c:17:13:17:14 | 2 | Invalid integer constant macro: literal suffixes not allowed |
5-
| test.c:18:13:18:14 | 3 | Invalid integer constant macro: literal suffixes not allowed |
6-
| test.c:19:13:19:14 | 4 | Invalid integer constant macro: literal suffixes not allowed |
7-
| test.c:20:13:20:15 | 5 | Invalid integer constant macro: literal suffixes not allowed |
8-
| test.c:26:13:26:15 | 256 | Invalid integer constant macro: invalid size |
9-
| test.c:27:13:27:16 | 256 | Invalid integer constant macro: invalid size |
10-
| test.c:28:13:28:17 | 256 | Invalid integer constant macro: invalid size |
11-
| test.c:31:13:31:14 | - ... | Invalid integer constant macro: signed/unsigned mismatch |
12-
| test.c:32:13:32:15 | - ... | Invalid integer constant macro: signed/unsigned mismatch |
13-
| test.c:33:13:33:15 | - ... | Invalid integer constant macro: signed/unsigned mismatch |
14-
| test.c:34:13:34:17 | - ... | Invalid integer constant macro: signed/unsigned mismatch |
15-
| test.c:37:13:37:17 | ... + ... | Invalid integer constant macro: invalid expression |
16-
| test.c:38:13:38:18 | access to array | Invalid integer constant macro: invalid expression |
17-
| test.c:39:13:39:18 | access to array | Invalid integer constant macro: invalid expression |
18-
| test.c:40:13:39:18 | UINT8_MAX | Invalid integer constant macro: invalid expression |
19-
| test.c:54:12:54:15 | 191 | Invalid integer constant macro: invalid size |
20-
| test.c:55:12:55:14 | 255 | Invalid integer constant macro: invalid size |
21-
| test.c:56:12:56:15 | 192 | Invalid integer constant macro: invalid size |
22-
| test.c:57:12:57:15 | 128 | Invalid integer constant macro: invalid size |
23-
| test.c:61:12:57:15 | -129 | Invalid integer constant macro: invalid size |
24-
| test.c:62:12:57:15 | -129 | Invalid integer constant macro: invalid size |
25-
| test.c:63:12:57:15 | -201 | Invalid integer constant macro: invalid size |
26-
| test.c:64:12:57:15 | -0x81 | Invalid integer constant macro: invalid size |
27-
| test.c:76:14:76:18 | 65536 | Invalid integer constant macro: invalid size |
28-
| test.c:78:14:78:20 | 65536 | Invalid integer constant macro: invalid size |
29-
| test.c:91:13:91:17 | 32768 | Invalid integer constant macro: invalid size |
30-
| test.c:93:13:93:18 | 32768 | Invalid integer constant macro: invalid size |
31-
| test.c:97:13:93:18 | -32769 | Invalid integer constant macro: invalid size |
32-
| test.c:98:13:93:18 | -040001 | Invalid integer constant macro: invalid size |
33-
| test.c:99:13:93:18 | -0x8001 | Invalid integer constant macro: invalid size |
34-
| test.c:109:14:109:24 | 4294967296 | Invalid integer constant macro: invalid size |
35-
| test.c:110:14:110:25 | 4294967296 | Invalid integer constant macro: invalid size |
36-
| test.c:120:13:120:22 | 2147483648 | Invalid integer constant macro: invalid size |
37-
| test.c:121:13:121:23 | 34359738368 | Invalid integer constant macro: invalid size |
38-
| test.c:130:14:130:15 | 0 | Invalid integer constant macro: invalid size |
39-
| test.c:133:14:133:34 | 18446744073709551615 | Invalid integer constant macro: invalid size |
40-
| test.c:134:14:134:32 | 18446744073709551615 | Invalid integer constant macro: invalid size |
41-
| test.c:140:13:140:14 | 0 | Invalid integer constant macro: invalid size |
42-
| test.c:143:13:143:32 | 9223372036854775807 | Invalid integer constant macro: invalid size |
43-
| test.c:147:13:147:33 | - ... | Invalid integer constant macro: invalid size |
44-
| test.c:148:13:148:37 | ... - ... | Invalid integer constant macro: invalid expression |
45-
| test.c:148:13:148:37 | ... - ... | Invalid integer constant macro: invalid literal type |
46-
| test.c:148:13:148:37 | ... - ... | Invalid integer constant macro: invalid size |
47-
| test.c:148:13:148:37 | ... - ... | Invalid integer constant macro: signed/unsigned mismatch |
48-
| test.c:150:13:150:37 | ... - ... | Invalid integer constant macro: invalid expression |
49-
| test.c:150:13:150:37 | ... - ... | Invalid integer constant macro: invalid literal type |
50-
| test.c:150:13:150:37 | ... - ... | Invalid integer constant macro: invalid size |
51-
| test.c:150:13:150:37 | ... - ... | Invalid integer constant macro: signed/unsigned mismatch |
52-
| test.c:152:13:152:31 | 9223372036854775807 | Invalid integer constant macro: invalid size |
53-
| test.c:153:13:153:31 | 9223372036854775808 | Invalid integer constant macro: invalid size |
54-
| test.c:154:13:154:31 | - ... | Invalid integer constant macro: invalid size |
55-
| test.c:155:13:155:30 | - ... | Invalid integer constant macro: invalid size |
1+
| test.c:37:13:37:17 | ... + ... | Integer constant macro argument must be an integer literal. |
2+
| test.c:38:13:38:18 | access to array | Integer constant macro argument must be an integer literal. |
3+
| test.c:39:13:39:19 | access to array | Integer constant macro argument must be an integer literal. |
4+
| test.c:152:13:152:37 | ... - ... | Integer constant macro argument must be an integer literal. |
5+
| test.c:153:13:153:47 | ... - ... | Integer constant macro argument must be an integer literal. |
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| test.c:12:13:12:15 | 1.0 | Integer constant macro arguments must be a decimal, octal, or hex integer literal. |
2+
| test.c:13:13:13:17 | 7 | Integer constant macro arguments must be a decimal, octal, or hex integer literal. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-7-5/InvalidLiteralForIntegerConstantMacroArgument.ql

0 commit comments

Comments
 (0)