Skip to content

Commit 259f714

Browse files
committed
C++: Model operator new and operator new[].
1 parent ef68bd6 commit 259f714

File tree

3 files changed

+59
-8
lines changed

3 files changed

+59
-8
lines changed

cpp/ql/src/semmle/code/cpp/exprs/Expr.qll

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import semmle.code.cpp.Element
22
private import semmle.code.cpp.Enclosing
33
private import semmle.code.cpp.internal.ResolveClass
44
private import semmle.code.cpp.internal.AddressConstantExpression
5+
private import semmle.code.cpp.models.implementations.Allocation
56

67
/**
78
* A C/C++ expression.
@@ -804,8 +805,10 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr {
804805
* call the constructor of `T` but will not allocate memory.
805806
*/
806807
Expr getPlacementPointer() {
807-
isStandardPlacementNewAllocator(this.getAllocator()) and
808-
result = this.getAllocatorCall().getArgument(1)
808+
result =
809+
this
810+
.getAllocatorCall()
811+
.getArgument(this.getAllocator().(OperatorNewAllocationFunction).getPlacementArgument())
809812
}
810813
}
811814

@@ -1194,12 +1197,6 @@ private predicate convparents(Expr child, int idx, Element parent) {
11941197
)
11951198
}
11961199

1197-
private predicate isStandardPlacementNewAllocator(Function operatorNew) {
1198-
operatorNew.getName().matches("operator new%") and
1199-
operatorNew.getNumberOfParameters() = 2 and
1200-
operatorNew.getParameter(1).getType() instanceof VoidPointerType
1201-
}
1202-
12031200
// Pulled out for performance. See QL-796.
12041201
private predicate hasNoConversions(Expr e) { not e.hasConversion() }
12051202

cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,39 @@ class SizelessAllocationFunction extends AllocationFunction {
215215
}
216216
}
217217

218+
/**
219+
* An `operator new` or `operator new[]` function that may be associated with a `new` or
220+
* `new[]` expression. Note that `new` and `new[]` are not function calls, but these
221+
* functions may also be called directly.
222+
*/
223+
class OperatorNewAllocationFunction extends AllocationFunction {
224+
OperatorNewAllocationFunction() {
225+
exists(string name |
226+
hasGlobalOrStdName(name) and
227+
(
228+
// operator new(bytes, ...)
229+
name = "operator new" or
230+
// operator new[](bytes, ...)
231+
name = "operator new[]"
232+
)
233+
)
234+
}
235+
236+
override int getSizeArg() { result = 0 }
237+
238+
override predicate requiresDealloc() { not exists(getPlacementArgument()) }
239+
240+
/**
241+
* Gets the position of the placement pointer if this is a placement
242+
* `operator new` function.
243+
*/
244+
int getPlacementArgument() {
245+
getNumberOfParameters() = 2 and
246+
getParameter(1).getType() instanceof VoidPointerType and
247+
result = 1
248+
}
249+
}
250+
218251
/**
219252
* An allocation expression that is a function call, such as call to `malloc`.
220253
*/

