Skip to content

Michaelrfairhurst/implement types2 package #724

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

Merged
merged 17 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* @id c/misra/incorrectly-sized-integer-constant-macro-argument
* @name RULE-7-5: The argument of an integer constant macro shall have an appropriate size
* @description Integer constant macros argument values should be values of a compatible size.
* @kind problem
* @precision very-high
* @problem.severity error
* @tags external/misra/id/rule-7-5
* correctness
* external/misra/c/2012/amendment3
* external/misra/obligation/required
*/

import cpp
import codingstandards.c.misra
import codingstandards.cpp.IntegerConstantMacro
import codingstandards.cpp.Literals

predicate matchesSign(IntegerConstantMacro macro, PossiblyNegativeLiteral literal) {
literal.isNegative() implies macro.isSigned()
}

predicate matchesSize(IntegerConstantMacro macro, PossiblyNegativeLiteral literal) {
// Wait for BigInt support to check 64 bit macro types.
(macro.getSize() < 64 and matchesSign(macro, literal))
implies
(
literal.getRawValue() <= macro.maxValue() and
literal.getRawValue() >= macro.minValue()
)
}

from
PossiblyNegativeLiteral literal, MacroInvocation invoke, IntegerConstantMacro macro,
string explanation
where
not isExcluded(invoke, Types2Package::incorrectlySizedIntegerConstantMacroArgumentQuery()) and
invoke.getMacro() = macro and
literal = invoke.getExpr() and
(
not matchesSign(macro, invoke.getExpr()) and explanation = " cannot be negative"
or
not matchesSize(macro, invoke.getExpr()) and
explanation = " is outside of the allowed range " + macro.getRangeString()
)
select invoke.getExpr(), "Value provided to integer constant macro " + macro.getName() + explanation
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* @id c/misra/integer-constant-macro-argument-uses-suffix
* @name RULE-7-5: The argument of an integer constant macro shall not use literal suffixes u, l, or ul
* @description Integer constant macros should be used integer literal values with no u/l suffix.
* @kind problem
* @precision high
* @problem.severity warning
* @tags external/misra/id/rule-7-5
* readability
* maintainability
* external/misra/c/2012/amendment3
* external/misra/obligation/required
*/

import cpp
import codingstandards.c.misra
import codingstandards.cpp.IntegerConstantMacro
import codingstandards.cpp.Literals

string argumentSuffix(MacroInvocation invoke) {
// Compiler strips the suffix unless we look at the unexpanded argument text.
// Unexpanded argument text can be malformed in all sorts of ways, so make
// this match relatively strict, to be safe.
result = invoke.getUnexpandedArgument(0).regexpCapture("([0-9]+|0[xX][0-9A-F]+)([uUlL]+)$", 2)
}

from MacroInvocation invoke, PossiblyNegativeLiteral argument, string suffix
where
not isExcluded(invoke, Types2Package::integerConstantMacroArgumentUsesSuffixQuery()) and
invoke.getMacro() instanceof IntegerConstantMacro and
invoke.getExpr() = argument and
suffix = argumentSuffix(invoke)
select invoke.getExpr(),
"Value suffix '" + suffix + "' is not allowed on provided argument to integer constant macro " +
invoke.getMacroName() + "."
35 changes: 35 additions & 0 deletions c/misra/src/rules/RULE-7-5/InvalidIntegerConstantMacroArgument.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* @id c/misra/invalid-integer-constant-macro-argument
* @name RULE-7-5: The argument of an integer constant macro shall be a literal
* @description Integer constant macros should be given a literal value as an argument.
* @kind problem
* @precision very-high
* @problem.severity warning
* @tags external/misra/id/rule-7-5
* correctness
* external/misra/c/2012/amendment3
* external/misra/obligation/required
*/

import cpp
import codingstandards.c.misra
import codingstandards.cpp.IntegerConstantMacro
import codingstandards.cpp.Literals
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis

