Skip to content

Commit 71a860a

Browse files
committed
C++: Exclude custom operator new allocators from the ThrowingAllocator class.
1 parent e01d712 commit 71a860a

File tree

1 file changed

+27
-1
lines changed

1 file changed

+27
-1
lines changed

cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.ql

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,38 @@ predicate exprMayThrow(Expr e) {
153153
)
154154
}
155155

156+
class NoThrowType extends Struct {
157+
NoThrowType() { this.hasGlobalOrStdOrBslName("nothrow_t") }
158+
}
159+
156160
/** An allocator that might throw an exception. */
157161
class ThrowingAllocator extends Function {
158162
ThrowingAllocator() {
159163
exists(NewOrNewArrayExpr newExpr |
160164
newExpr.getAllocator() = this and
161-
functionMayThrow(this)
165+
// Exclude custom overloads of `operator new`.
166+
// What we really want here is to only include the functions that satisfy `functionMayThrow`, but
167+
// there seems to be examples where `throw()` isn't extracted (which causes false positives).
168+
//
169+
// As noted in the QLDoc for `Function.getAllocatorCall`:
170+
//
171+
// "As a rule of thumb, there will be an allocator call precisely when the type
172+
// being allocated has a custom `operator new`, or when an argument list appears
173+
// after the `new` keyword and before the name of the type being allocated.
174+
//
175+
// In particular note that uses of placement-new and nothrow-new will have an
176+
// allocator call."
177+
//
178+
// So we say an allocator might throw if:
179+
// 1. It doesn't have a body
180+
// 2. there is a parameter that is not `nothrow`
181+
// 3. the allocator isn't marked with `throw()` or `noexcept`.
182+
not exists(this.getBlock()) and
183+
exists(Parameter p | p = this.getAParameter() |
184+
not p.getUnspecifiedType() instanceof NoThrowType
185+
) and
186+
not this.isNoExcept() and
187+
not this.isNoThrow()
162188
)
163189
}
164190
}

0 commit comments

Comments
 (0)