mirror of
https://github.com/github/codeql.git
synced 2026-04-28 02:05:14 +02:00
C++: Detect non-allocating placement new
This adds a `NewOrNewArrayExpr.getPlacementPointer` predicate and uses it in `Alloc.qll` to detect when a `new`-expression is not an allocation. User-defined replacements for `operator new` may not be allocations either, but the code continues to assume that they are. It's possible that we want to change this assumption in the future or leave it up to individual queries to decide on which side to err. It's hard to statically tell whether `operator new` has been overloaded in a particular file because it can be overloaded by a definition that is not in scope but is only linked together with that file.
This commit is contained in:
@@ -78,8 +78,8 @@ predicate isStdLibAllocationExpr(Expr e)
|
||||
*/
|
||||
predicate isAllocationExpr(Expr e) {
|
||||
allocationCall(e)
|
||||
or e instanceof NewExpr
|
||||
or e instanceof NewArrayExpr
|
||||
or
|
||||
e = any(NewOrNewArrayExpr new | not exists(new.getPlacementPointer()))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -664,6 +664,16 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr {
|
||||
* For `new int[5]` the result is `int[5]`.
|
||||
*/
|
||||
abstract Type getAllocatedType();
|
||||
|
||||
/**
|
||||
* Gets the pointer `p` if this expression is of the form `new(p) T...`.
|
||||
* Invocations of this form are non-allocating `new` expressions that may
|
||||
* call the constructor of `T` but will not allocate memory.
|
||||
*/
|
||||
Expr getPlacementPointer() {
|
||||
isStandardPlacementNewAllocator(this.getAllocator()) and
|
||||
result = this.getAllocatorCall().getArgument(1)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -961,3 +971,9 @@ private predicate convparents(Expr child, int idx, Element parent) {
|
||||
child = astChild.getFullyConverted()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isStandardPlacementNewAllocator(Function operatorNew) {
|
||||
operatorNew.getName().matches("operator new%") and
|
||||
operatorNew.getNumberOfParameters() = 2 and
|
||||
operatorNew.getParameter(1).getType() instanceof VoidPointerType
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user