Skip to content

Commit 266c3e5

Browse files
committed
Misra rules 12-2 17-5 17-7
1 parent ea6c573 commit 266c3e5

File tree

9 files changed

+158
-24
lines changed

9 files changed

+158
-24
lines changed

c/misra/src/rules/RULE-12-2/RightHandOperandOfAShiftOperatorRange.ql

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,15 @@
1212

1313
import cpp
1414
import codingstandards.c.misra
15+
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
1516

16-
from
17+
from BinaryOperation x, int max_size
1718
where
1819
not isExcluded(x, Contracts6Package::rightHandOperandOfAShiftOperatorRangeQuery()) and
19-
select
20+
(x instanceof LShiftExpr or x instanceof RShiftExpr) and
21+
max_size = (8 * x.getLeftOperand().getExplicitlyConverted().getUnderlyingType().getSize()) - 1 and
22+
exists(Expr rhs | rhs = x.getRightOperand().getFullyConverted() |
23+
lowerBound(rhs) < 0 or
24+
upperBound(rhs) > max_size
25+
)
26+
select x, "The right hand operand of the shift operator is not in the range 0 to " + max_size + "."

c/misra/src/rules/RULE-17-5/ArrayFunctionArgumentNumberOfElements.ql

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,64 @@
1212

1313
import cpp
1414
import codingstandards.c.misra
15+
import semmle.code.cpp.dataflow.DataFlow
1516

16-
from
17+
/**
18+
* Models a function parameter of type array with specified size
19+
* ```
20+
* void f1(int ar[3]);
21+
* ```
22+
*/
23+
class ArrayParameter extends Parameter {
24+
ArrayParameter() { this.getType().(ArrayType).hasArraySize() }
25+
26+
Expr getAMatchingArgument() {
27+
exists(FunctionCall fc |
28+
this.getFunction() = fc.getTarget() and
29+
result = fc.getArgument(this.getIndex())
30+
)
31+
}
32+
33+
int getArraySize() { result = this.getType().(ArrayType).getArraySize() }
34+
}
35+
36+
/**
37+
* The number of initialized elements in an ArrayAggregateLiteral.
38+
* In the following examples the result=2
39+
* ```
40+
* int arr3[3] = {1, 2};
41+
* int arr2[2] = {1, 2, 3};
42+
* ```
43+
*/
44+
int countElements(ArrayAggregateLiteral l) { result = count(l.getElementExpr(_)) }
45+
46+
class SmallArrayConfig extends DataFlow::Configuration {
47+
SmallArrayConfig() { this = "SmallArrayConfig" }
48+
49+
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ArrayAggregateLiteral }
50+
51+
override predicate isSink(DataFlow::Node sink) {
52+
sink.asExpr() = any(ArrayParameter p).getAMatchingArgument()
53+
}
54+
}
55+
56+
from Expr arg, ArrayParameter p
1757
where
18-
not isExcluded(x, Contracts6Package::arrayFunctionArgumentNumberOfElementsQuery()) and
19-
select
58+
not isExcluded(arg, Contracts6Package::arrayFunctionArgumentNumberOfElementsQuery()) and
59+
exists(SmallArrayConfig config | arg = p.getAMatchingArgument() |
60+
// the argument is a value and not an arrey
61+
not arg.getType() instanceof DerivedType
62+
or
63+
// the argument is an array too small
64+
arg.getType().(ArrayType).getArraySize() < p.getArraySize()
65+
or
66+
// the argument is a pointer and its value does not come from a literal of the correct
67+
arg.getType() instanceof PointerType and
68+
not exists(ArrayAggregateLiteral l |
69+
config.hasFlow(DataFlow::exprNode(l), DataFlow::exprNode(arg)) and
70+
countElements(l) >= p.getArraySize()
71+
)
72+
)
73+
select arg,
74+
"The function argument does not have a sufficient number or elements declared in the $@.", p,
75+
"parameter"
Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @id c/misra/value-returned-by-a-function-not-used
33
* @name RULE-17-7: The value returned by a function having non-void return type shall be used
4-
* @description
4+
* @description
55
* @kind problem
66
* @precision very-high
77
* @problem.severity error
@@ -11,8 +11,16 @@
1111

1212
import cpp
1313
import codingstandards.c.misra
14+
import semmle.code.cpp.dataflow.DataFlow
1415

