Skip to content

Commit dce0e80

Browse files
committed
Finalize draft of 21-6-1 and factor out duplicated code
1 parent 997cb7a commit dce0e80

File tree

5 files changed

+195
-62
lines changed

5 files changed

+195
-62
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/** Provides classes for modeling dynamic memory allocation and deallocation functions. */
2+
3+
import cpp
4+
5+
/**
6+
* An `operator new` or `operator new[]` allocation function called by a placement-new expression.
7+
*
8+
* The operator functions have a `std::size_t` as their first parameter and a
9+
* `void*` parameter somewhere in the rest of the parameter list.
10+
*/
11+
class PlacementNewOrNewArrayAllocationFunction extends AllocationFunction {
12+
PlacementNewOrNewArrayAllocationFunction() {
13+
this.getName() in ["operator new", "operator new[]"] and
14+
this.getParameter(0).getType().resolveTypedefs*() instanceof Size_t and
15+
this.getAParameter().getUnderlyingType() instanceof VoidPointerType
16+
}
17+
}
18+
19+
/**
20+
* A function that has namespace `std` and has name `allocate` or `deallocate`, including but
21+
* not limited to:
22+
* - `std::allocator<T>::allocate(std::size_t)`
23+
* - `std::allocator<T>::deallocate(T*, std::size_t)`
24+
* - `std::pmr::memory_resource::allocate(std::size_t, std::size_t)`
25+
* - `std::pmr::memory_resource::deallocate(void*, std::size_t, std::size_t)`
26+
*/
27+
class AllocateOrDeallocateStdlibMemberFunction extends MemberFunction {
28+
AllocateOrDeallocateStdlibMemberFunction() {
29+
this.getName() in ["allocate", "deallocate"] and
30+
this.getNamespace().getParentNamespace*() instanceof StdNamespace
31+
}
32+
}

cpp/misra/src/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.ql

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,7 @@
1515

1616
import cpp
1717
import codingstandards.cpp.misra
18-
19-
class PlacementNewOrNewArrayAllocationFunction extends AllocationFunction {
20-
/* NOTE: Duplicate with RULE-21-6-2 */
21-
PlacementNewOrNewArrayAllocationFunction() {
22-
this.getName() in ["operator new", "operator new[]"] and
23-
this.getParameter(0).getType().resolveTypedefs*() instanceof Size_t and
24-
this.getAParameter().getUnderlyingType() instanceof VoidPointerType
25-
}
26-
}
27-
28-
/**
29-
* A function that has namespace `std` and has name `allocate` or `deallocate`, including but not limited to:
30-
* - `std::allocator<T>::allocate(std::size_t)`
31-
* - `std::allocator<T>::dellocate(T*, std::size_t)`
32-
* - `std::pmr::memory_resource::allocate(std::size_t, std::size_t)`
33-
* - `std::pmr::memory_resource::deallocate(void*, std::size_t, std::size_t)`
34-
*/
35-
class AllocateOrDeallocateStdlibMemberFunction extends MemberFunction {
36-
/* NOTE: Duplicate with RULE-21-6-2 */
37-
AllocateOrDeallocateStdlibMemberFunction() {
38-
this.getName() in ["allocate", "deallocate"] and
39-
this.getNamespace().getParentNamespace*() instanceof StdNamespace
40-
}
41-
}
18+
import codingstandards.cpp.DynamicMemory
4219

4320
/**
4421
* A function that directly or indirectly allocates dynamic memory.
@@ -56,6 +33,8 @@ class DirectDynamicMemoryAllocatingFunction extends DynamicMemoryAllocatingFunct
5633
DirectDynamicMemoryAllocatingFunction() {
5734
this instanceof AllocationFunction and
5835
not this instanceof PlacementNewOrNewArrayAllocationFunction
36+
or
37+
this.hasGlobalOrStdName("aligned_alloc")
5938
}
6039
}
6140

@@ -226,19 +205,48 @@ abstract class DynamicMemoryDeallocatingFunction extends Function { }
226205

227206
/**
228207
* A function that directly deallocates dynamic memory.
229-
* Includes C allocation functions (`free`)
230-
* and C++ allocation functions (`operator delete`, `operator delete[]`).
208+
* Includes C deallocation functions (`free`)
209+
* and C++ deallocation functions (`operator delete`, `operator delete[]`).
231210
*/
232-
class DirectDynamicMemoryDeallocatingFunction extends DynamicMemoryDeallocatingFunction { }
211+
class DirectDynamicMemoryDeallocatingFunction extends DynamicMemoryDeallocatingFunction {
212+
DirectDynamicMemoryDeallocatingFunction() {
213+
this instanceof DeallocationFunction
214+
}
215+
}
233216