predicate containsMacroInvocation(MacroInvocation outer, MacroInvocation inner) {
outer.getExpr() = inner.getExpr() and
exists(outer.getUnexpandedArgument(0).indexOf(inner.getMacroName()))
}

from MacroInvocation invoke, IntegerConstantMacro macro
where
not isExcluded(invoke, Types2Package::invalidIntegerConstantMacroArgumentQuery()) and
invoke.getMacro() = macro and
(
not invoke.getExpr() instanceof PossiblyNegativeLiteral
or
containsMacroInvocation(invoke, _)
)
select invoke.getExpr(),
"Argument to integer constant macro " + macro.getName() + " must be an integer literal."
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* @id c/misra/invalid-literal-for-integer-constant-macro-argument
* @name RULE-7-5: The argument of an integer constant macro shall be a decimal, hex, or octal literal
* @description Integer constant macro arguments should be a decimal, hex, or octal literal.
* @kind problem
* @precision very-high
* @problem.severity error
* @tags external/misra/id/rule-7-5
* correctness
* external/misra/c/2012/amendment3
* external/misra/obligation/required
*/

import cpp
import codingstandards.c.misra
import codingstandards.cpp.IntegerConstantMacro
import codingstandards.cpp.Literals

/**
* Floating point literals are not allowed. Neither are char or string
* literals, although those are not `NumericLiteral`s and therefore detected in
* `InvalidIntegerConstantMacroArgument.ql`.
*/
predicate validLiteralType(PossiblyNegativeLiteral literal) {
literal.getBaseLiteral() instanceof Cpp14Literal::DecimalLiteral or
literal.getBaseLiteral() instanceof Cpp14Literal::OctalLiteral or
literal.getBaseLiteral() instanceof Cpp14Literal::HexLiteral or
// Ignore cases where the AST/extractor don't give us enough information:
literal.getBaseLiteral() instanceof Cpp14Literal::UnrecognizedNumericLiteral
}

/**
* Clang accepts `xINTsize_C(0b01)`, and expands the argument into a decimal
* literal. Binary literals are not standard c nor are they allowed by rule 7-5.
* Detect this pattern before macro expansion.
*/
predicate seemsBinaryLiteral(MacroInvocation invoke) {
invoke.getUnexpandedArgument(0).regexpMatch("-?0[bB][01]+")
}

/**
* Extractor converts `xINTsize_C('a')` to a decimal literal. Therefore, detect
* this pattern before macro expansion.
*/
predicate seemsCharLiteral(MacroInvocation invoke) {
invoke.getUnexpandedArgument(0).regexpMatch("-?'\\\\?.'")
}

string explainIncorrectArgument(MacroInvocation invoke) {
if seemsBinaryLiteral(invoke)
then result = "binary literal"
else
if seemsCharLiteral(invoke)
then result = "char literal"
else
exists(PossiblyNegativeLiteral literal |
literal = invoke.getExpr() and
if literal.getBaseLiteral() instanceof Cpp14Literal::FloatingLiteral
then result = "floating point literal"
else result = "invalid literal"
)
}

from MacroInvocation invoke, PossiblyNegativeLiteral literal
where
not isExcluded(invoke, Types2Package::invalidLiteralForIntegerConstantMacroArgumentQuery()) and
invoke.getMacro() instanceof IntegerConstantMacro and
literal = invoke.getExpr() and
(
not validLiteralType(literal) or
seemsBinaryLiteral(invoke) or
seemsCharLiteral(invoke)
)
select literal,
"Integer constant macro " + invoke.getMacroName() + " used with " +
explainIncorrectArgument(invoke) +
" argument, only decimal, octal, or hex integer literal allowed."
24 changes: 24 additions & 0 deletions c/misra/src/rules/RULE-7-6/UseOfBannedSmallIntegerConstantMacro.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @id c/misra/use-of-banned-small-integer-constant-macro
* @name RULE-7-6: The small integer variants of the minimum-width integer constant macros shall not be used
* @description Small integer constant macros expression are promoted to type int, which can lead to
* unexpected results.
* @kind problem
* @precision very-high
* @problem.severity warning
* @tags external/misra/id/rule-7-6
* readability
* external/misra/c/2012/amendment3
* external/misra/obligation/required
*/

