Skip to content

Commit 03a6499

Browse files
committed
RULE-8-2-7 - NoPointerToIntegralCast
Detects casts that convert pointer types to integral types, which can make code harder to understand and may break pointer tracking in analysis tools. [a]
1 parent 414e8a7 commit 03a6499

File tree

4 files changed

+119
-0
lines changed

4 files changed

+119
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* @id cpp/misra/no-pointer-to-integral-cast
3+
* @name RULE-8-2-7: A cast should not convert a pointer type to an integral type
4+
* @description Casting between pointer types and integral types makes code behavior harder to
5+
* understand and may cause pointer tracking tools to become unreliable.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-8-2-7
10+
* scope/single-translation-unit
11+
* external/misra/enforcement/decidable
12+
* external/misra/obligation/advisory
13+
*/
14+
15+
import cpp
16+
import codingstandards.cpp.misra
17+
18+
from Cast cast, Type sourceType, Type targetType
19+
where
20+
not isExcluded(cast, Conversions2Package::noPointerToIntegralCastQuery()) and
21+
sourceType = cast.getExpr().getType().getUnspecifiedType() and
22+
targetType = cast.getType().getUnspecifiedType() and
23+
(sourceType instanceof PointerType or sourceType instanceof FunctionPointerType) and
24+
targetType instanceof IntegralType
25+
select cast, "Cast converts pointer type to integral type '" + targetType.toString() + "'."
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
| test.cpp:22:22:22:59 | reinterpret_cast<intptr_t>... | Cast converts pointer type to integral type 'long'. |
2+
| test.cpp:23:23:23:61 | reinterpret_cast<uintptr_t>... | Cast converts pointer type to integral type 'unsigned long'. |
3+
| test.cpp:24:20:24:55 | reinterpret_cast<int8_t>... | Cast converts pointer type to integral type 'signed char'. |
4+
| test.cpp:25:21:25:57 | reinterpret_cast<uint8_t>... | Cast converts pointer type to integral type 'unsigned char'. |
5+
| test.cpp:26:21:26:57 | reinterpret_cast<int16_t>... | Cast converts pointer type to integral type 'signed short'. |
6+
| test.cpp:27:22:27:59 | reinterpret_cast<uint16_t>... | Cast converts pointer type to integral type 'unsigned short'. |
7+
| test.cpp:28:21:28:59 | reinterpret_cast<int32_t>... | Cast converts pointer type to integral type 'signed int'. |
8+
| test.cpp:29:22:29:61 | reinterpret_cast<uint32_t>... | Cast converts pointer type to integral type 'unsigned int'. |
9+
| test.cpp:30:22:30:61 | reinterpret_cast<int64_t>... | Cast converts pointer type to integral type 'signed long'. |
10+
| test.cpp:32:7:32:47 | reinterpret_cast<uint64_t>... | Cast converts pointer type to integral type 'unsigned long'. |
11+
| test.cpp:33:14:33:42 | reinterpret_cast<long>... | Cast converts pointer type to integral type 'long'. |
12+
| test.cpp:34:23:34:60 | reinterpret_cast<unsigned long>... | Cast converts pointer type to integral type 'unsigned long'. |
13+
| test.cpp:35:13:35:40 | reinterpret_cast<int>... | Cast converts pointer type to integral type 'int'. |
14+
| test.cpp:36:22:36:58 | reinterpret_cast<unsigned int>... | Cast converts pointer type to integral type 'unsigned int'. |
15+
| test.cpp:64:7:64:47 | reinterpret_cast<intptr_t>... | Cast converts pointer type to integral type 'long'. |
16+
| test.cpp:66:7:66:48 | reinterpret_cast<uintptr_t>... | Cast converts pointer type to integral type 'unsigned long'. |
17+
| test.cpp:67:14:67:45 | reinterpret_cast<long>... | Cast converts pointer type to integral type 'long'. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-8-2-7/NoPointerToIntegralCast.ql
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include <cstdint>
2+
3+
struct S {
4+
int m1;
5+
};
6+
7+
class C {
8+
public:
9+
int m1;
10+
};
11+
12+
void test_pointer_to_integral_casts() {
13+
S s;
14+
S *s_ptr = &s;
15+
C c;
16+
C *c_ptr = &c;
17+
int l1 = 42;
18+
int *int_ptr = &l1;
19+
void *void_ptr = &l1;
20+
21+
// Non-compliant cases - pointer to integral type casts
22+
std::intptr_t l2 = reinterpret_cast<std::intptr_t>(s_ptr); // NON_COMPLIANT
23+
std::uintptr_t l3 = reinterpret_cast<std::uintptr_t>(s_ptr); // NON_COMPLIANT
24+
std::int8_t l4 = reinterpret_cast<std::int8_t>(s_ptr); // NON_COMPLIANT
25+
std::uint8_t l5 = reinterpret_cast<std::uint8_t>(s_ptr); // NON_COMPLIANT
26+
std::int16_t l6 = reinterpret_cast<std::int16_t>(c_ptr); // NON_COMPLIANT
27+
std::uint16_t l7 = reinterpret_cast<std::uint16_t>(c_ptr); // NON_COMPLIANT
28+
std::int32_t l8 = reinterpret_cast<std::int32_t>(int_ptr); // NON_COMPLIANT
29+
std::uint32_t l9 = reinterpret_cast<std::uint32_t>(int_ptr); // NON_COMPLIANT
30+
std::int64_t l10 = reinterpret_cast<std::int64_t>(void_ptr); // NON_COMPLIANT
31+
std::uint64_t l11 =
32+
reinterpret_cast<std::uint64_t>(void_ptr); // NON_COMPLIANT
33+
long l12 = reinterpret_cast<long>(s_ptr); // NON_COMPLIANT
34+
unsigned long l13 = reinterpret_cast<unsigned long>(s_ptr); // NON_COMPLIANT
35+
int l14 = reinterpret_cast<int>(s_ptr); // NON_COMPLIANT
36+
unsigned int l15 = reinterpret_cast<unsigned int>(s_ptr); // NON_COMPLIANT
37+
}
38+
39+
void test_compliant_pointer_operations() {
40+
S s;
41+
S *s_ptr = &s;
42+
C c;
43+
C *c_ptr = &c;
44+
int l1 = 42;
45+
int *int_ptr = &l1;
46+
47+
// Compliant cases - pointer to pointer casts
48+
void *l16 = static_cast<void *>(s_ptr); // COMPLIANT
49+
S *l17 = static_cast<S *>(static_cast<void *>(s_ptr)); // COMPLIANT
50+
C *l18 = reinterpret_cast<C *>(s_ptr); // COMPLIANT
51+
52+
// Compliant cases - using pointers without casting to integral
53+
S *l19 = s_ptr; // COMPLIANT
54+
if (s_ptr != nullptr) { // COMPLIANT
55+
s_ptr->m1 = 10; // COMPLIANT
56+
}
57+
}
58+
59+
void test_function_pointer_to_integral() {
60+
void (*func_ptr)() = nullptr;
61+
62+
// Non-compliant cases - function pointer to integral type casts
63+
std::intptr_t l20 =
64+
reinterpret_cast<std::intptr_t>(func_ptr); // NON_COMPLIANT
65+
std::uintptr_t l21 =
66+
reinterpret_cast<std::uintptr_t>(func_ptr); // NON_COMPLIANT
67+
long l22 = reinterpret_cast<long>(func_ptr); // NON_COMPLIANT
68+
}
69+
70+
void test_member_pointer_to_integral() {
71+
// Member pointer to integral type casts are forbidden by the rule, but also
72+
// prohibited by the compiler, e.g.
73+
// int S::*member_ptr = &S::m1;
74+
// std::intptr_t l23 = reinterpret_cast<std::intptr_t>(member_ptr);
75+
// std::uintptr_t l24 = reinterpret_cast<std::uintptr_t>(member_ptr);
76+
}

0 commit comments

Comments
 (0)