Skip to content

Commit cf12521

Browse files
committed
EssentialTypes: Implement Rule 21.16
Adds a query to find uses of memcmp with pointer types which are prohibited by MISRA C.
1 parent c330ed6 commit cf12521

File tree

4 files changed

+109
-0
lines changed

4 files changed

+109
-0
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/memcmp-on-inappropriate-essential-type-args
3+
* @name RULE-21-16: The pointer arguments to the Standard Library function memcmp shall point to either a pointer type,
4+
* @description The pointer arguments to the Standard Library function memcmp shall point to either
5+
* a pointer type, an essentially signed type, an essentially unsigned type, an
6+
* essentially Boolean type or an essentially enum type
7+
* @kind problem
8+
* @precision very-high
9+
* @problem.severity error
10+
* @tags external/misra/id/rule-21-16
11+
* external/misra/obligation/required
12+
*/
13+
14+
import cpp
15+
import codingstandards.c.misra
16+
import codingstandards.c.misra.EssentialTypes
17+
18+
from FunctionCall memcmp, Expr arg, Type argBaseType
19+
where
20+
not isExcluded(arg, EssentialTypesPackage::memcmpOnInappropriateEssentialTypeArgsQuery()) and
21+
memcmp.getTarget().hasGlobalName("memcmp") and
22+
// Pointer arguments
23+
arg = memcmp.getArgument([0, 1]) and
24+
exists(DerivedType pt |
25+
// Must be a pointer type or array type
26+
(
27+
pt instanceof PointerType or
28+
pt instanceof ArrayType
29+
) and
30+
pt = arg.getType() and
31+
argBaseType = pt.getBaseType() and
32+
// Doesn't point to a pointer type
33+
not argBaseType instanceof PointerType and
34+
// Doesn't point to a type which is essentially signed, unsigned, boolean or enum
35+
not exists(EssentialTypeCategory typeCategory |
36+
typeCategory = getEssentialTypeCategory(argBaseType)
37+
|
38+
typeCategory = EssentiallySignedType() or
39+
typeCategory = EssentiallyUnsignedType() or
40+
typeCategory = EssentiallyBooleanType() or
41+
typeCategory = EssentiallyEnumType()
42+
)
43+
)
44+
select arg, "Argument is a pointer to " + argBaseType + "."
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
| test.c:23:10:23:10 | p | Argument is a pointer to float. |
2+
| test.c:23:13:23:13 | q | Argument is a pointer to float. |
3+
| test.c:35:10:35:10 | p | Argument is a pointer to S1. |
4+
| test.c:35:13:35:13 | q | Argument is a pointer to S1. |
5+
| test.c:41:10:41:10 | p | Argument is a pointer to U. |
6+
| test.c:41:13:41:13 | q | Argument is a pointer to U. |
7+
| test.c:45:10:45:10 | p | Argument is a pointer to char. |
8+
| test.c:45:13:45:13 | q | Argument is a pointer to char. |
9+
| test.c:49:10:49:10 | p | Argument is a pointer to char. |
10+
| test.c:49:13:49:13 | q | Argument is a pointer to char. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-21-16/MemcmpOnInappropriateEssentialTypeArgs.ql

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

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include <stdbool.h>
2+
#include <string.h>
3+
4+
void testMemcmpSignedInt(signed int *p, signed int *q, size_t size) {
5+
memcmp(p, q, size); // COMPLIANT
6+
}
7+
8+
void testMemcmpUnsignedInt(unsigned int *p, unsigned int *q, size_t size) {
9+
memcmp(p, q, size); // COMPLIANT
10+
}
11+
12+
enum E1 { E1_1, E1_2 };
13+
14+
void testMemcmpEnum(enum E1 *p, enum E1 *q, size_t size) {
15+
memcmp(p, q, size); // COMPLIANT
16+
}
17+
18+
void testMemcmpBool(bool *p, bool *q, size_t size) {
19+
memcmp(p, q, size); // COMPLIANT
20+
}
21+
22+
void testMemcmpFloat(float *p, float *q, size_t size) {
23+
memcmp(p, q, size); // NON_COMPLIANT
24+
}
25+
26+
void testMemcmpPointerToPointer(void **p, void **q, size_t size) {
27+
memcmp(p, q, size); // COMPLIANT
28+
}
29+
30+
struct S1 {
31+
int i;
32+
};
33+
34+
void testMemcmpStruct(struct S1 *p, struct S1 *q, size_t size) {
35+
memcmp(p, q, size); // NON_COMPLIANT
36+
}
37+
38+
union U;
39+
40+
void testMemcmpUnion(union U *p, union U *q, size_t size) {
41+
memcmp(p, q, size); // NON_COMPLIANT
42+
}
43+
44+
void testMemcmpChar(char *p, char *q, size_t size) {
45+
memcmp(p, q, size); // NON_COMPLIANT
46+
}
47+
48+
void testMemcmpCharArray(char p[10], char q[10], size_t size) {
49+
memcmp(p, q, size); // NON_COMPLIANT
50+
}
51+
52+
void testMemcmpIntArray(int p[10], int q[10], size_t size) {
53+
memcmp(p, q, size); // COMPLIANT
54+
}

0 commit comments

Comments
 (0)