15-
from
16+
from Call c
1617
where
17-
not isExcluded(x, Contracts6Package::valueReturnedByAFunctionNotUsedQuery()) and
18-
select
18+
not isExcluded(c, Contracts6Package::valueReturnedByAFunctionNotUsedQuery()) and
19+
// Calls in `ExprStmt`s indicate that the return value is ignored
20+
c.getParent() instanceof ExprStmt and
21+
// Ignore calls to void functions or where the return value is cast to `void`
22+
not c.getActualType() instanceof VoidType and
23+
// Exclude cases where the function call is generated within a macro, as the user of the macro is
24+
// not necessarily able to address thoes results
25+
not c.isAffectedByMacro()
26+
select c, "The value returned by this call shall be used or cast to `void`."
Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,21 @@
1-
No expected results have yet been specified
1+
| test.c:20:7:20:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 31. |
2+
| test.c:22:7:22:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 31. |
3+
| test.c:23:7:23:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 31. |
4+
| test.c:25:7:25:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 31. |
5+
| test.c:26:7:26:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 31. |
6+
| test.c:29:7:29:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 15. |
7+
| test.c:30:7:30:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 15. |
8+
| test.c:31:7:31:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 15. |
9+
| test.c:32:7:32:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 15. |
10+
| test.c:33:7:33:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 15. |
11+
| test.c:34:7:34:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 15. |
12+
| test.c:35:7:35:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 15. |
13+
| test.c:38:7:38:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 63. |
14+
| test.c:40:7:40:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 63. |
15+
| test.c:43:7:43:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 63. |
16+
| test.c:46:7:46:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 7. |
17+
| test.c:47:7:47:12 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 7. |
18+
| test.c:63:7:63:13 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 7. |
19+
| test.c:71:8:71:14 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 7. |
20+
| test.c:75:3:75:19 | ... << ... | The right hand operand of the shift operator is not in the range 0 to 15. |
21+
| test.c:77:3:77:12 | ... >> ... | The right hand operand of the shift operator is not in the range 0 to 63. |

c/misra/test/rules/RULE-12-2/test.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
#include <stdint.h>
22

