Skip to content

Commit 8485924

Browse files
committed
Rule 24-5-2 - NoMemoryFunctionsFromCString.ql
Adds a new query to detect use of banned cstring functions. [a]
1 parent 367a18a commit 8485924

File tree

4 files changed

+139
-0
lines changed

4 files changed

+139
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* @id cpp/misra/no-memory-functions-from-c-string
3+
* @name RULE-24-5-2: The C++ Standard Library functions memcpy, memmove and memcmp from <cstring> shall not be used
4+
* @description Using memcpy, memmove or memcmp from <cstring> can result in undefined behavior due
5+
* to overlapping memory, non-trivially copyable objects, or unequal comparison of
6+
* logically equal objects.
7+
* @kind problem
8+
* @precision very-high
9+
* @problem.severity error
10+
* @tags external/misra/id/rule-24-5-2
11+
* scope/single-translation-unit
12+
* external/misra/enforcement/decidable
13+
* external/misra/obligation/required
14+
*/
15+
16+
import cpp
17+
import codingstandards.cpp.misra
18+
import codingstandards.cpp.BannedFunctions
19+
20+
class BannedMemoryFunction extends Function {
21+
BannedMemoryFunction() { this.hasGlobalOrStdName(["memcpy", "memmove", "memcmp"]) }
22+
}
23+
24+
from BannedFunctions<BannedMemoryFunction>::Use use
25+
where not isExcluded(use, BannedAPIsPackage::noMemoryFunctionsFromCStringQuery())
26+
select use, use.getAction() + " banned function '" + use.getFunctionName() + "' from <cstring>."
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
| test.cpp:9:3:9:8 | call to memcpy | Call to banned function 'memcpy' from <cstring>. |
2+
| test.cpp:10:3:10:13 | call to memcpy | Call to banned function 'memcpy' from <cstring>. |
3+
| test.cpp:17:3:17:9 | call to memmove | Call to banned function 'memmove' from <cstring>. |
4+
| test.cpp:18:3:18:14 | call to memmove | Call to banned function 'memmove' from <cstring>. |
5+
| test.cpp:25:12:25:17 | call to memcmp | Call to banned function 'memcmp' from <cstring>. |
6+
| test.cpp:26:12:26:22 | call to memcmp | Call to banned function 'memcmp' from <cstring>. |
7+
| test.cpp:30:52:30:57 | memcpy | Address taken for banned function 'memcpy' from <cstring>. |
8+
| test.cpp:31:52:31:58 | memmove | Address taken for banned function 'memmove' from <cstring>. |
9+
| test.cpp:32:56:32:61 | memcmp | Address taken for banned function 'memcmp' from <cstring>. |
10+
| test.cpp:34:52:34:62 | memcpy | Address taken for banned function 'memcpy' from <cstring>. |
11+
| test.cpp:36:7:36:18 | memmove | Address taken for banned function 'memmove' from <cstring>. |
12+
| test.cpp:38:7:38:17 | memcmp | Address taken for banned function 'memcmp' from <cstring>. |
13+
| test.cpp:50:7:50:12 | call to memcmp | Call to banned function 'memcmp' from <cstring>. |
14+
| test.cpp:53:7:53:17 | call to memcmp | Call to banned function 'memcmp' from <cstring>. |
15+
| test.cpp:61:7:61:12 | call to memcmp | Call to banned function 'memcmp' from <cstring>. |
16+
| test.cpp:64:7:64:17 | call to memcmp | Call to banned function 'memcmp' from <cstring>. |
17+
| test.cpp:71:3:71:8 | call to memcpy | Call to banned function 'memcpy' from <cstring>. |
18+
| test.cpp:72:3:72:9 | call to memmove | Call to banned function 'memmove' from <cstring>. |
19+
| test.cpp:74:3:74:13 | call to memcpy | Call to banned function 'memcpy' from <cstring>. |
20+
| test.cpp:75:3:75:14 | call to memmove | Call to banned function 'memmove' from <cstring>. |
21+
| test.cpp:78:1:78:28 | #define CUSTOM_MEMCPY memcpy | Call to banned function 'memcpy' from <cstring>. |
22+
| test.cpp:79:1:79:30 | #define CUSTOM_MEMMOVE memmove | Call to banned function 'memmove' from <cstring>. |
23+
| test.cpp:80:1:80:28 | #define CUSTOM_MEMCMP memcmp | Call to banned function 'memcmp' from <cstring>. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-24-5-2/NoMemoryFunctionsFromCString.ql
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#include <cstdint>
2+
#include <cstring>
3+
#include <string.h>
4+
5+
void test_memcpy_usage() {
6+
std::uint8_t l1[10];
7+
std::uint8_t l2[10];
8+
9+
memcpy(l1, l2, 10); // NON_COMPLIANT
10+
std::memcpy(l1, l2, 10); // NON_COMPLIANT
11+
}
12+
13+
void test_memmove_usage() {
14+
std::uint8_t l1[10];
15+
std::uint8_t l2[10];
16+
17+
memmove(l1, l2, 10); // NON_COMPLIANT
18+
std::memmove(l1, l2, 10); // NON_COMPLIANT
19+
}
20+
21+
void test_memcmp_usage() {
22+
std::uint8_t l1[10];
23+
std::uint8_t l2[10];
24+
25+
int l3 = memcmp(l1, l2, 10); // NON_COMPLIANT
26+
int l4 = std::memcmp(l1, l2, 10); // NON_COMPLIANT
27+
}
28+
29+
void test_function_pointers() {
30+
void *(*l1)(void *, const void *, std::size_t) = memcpy; // NON_COMPLIANT
31+
void *(*l2)(void *, const void *, std::size_t) = memmove; // NON_COMPLIANT
32+
int (*l3)(const void *, const void *, std::size_t) = memcmp; // NON_COMPLIANT
33+
34+
void *(*l4)(void *, const void *, std::size_t) = std::memcpy; // NON_COMPLIANT
35+
void *(*l5)(void *, const void *, std::size_t) =
36+
std::memmove; // NON_COMPLIANT
37+
int (*l6)(const void *, const void *, std::size_t) =
38+
std::memcmp; // NON_COMPLIANT
39+
}
40+
41+
struct S {
42+
bool m1;
43+
std::int64_t m2;
44+
};
45+
46+
void test_struct_comparison() {
47+
S l1{true, 42};
48+
S l2{true, 42};
49+
50+
if (memcmp(&l1, &l2, sizeof(S)) != 0) { // NON_COMPLIANT
51+
}
52+
53+
if (std::memcmp(&l1, &l2, sizeof(S)) != 0) { // NON_COMPLIANT
54+
}
55+
}
56+
57+
void test_buffer_comparison() {
58+
char l1[12];
59+
char l2[12];
60+
61+
if (memcmp(l1, l2, sizeof(l1)) != 0) { // NON_COMPLIANT
62+
}
63+
64+
if (std::memcmp(l1, l2, sizeof(l1)) != 0) { // NON_COMPLIANT
65+
}
66+
}
67+
68+
void test_overlapping_memory() {
69+
std::uint8_t l1[20];
70+
71+
memcpy(l1 + 5, l1, 10); // NON_COMPLIANT
72+
memmove(l1 + 5, l1, 10); // NON_COMPLIANT
73+
74+
std::memcpy(l1 + 5, l1, 10); // NON_COMPLIANT
75+
std::memmove(l1 + 5, l1, 10); // NON_COMPLIANT
76+
}
77+
78+
#define CUSTOM_MEMCPY memcpy // NON_COMPLIANT
79+
#define CUSTOM_MEMMOVE memmove // NON_COMPLIANT
80+
#define CUSTOM_MEMCMP memcmp // NON_COMPLIANT
81+
82+
void test_macro_expansion() {
83+
std::uint8_t l1[10];
84+
std::uint8_t l2[10];
85+
86+
CUSTOM_MEMCPY(l1, l2, 10);
87+
CUSTOM_MEMMOVE(l1, l2, 10);
88+
int l3 = CUSTOM_MEMCMP(l1, l2, 10);
89+
}

0 commit comments

Comments
 (0)