import cpp
import codingstandards.c.misra
import codingstandards.cpp.IntegerConstantMacro

from MacroInvocation macroInvoke, IntegerConstantMacro macro
where
not isExcluded(macroInvoke, Types2Package::useOfBannedSmallIntegerConstantMacroQuery()) and
macroInvoke.getMacro() = macro and
macro.isSmall()
select macroInvoke, "Usage of small integer constant macro " + macro.getName() + " is not allowed."
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
| test.c:17:13:17:16 | - ... | Value provided to integer constant macro UINT8_C cannot be negative |
| test.c:19:13:19:18 | - ... | Value provided to integer constant macro UINT8_C cannot be negative |
| test.c:21:13:21:16 | - ... | Value provided to integer constant macro UINT8_C cannot be negative |
| test.c:37:13:37:15 | 256 | Value provided to integer constant macro UINT8_C is outside of the allowed range 0..255 |
| test.c:38:13:38:16 | 256 | Value provided to integer constant macro UINT8_C is outside of the allowed range 0..255 |
| test.c:39:13:39:17 | 256 | Value provided to integer constant macro UINT8_C is outside of the allowed range 0..255 |
| test.c:42:13:42:14 | - ... | Value provided to integer constant macro UINT8_C cannot be negative |
| test.c:43:13:43:15 | - ... | Value provided to integer constant macro UINT8_C cannot be negative |
| test.c:44:13:44:15 | - ... | Value provided to integer constant macro UINT8_C cannot be negative |
| test.c:45:13:45:17 | - ... | Value provided to integer constant macro UINT8_C cannot be negative |
| test.c:70:12:70:14 | 128 | Value provided to integer constant macro INT8_C is outside of the allowed range -128..127 |
| test.c:71:12:71:15 | 128 | Value provided to integer constant macro INT8_C is outside of the allowed range -128..127 |
| test.c:72:12:72:15 | 128 | Value provided to integer constant macro INT8_C is outside of the allowed range -128..127 |
| test.c:76:12:76:15 | - ... | Value provided to integer constant macro INT8_C is outside of the allowed range -128..127 |
| test.c:77:12:77:16 | - ... | Value provided to integer constant macro INT8_C is outside of the allowed range -128..127 |
| test.c:78:12:78:16 | - ... | Value provided to integer constant macro INT8_C is outside of the allowed range -128..127 |
| test.c:91:14:91:18 | 65536 | Value provided to integer constant macro UINT16_C is outside of the allowed range 0..65535 |
| test.c:92:14:92:20 | 65536 | Value provided to integer constant macro UINT16_C is outside of the allowed range 0..65535 |
| test.c:93:14:93:20 | 65536 | Value provided to integer constant macro UINT16_C is outside of the allowed range 0..65535 |
| test.c:106:13:106:17 | 32768 | Value provided to integer constant macro INT16_C is outside of the allowed range -32768..32767 |
| test.c:107:13:107:19 | 32768 | Value provided to integer constant macro INT16_C is outside of the allowed range -32768..32767 |
| test.c:108:13:108:18 | 32768 | Value provided to integer constant macro INT16_C is outside of the allowed range -32768..32767 |
| test.c:112:13:112:18 | - ... | Value provided to integer constant macro INT16_C is outside of the allowed range -32768..32767 |
| test.c:113:13:113:20 | - ... | Value provided to integer constant macro INT16_C is outside of the allowed range -32768..32767 |
| test.c:114:13:114:19 | - ... | Value provided to integer constant macro INT16_C is outside of the allowed range -32768..32767 |
| test.c:124:14:124:24 | 4294967296 | Value provided to integer constant macro UINT32_C is outside of the allowed range 0..4294967295 |
| test.c:125:14:125:25 | 4294967296 | Value provided to integer constant macro UINT32_C is outside of the allowed range 0..4294967295 |
| test.c:135:13:135:22 | 2147483648 | Value provided to integer constant macro INT32_C is outside of the allowed range -2147483648..2147483647 |
| test.c:136:13:136:22 | 2147483648 | Value provided to integer constant macro INT32_C is outside of the allowed range -2147483648..2147483647 |
| test.c:139:13:139:23 | - ... | Value provided to integer constant macro INT32_C is outside of the allowed range -2147483648..2147483647 |
| test.c:140:13:140:23 | - ... | Value provided to integer constant macro INT32_C is outside of the allowed range -2147483648..2147483647 |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-7-5/IncorrectlySizedIntegerConstantMacroArgument.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
| test.c:25:13:25:14 | 1 | Value suffix 'u' is not allowed on provided argument to integer constant macro UINT8_C. |
| test.c:26:13:26:14 | 2 | Value suffix 'U' is not allowed on provided argument to integer constant macro UINT8_C. |
| test.c:27:13:27:14 | 3 | Value suffix 'l' is not allowed on provided argument to integer constant macro UINT8_C. |
| test.c:28:13:28:14 | 4 | Value suffix 'L' is not allowed on provided argument to integer constant macro UINT8_C. |
| test.c:29:13:29:15 | 5 | Value suffix 'ul' is not allowed on provided argument to integer constant macro UINT8_C. |
| test.c:30:13:30:15 | 5 | Value suffix 'll' is not allowed on provided argument to integer constant macro UINT8_C. |
| test.c:31:13:31:16 | 5 | Value suffix 'ull' is not allowed on provided argument to integer constant macro UINT8_C. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-7-5/IntegerConstantMacroArgumentUsesSuffix.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
| test.c:48:13:48:17 | ... + ... | Argument to integer constant macro UINT8_C must be an integer literal. |
| test.c:49:13:49:18 | access to array | Argument to integer constant macro UINT8_C must be an integer literal. |
| test.c:50:13:50:19 | access to array | Argument to integer constant macro UINT8_C must be an integer literal. |
| test.c:51:5:51:22 | 255 | Argument to integer constant macro UINT8_C must be an integer literal. |
| test.c:52:5:52:17 | 1 | Argument to integer constant macro UINT8_C must be an integer literal. |
| test.c:53:5:53:18 | 0 | Argument to integer constant macro UINT8_C must be an integer literal. |
| test.c:54:5:54:17 | 0 | Argument to integer constant macro UINT8_C must be an integer literal. |
| test.c:55:5:55:20 | 0 | Argument to integer constant macro UINT8_C must be an integer literal. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-7-5/InvalidIntegerConstantMacroArgument.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
| test.c:16:13:16:15 | 1.0 | Integer constant macro UINT8_C used with floating point literal argument, only decimal, octal, or hex integer literal allowed. |
| test.c:17:13:17:16 | - ... | Integer constant macro UINT8_C used with floating point literal argument, only decimal, octal, or hex integer literal allowed. |
| test.c:18:13:18:17 | 7 | Integer constant macro UINT8_C used with binary literal argument, only decimal, octal, or hex integer literal allowed. |
| test.c:19:13:19:18 | - ... | Integer constant macro UINT8_C used with binary literal argument, only decimal, octal, or hex integer literal allowed. |
| test.c:20:13:20:15 | 97 | Integer constant macro UINT8_C used with char literal argument, only decimal, octal, or hex integer literal allowed. |
| test.c:21:13:21:16 | - ... | Integer constant macro UINT8_C used with char literal argument, only decimal, octal, or hex integer literal allowed. |
| test.c:22:13:22:16 | 10 | Integer constant macro UINT8_C used with char literal argument, only decimal, octal, or hex integer literal allowed. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-7-5/InvalidLiteralForIntegerConstantMacroArgument.ql
Loading
Loading