234217
/**
235-
* A function that indirectly allocates dynamic memory through
218+
* A function that indirectly deallocates dynamic memory through
236219
* standard library classes and their member functions (e.g. `std::allocator::deallocate`).
237220
*/
238-
class IndirectDynamicMemoryDeallocatingFunction extends DynamicMemoryDeallocatingFunction { }
221+
class IndirectDynamicMemoryDeallocatingFunction extends DynamicMemoryDeallocatingFunction {
222+
IndirectDynamicMemoryDeallocatingFunction() {
223+
this instanceof AllocateOrDeallocateStdlibMemberFunction and
224+
this.getName() = "deallocate"
225+
}
226+
}
239227

240-
from FunctionCall call
228+
from FunctionCall call, string message
241229
where
242230
not isExcluded(call, Banned7Package::dynamicMemoryShouldNotBeUsedQuery()) and
243-
call.getTarget() instanceof DynamicMemoryAllocatingFunction
244-
select call, call.getTarget().toString()
231+
(
232+
// Direct allocation: malloc, calloc, realloc, aligned_alloc, operator new, operator new[]
233+
call.getTarget() instanceof DirectDynamicMemoryAllocatingFunction and
234+
message =
235+
"Call to dynamic memory allocating function '" + call.getTarget().getName() +
236+
"'."
237+
or
238+
// Indirect allocation: std library types that allocate internally
239+
call.getTarget() instanceof IndirectDynamicMemoryAllocatingFunction and
240+
message =
241+
"Call to '" + call.getTarget().getName() +
242+
"' that dynamically allocates memory via the standard library."
243+
or
244+
// Deallocation: free, operator delete, operator delete[], std::allocator::deallocate
245+
// Excludes realloc (already caught as allocation).
246+
call.getTarget() instanceof DynamicMemoryDeallocatingFunction and
247+
not call.getTarget() instanceof DynamicMemoryAllocatingFunction and
248+
message =
249+
"Call to dynamic memory deallocating function '" + call.getTarget().getName() +
250+
"'."
251+
)
252+
select call, message

cpp/misra/src/rules/RULE-21-6-2/DynamicMemoryManagedManually.ql

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,7 @@
1717
import cpp
1818
import codingstandards.cpp.misra
1919
import codingstandards.cpp.SmartPointers
20-
21-
/**
22-
* An `operator new` or `operator new[]` allocation function called by a placement-new expression.
23-
*
24-
* The operator functions are supposed to have a `std::size_t` as their first parameter and a
25-
* `void*` parameter somewhere in the rest of the parameter list.
26-
*/
27-
class PlacementNewOrNewArrayAllocationFunction extends AllocationFunction {
28-
PlacementNewOrNewArrayAllocationFunction() {
29-
this.getName() in ["operator new", "operator new[]"] and
30-
this.getParameter(0).getType().resolveTypedefs*() instanceof Size_t and
31-
this.getAParameter().getUnderlyingType() instanceof VoidPointerType
32-
}
33-
}
20+
import codingstandards.cpp.DynamicMemory
3421

3522
class DynamicMemoryManagementFunction extends Function {
3623
DynamicMemoryManagementFunction() {
@@ -52,20 +39,6 @@ class DynamicMemoryManagementFunction extends Function {
5239
}
5340
}
5441

55-
/**
56-
* A function that has namespace `std` and has name `allocate` or `deallocate`, including but not limited to:
57-
* - `std::allocator<T>::allocate(std::size_t)`
58-
* - `std::allocator<T>::dellocate(T*, std::size_t)`
59-
* - `std::pmr::memory_resource::allocate(std::size_t, std::size_t)`
60-
* - `std::pmr::memory_resource::deallocate(void*, std::size_t, std::size_t)`
61-
*/
62-
class AllocateOrDeallocateStdlibMemberFunction extends MemberFunction {
63-
AllocateOrDeallocateStdlibMemberFunction() {
64-
this.getName() in ["allocate", "deallocate"] and
65-
this.getNamespace().getParentNamespace*() instanceof StdNamespace
66-
}
67-
}
68-
6942
/**
7043
* The `std::realloc` (`<cstdlib>`) or `::realloc` (`<stdlib.h>`) function.
7144
*/

0 commit comments

Comments
 (0)