33
const short int s1 = 15;
44
const short int s2 = -1;
@@ -58,8 +58,21 @@ void f2() {
5858
int aa = 10;
5959
aa++;
6060

61-
a = a << aa;
62-
b = b << aa;
63-
c = c << aa;
64-
d = d << aa;
61+
a = a << aa; // COMPLIANT
62+
b = b << aa; // COMPLIANT
63+
c = c << aa; // NON_COMPLIANT
64+
d = d << aa; // COMPLIANT
65+
}
66+
67+
void f3() {
68+
uint8_t u8;
69+
uint16_t u16;
70+
u8 = u8 << 7; // COMPLIANT
71+
u8 = u8 << 8; // NON_COMPLIANT
72+
u16 = (uint16_t)u8 << 9; // COMPLIANT
73+
// 0u is essentially unsigned char
74+
0u << 10; // NON_COMPLIANT[FALSE_NEGATIVE]
75+
(uint16_t)0 << 20; // NON_COMPLIANT
76+
0UL << 10; // COMPLIANT
77+
0UL >> 100; // NON_COMPLIANT
6578
}
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,9 @@
1-
No expected results have yet been specified
1+
| test.c:18:6:18:6 | 0 | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter |
2+
| test.c:19:6:19:7 | ar | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter |
3+
| test.c:21:6:21:9 | ar2p | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter |
4+
| test.c:26:9:26:9 | 0 | The function argument does not have a sufficient number or elements declared in the $@. | test.c:2:20:2:21 | ar | parameter |
5+
| test.c:27:9:27:10 | ar | The function argument does not have a sufficient number or elements declared in the $@. | test.c:2:20:2:21 | ar | parameter |
6+
| test.c:29:9:29:12 | ar2p | The function argument does not have a sufficient number or elements declared in the $@. | test.c:2:20:2:21 | ar | parameter |
7+
| test.c:61:6:61:8 | ar2 | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter |
8+
| test.c:62:6:62:9 | ar2b | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter |
9+
| test.c:63:6:63:9 | ar2p | The function argument does not have a sufficient number or elements declared in the $@. | test.c:1:13:1:14 | ar | parameter |

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

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ void t1() {
1717

1818
f1(0); // NON_COMPLAINT
1919
f1(ar); // NON_COMPLAINT
20-
f1(ar2); // NON_COMPLIANT
20+
f1(ar2); // COMPLIANT
2121
f1(ar2p); // NON_COMPLIANT
2222
f1(ar3); // COMPLIANT
2323
f1(ar3p); // COMPLIANT
2424
f1(ar4); // COMPLIANT
2525

2626
f2(0, 0); // NON_COMPLAINT
2727
f2(0, ar); // NON_COMPLAINT
28-
f2(0, ar2); // NON_COMPLIANT
28+
f2(0, ar2); // COMPLIANT
2929
f2(0, ar2p); // NON_COMPLIANT
3030
f2(0, ar3); // COMPLIANT
3131
f2(0, ar3p); // COMPLIANT
@@ -46,4 +46,21 @@ void t1() {
4646
f4(0, ar3); // COMPLIANT
4747
f4(0, ar3p); // COMPLIANT
4848
f4(0, ar4); // COMPLIANT
49+
}
50+
51+
void t2() {
52+
int ar2[2] = {1, 2};
53+
int ar2b[2] = {1, 2, 3};
54+
int *ar2p = ar2;
55+
int ar3[3];
56+
ar3[0] = 1;
57+
ar3[1] = 2;
58+
ar3[2] = 3;
59+
int ar4[4] = {1, 2, 3, 4};
60+
61+
f1(ar2); // NON_COMPLIANT
62+
f1(ar2b); // NON_COMPLIANT
63+
f1(ar2p); // NON_COMPLIANT
64+
f1(ar3); // COMPLIANT
65+
f1(ar4); // COMPLIANT
4966
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
No expected results have yet been specified
1+
| test.c:6:3:6:4 | call to f2 | The value returned by this call shall be used or cast to `void`. |
2+
| test.c:15:3:15:9 | call to expression | The value returned by this call shall be used or cast to `void`. |

cpp/common/src/codingstandards/cpp/exclusions/c/Contracts6.qll

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,42 @@ newtype Contracts6Query =
99
TArrayFunctionArgumentNumberOfElementsQuery() or
1010
TValueReturnedByAFunctionNotUsedQuery()
1111

12-
predicate isContracts6QueryMetadata(Query query, string queryId, string ruleId) {
12+
predicate isContracts6QueryMetadata(Query query, string queryId, string ruleId, string category) {
1313
query =
1414
// `Query` instance for the `doNotModifyConstantObjects` query
1515
Contracts6Package::doNotModifyConstantObjectsQuery() and
1616
queryId =
1717
// `@id` for the `doNotModifyConstantObjects` query
1818
"c/cert/do-not-modify-constant-objects" and
19-
ruleId = "EXP40-C"
19+
ruleId = "EXP40-C" and
20+
category = "rule"
2021
or
2122
query =
2223
// `Query` instance for the `rightHandOperandOfAShiftOperatorRange` query
2324
Contracts6Package::rightHandOperandOfAShiftOperatorRangeQuery() and
2425
queryId =
2526
// `@id` for the `rightHandOperandOfAShiftOperatorRange` query
2627
"c/misra/right-hand-operand-of-a-shift-operator-range" and
27-
ruleId = "RULE-12-2"
28+
ruleId = "RULE-12-2" and
29+
category = "required"
2830
or
2931
query =
3032
// `Query` instance for the `arrayFunctionArgumentNumberOfElements` query
3133
Contracts6Package::arrayFunctionArgumentNumberOfElementsQuery() and
3234
queryId =
3335
// `@id` for the `arrayFunctionArgumentNumberOfElements` query
3436
"c/misra/array-function-argument-number-of-elements" and
35-
ruleId = "RULE-17-5"
37+
ruleId = "RULE-17-5" and
38+
category = "advisory"
3639
or
3740
query =
3841
// `Query` instance for the `valueReturnedByAFunctionNotUsed` query
3942
Contracts6Package::valueReturnedByAFunctionNotUsedQuery() and
4043
queryId =
4144
// `@id` for the `valueReturnedByAFunctionNotUsed` query
4245
"c/misra/value-returned-by-a-function-not-used" and
43-
ruleId = "RULE-17-7"
46+
ruleId = "RULE-17-7" and
47+
category = "required"
4448
}
4549

4650
module Contracts6Package {

0 commit comments

Comments
 (0)