Skip to content

Commit 15ed053

Browse files
Merge pull request #190 from github/jeongsoolee09/MISRA_21-13_and-21-15
Implement MISRA RULE-21-13 and RULE-21-15
2 parents d4c68f6 + 7dba082 commit 15ed053

17 files changed

+261
-3
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* @id c/misra/ctype-function-arg-not-unsigned-char-or-eof
3+
* @name RULE-21-13: <ctype.h> function arguments shall be represented as unsigned char
4+
* @description Passing arguments to <ctype.h> functions outside the range of unsigned char or EOF
5+
* causes undefined behavior.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-21-13
10+
* external/misra/obligation/mandatory
11+
*/
12+
13+
import cpp
14+
import codingstandards.c.misra
15+
import codingstandards.cpp.CharFunctions
16+
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
17+
18+
from UseOfToOrIsChar ctypeCall
19+
where
20+
not isExcluded(ctypeCall,
21+
StandardLibraryFunctionTypesPackage::ctypeFunctionArgNotUnsignedCharOrEofQuery()) and
22+
not exists(Expr ctypeCallArgument | ctypeCallArgument = ctypeCall.getConvertedArgument() |
23+
/* The argument's value should be in the EOF + `unsigned char` range. */
24+
-1 <= lowerBound(ctypeCallArgument) and upperBound(ctypeCallArgument) <= 255
25+
)
26+
select ctypeCall,
27+
"The <ctype.h> function " + ctypeCall + " accepts an argument " + ctypeCall.getConvertedArgument()
28+
+ " that is not an unsigned char nor an EOF."
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* @id c/misra/memcpy-memmove-memcmp-arg-not-pointers-to-compatible-types
3+
* @name RULE-21-15: The pointer arguments to the Standard Library functions memcpy, memmove and memcmp shall be pointers
4+
* @description Passing pointers to incompatible types as arguments to memcpy, memmove and memcmp
5+
* indicates programmers' confusion.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-21-15
10+
* external/misra/obligation/required
11+
*/
12+
13+
import cpp
14+
import codingstandards.c.misra
15+
import codingstandards.c.Pointers
16+
17+
class MemCmpMoveCpy extends Function {
18+
// Couldn't extend BuiltInFunction because it misses `memcmp`
19+
MemCmpMoveCpy() {
20+
this.getName().regexpMatch("mem(cmp|cpy|move)") and
21+
this.getADeclaration().getAFile().(HeaderFile).getBaseName() = "string.h"
22+
}
23+
}
24+
25+
from FunctionCall fc
26+
where
27+
not isExcluded(fc,
28+
StandardLibraryFunctionTypesPackage::memcpyMemmoveMemcmpArgNotPointersToCompatibleTypesQuery()) and
29+
exists(MemCmpMoveCpy memfun, Type dstType, Type srcType | fc.getTarget() = memfun |
30+
dstType = fc.getArgument(0).getUnspecifiedType() and
31+
srcType = fc.getArgument(1).getUnspecifiedType() and
32+
(
33+
/* Case 1: dst and src are pointer types */
34+
dstType instanceof PointerType and
35+
srcType instanceof PointerType
36+
or
37+
/* Case 2: dst and src are array types */
38+
dstType instanceof ArrayType and
39+
srcType instanceof ArrayType
40+
) and
41+
not dstType = srcType
42+
)
43+
select fc,
44+
"The dest type " + fc.getArgument(0).getUnspecifiedType() + " and src type " +
45+
fc.getArgument(1).getUnspecifiedType() + " of function " + fc.getTarget() +
46+
" are not compatible."
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| test.c:14:7:14:13 | call to isalnum | The <ctype.h> function call to isalnum accepts an argument c3 that is not an unsigned char nor an EOF. |
2+
| test.c:20:7:20:13 | call to isalnum | The <ctype.h> function call to isalnum accepts an argument c4 that is not an unsigned char nor an EOF. |
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| test.c:14:7:14:17 | isalnum(c) | The <ctype.h> function isalnum(c) accepts an argument (...) that is not an unsigned char nor an EOF. |
2+
| test.c:20:7:20:17 | isalnum(c) | The <ctype.h> function isalnum(c) accepts an argument (...) that is not an unsigned char nor an EOF. |
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| test.c:14:7:14:17 | isalnum(c) | The <ctype.h> function isalnum(c) accepts an argument (...) that is not an unsigned char nor an EOF. |
2+
| test.c:20:7:20:17 | isalnum(c) | The <ctype.h> function isalnum(c) accepts an argument (...) that is not an unsigned char nor an EOF. |
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| test.c:14:7:14:17 | isalnum(c) | The <ctype.h> function isalnum(c) accepts an argument (...) that is not an unsigned char nor an EOF. |
2+
| test.c:20:7:20:17 | isalnum(c) | The <ctype.h> function isalnum(c) accepts an argument (...) that is not an unsigned char nor an EOF. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-21-13/CtypeFunctionArgNotUnsignedCharOrEof.ql

c/misra/test/rules/RULE-21-13/test.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include <ctype.h>
2+
#include <stdio.h>
3+
4+
void sample() {
5+
unsigned char c1 = 'c';
6+
int r1 = isalnum(
7+
c1); // COMPLIANT: ASCII 99 is within unsigned char range of [0, 255]
8+
int r2 = isalnum(EOF); // COMPLIANT: EOF (-1)
9+
10+
int x3 = 256;
11+
int x4 = x3;
12+
int c3 = x4;
13+
int r3 =
14+
isalnum(c3); // NON_COMPLIANT: is outside unsigned char range of [0, 255]
15+
16+
unsigned char x5 = EOF;
17+
unsigned char x6 = x5;
18+
int c4 = x6 + 10000;
19+
int r4 =
20+
isalnum(c4); // NON_COMPLIANT: is outside unsigned char range of [0, 255]
21+
22+
int c5 = getchar();
23+
int r5 = isalnum(
24+
c5); // COMPLIANT: <stdio.h> source functions like getchar are modelled
25+
26+
unsigned char x7;
27+
int c6;
28+
if (x7 == 1) {
29+
c6 = EOF;
30+
} else {
31+
c6 = 'c';
32+
}
33+
int r6 =
34+
isalnum(c6); // COMPLIANT: either control branch make this call compliant
35+
36+
int r7 = isalnum(EOF); // COMPLIANT: EOF (-1)
37+
}
38+
39+
int main() { return 0; }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| test.c:6:3:6:8 | call to memcpy | The dest type int * and src type char * of function memcpy are not compatible. |
2+
| test.c:18:3:18:9 | call to memmove | The dest type char[9] and src type int[2] of function memmove are not compatible. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-21-15/MemcpyMemmoveMemcmpArgNotPointersToCompatibleTypes.ql

0 commit comments

Comments
 (0)