cpp/ql/test/library-tests/allocators/allocators.expected

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,31 @@ deleteArrayExprs
4747
| allocators.cpp:82:3:82:49 | delete[] | PolymorphicBase | operator delete[](void *, unsigned long) -> void | 8 | 8 | sized |
4848
| allocators.cpp:83:3:83:23 | delete[] | int | operator delete[](void *, unsigned long) -> void | 4 | 4 | sized |
4949
allocationFunctions
50+
| allocators.cpp:7:7:7:18 | operator new | getSizeArg = 0, requiresDealloc |
51+
| allocators.cpp:8:7:8:20 | operator new[] | getSizeArg = 0, requiresDealloc |
52+
| allocators.cpp:9:7:9:18 | operator new | getSizeArg = 0, requiresDealloc |
53+
| allocators.cpp:10:7:10:20 | operator new[] | getSizeArg = 0, requiresDealloc |
54+
| allocators.cpp:121:7:121:18 | operator new | getSizeArg = 0 |
55+
| allocators.cpp:122:7:122:20 | operator new[] | getSizeArg = 0 |
56+
| allocators.cpp:123:7:123:18 | operator new | getSizeArg = 0, requiresDealloc |
57+
| allocators.cpp:124:7:124:20 | operator new[] | getSizeArg = 0, requiresDealloc |
58+
| file://:0:0:0:0 | operator new | getSizeArg = 0, requiresDealloc |
59+
| file://:0:0:0:0 | operator new | getSizeArg = 0, requiresDealloc |
60+
| file://:0:0:0:0 | operator new[] | getSizeArg = 0, requiresDealloc |
61+
| file://:0:0:0:0 | operator new[] | getSizeArg = 0, requiresDealloc |
5062
allocationExprs
5163
| allocators.cpp:49:3:49:9 | new | getSizeBytes = 4, requiresDealloc |
64+
| allocators.cpp:50:3:50:15 | call to operator new | getSizeExpr = <error expr>, getSizeMult = 1, requiresDealloc |
5265
| allocators.cpp:50:3:50:15 | new | getSizeBytes = 4, requiresDealloc |
5366
| allocators.cpp:51:3:51:11 | new | getSizeBytes = 4, requiresDealloc |
5467
| allocators.cpp:52:3:52:14 | new | getSizeBytes = 8, requiresDealloc |
68+
| allocators.cpp:53:3:53:27 | call to operator new | getSizeExpr = <error expr>, getSizeMult = 1, requiresDealloc |
5569
| allocators.cpp:53:3:53:27 | new | getSizeBytes = 8, requiresDealloc |
5670
| allocators.cpp:54:3:54:17 | new | getSizeBytes = 256, requiresDealloc |
71+
| allocators.cpp:55:3:55:25 | call to operator new | getSizeExpr = <error expr>, getSizeMult = 1, requiresDealloc |
5772
| allocators.cpp:55:3:55:25 | new | getSizeBytes = 256, requiresDealloc |
5873
| allocators.cpp:68:3:68:12 | new[] | getSizeExpr = n, getSizeMult = 4, requiresDealloc |
74+
| allocators.cpp:69:3:69:18 | call to operator new[] | getSizeExpr = <error expr>, getSizeMult = 1, requiresDealloc |
5975
| allocators.cpp:69:3:69:18 | new[] | getSizeExpr = n, getSizeMult = 4, requiresDealloc |
6076
| allocators.cpp:70:3:70:15 | new[] | getSizeExpr = n, getSizeMult = 8, requiresDealloc |
6177
| allocators.cpp:71:3:71:20 | new[] | getSizeExpr = n, getSizeMult = 256, requiresDealloc |
@@ -64,13 +80,18 @@ allocationExprs
6480
| allocators.cpp:108:3:108:19 | new[] | getSizeExpr = n, getSizeMult = 1, requiresDealloc |
6581
| allocators.cpp:109:3:109:35 | new | getSizeBytes = 128, requiresDealloc |
6682
| allocators.cpp:110:3:110:37 | new[] | getSizeBytes = 1280, requiresDealloc |
83+
| allocators.cpp:129:3:129:21 | call to operator new | getSizeExpr = <error expr>, getSizeMult = 1 |
6784
| allocators.cpp:129:3:129:21 | new | getSizeBytes = 4 |
85+
| allocators.cpp:132:3:132:17 | call to operator new[] | getSizeExpr = <error expr>, getSizeMult = 1 |
6886
| allocators.cpp:132:3:132:17 | new[] | getSizeBytes = 4 |
87+
| allocators.cpp:135:3:135:26 | call to operator new | getSizeExpr = <error expr>, getSizeMult = 1, requiresDealloc |
6988
| allocators.cpp:135:3:135:26 | new | getSizeBytes = 4, requiresDealloc |
89+
| allocators.cpp:136:3:136:26 | call to operator new[] | getSizeExpr = <error expr>, getSizeMult = 1, requiresDealloc |
7090
| allocators.cpp:136:3:136:26 | new[] | getSizeBytes = 8, requiresDealloc |
7191
| allocators.cpp:142:13:142:27 | new[] | getSizeExpr = x, getSizeMult = 10, requiresDealloc |
7292
| allocators.cpp:143:13:143:28 | new[] | getSizeBytes = 400, requiresDealloc |
7393
| allocators.cpp:144:13:144:31 | new[] | getSizeExpr = x, getSizeMult = 900, requiresDealloc |
94+
| allocators.cpp:149:8:149:19 | call to operator new | getSizeBytes = 4, getSizeExpr = sizeof(int), getSizeMult = 1, requiresDealloc |
7495
deallocationFunctions
7596
deallocationExprs
7697
| allocators.cpp:59:3:59:35 | delete | getFreedExpr = 0 |

0 commit comments

Comments
 (0)