CPP: Libraries: Add MallocFunction and AllocationExpr to malloc.qll.

This commit is contained in:
Geoffrey White
2019-11-20 19:06:34 +00:00
parent 5f798314d1
commit 376ef2fc8e

View File

@@ -1,70 +1,217 @@
import cpp
/**
* A library routine that allocates memory.
*/
predicate allocationFunction(Function f) {
private predicate allocationFunctionWithSize(Function f, int sizeArg) {
exists(string name |
f.hasGlobalOrStdName(name) and
(
name = "malloc" or
name = "calloc" or
name = "realloc" or
name = "strdup" or
name = "wcsdup"
(name = "malloc" and sizeArg = 0) // malloc(size)
)
or
f.hasGlobalName(name) and
(
name = "_strdup" or
name = "_wcsdup" or
name = "_mbsdup" or
name = "ExAllocatePool" or
name = "ExAllocatePoolWithTag" or
name = "ExAllocatePoolWithTagPriority" or
name = "ExAllocatePoolWithQuota" or
name = "ExAllocatePoolWithQuotaTag" or
name = "ExAllocateFromLookasideListEx" or
name = "ExAllocateFromPagedLookasideList" or
name = "ExAllocateFromNPagedLookasideList" or
name = "ExAllocateTimer" or
name = "IoAllocateMdl" or
name = "IoAllocateWorkItem" or
name = "IoAllocateErrorLogEntry" or
name = "MmAllocateContiguousMemory" or
name = "MmAllocateContiguousNodeMemory" or
name = "MmAllocateContiguousMemorySpecifyCache" or
name = "MmAllocateContiguousMemorySpecifyCacheNode" or
name = "MmAllocateNonCachedMemory" or
name = "MmAllocateMappingAddress" or
name = "MmAllocatePagesForMdl" or
name = "MmAllocatePagesForMdlEx" or
name = "MmAllocateNodePagesForMdlEx" or
name = "MmMapLockedPagesWithReservedMapping" or
name = "MmMapLockedPages" or
name = "MmMapLockedPagesSpecifyCache" or
name = "LocalAlloc" or
name = "LocalReAlloc" or
name = "GlobalAlloc" or
name = "GlobalReAlloc" or
name = "HeapAlloc" or
name = "HeapReAlloc" or
name = "VirtualAlloc" or
name = "CoTaskMemAlloc" or
name = "CoTaskMemRealloc"
(name = "ExAllocatePool" and sizeArg = 1) or // ExAllocatePool(type, size)
(name = "ExAllocatePoolWithTag" and sizeArg = 1) or // ExAllocatePool(type, size, tag)
(name = "ExAllocatePoolWithTagPriority" and sizeArg = 1) or // ExAllocatePoolWithTagPriority(type, size, tag, priority)
(name = "ExAllocatePoolWithQuota" and sizeArg = 1) or // ExAllocatePoolWithQuota(type, size)
(name = "ExAllocatePoolWithQuotaTag" and sizeArg = 1) or // ExAllocatePoolWithQuotaTag(type, size, tag)
(name = "IoAllocateMdl" and sizeArg = 1) or // IoAllocateMdl(address, size, flag, flag, irp)
(name = "IoAllocateErrorLogEntry" and sizeArg = 1) or // IoAllocateErrorLogEntry(object, size)
(name = "MmAllocateContiguousMemory" and sizeArg = 0) or // MmAllocateContiguousMemory(size, maxaddress)
(name = "MmAllocateContiguousNodeMemory" and sizeArg = 0) or // MmAllocateContiguousNodeMemory(size, minaddress, maxaddress, bound, flag, prefer)
(name = "MmAllocateContiguousMemorySpecifyCache" and sizeArg = 0) or // MmAllocateContiguousMemorySpecifyCache(size, minaddress, maxaddress, bound, type)
(name = "MmAllocateContiguousMemorySpecifyCacheNode" and sizeArg = 0) or // MmAllocateContiguousMemorySpecifyCacheNode(size, minaddress, maxaddress, bound, type, prefer)
(name = "MmAllocateNonCachedMemory" and sizeArg = 0) or // MmAllocateNonCachedMemory(size)
(name = "MmAllocateMappingAddress" and sizeArg = 0) or // MmAllocateMappingAddress(size, tag)
(name = "MmAllocatePagesForMdl" and sizeArg = 3) or // MmAllocatePagesForMdl(minaddress, maxaddress, skip, size)
(name = "MmAllocatePagesForMdlEx" and sizeArg = 3) or // MmAllocatePagesForMdlEx(minaddress, maxaddress, skip, size, type, flags)
(name = "MmAllocateNodePagesForMdlEx" and sizeArg = 3) or // MmAllocateNodePagesForMdlEx(minaddress, maxaddress, skip, size, type, prefer, flags)
(name = "LocalAlloc" and sizeArg = 1) or // LocalAlloc(flags, size)
(name = "GlobalAlloc" and sizeArg = 1) or // GlobalAlloc(flags, size)
(name = "HeapAlloc" and sizeArg = 2) or // HeapAlloc(heap, flags, size)
(name = "VirtualAlloc" and sizeArg = 1) or // VirtualAlloc(address, size, type, flag)
(name = "CoTaskMemAlloc" and sizeArg = 0) // CoTaskMemAlloc(size)
)
)
}
private predicate allocationFunctionWithSizeAndMult(Function f, int sizeArg, int multArg) {
exists(string name |
f.hasGlobalOrStdName(name) and
(name = "calloc" and sizeArg = 1 and multArg = 0) // calloc(num, size)
)
}
private predicate allocationFunctionWithSizeRealloc(Function f, int sizeArg, int reallocArg) {
exists(string name |
f.hasGlobalOrStdName(name) and
(
(name = "realloc" and sizeArg = 1 and reallocArg = 0) // realloc(ptr, size)
)
or
f.hasGlobalName(name) and
(
(name = "LocalReAlloc" and sizeArg = 1 and reallocArg = 0) or // LocalReAlloc(ptr, size, flags)
(name = "GlobalReAlloc" and sizeArg = 1 and reallocArg = 0) or // GlobalReAlloc(ptr, size, flags)
(name = "HeapReAlloc" and sizeArg = 3 and reallocArg = 2) or // HeapReAlloc(heap, flags, ptr, size)
(name = "CoTaskMemRealloc" and sizeArg = 1 and reallocArg = 0) // CoTaskMemRealloc(ptr, size)
)
)
}
private predicate allocationFunctionNoSize(Function f) {
exists(string name |
f.hasGlobalOrStdName(name) and
(
name = "strdup" or // strdup(str)
name = "wcsdup" // wcsdup(str)
)
or
f.hasGlobalName(name) and
(
name = "_strdup" or // _strdup(str)
name = "_wcsdup" or // _wcsdup(str)
name = "_mbsdup" or // _mbsdup(str)
name = "ExAllocateFromLookasideListEx" or // ExAllocateFromLookasideListEx(list)
name = "ExAllocateFromPagedLookasideList" or // ExAllocateFromPagedLookasideList(list)
name = "ExAllocateFromNPagedLookasideList" or // ExAllocateFromNPagedLookasideList(list)
name = "ExAllocateTimer" or // ExAllocateTimer(callback, context, attributes)
name = "IoAllocateWorkItem" or // IoAllocateWorkItem(object)
name = "MmMapLockedPagesWithReservedMapping" or // MmMapLockedPagesWithReservedMapping(address, tag, list, type)
name = "MmMapLockedPages" or // MmMapLockedPages(list, mode)
name = "MmMapLockedPagesSpecifyCache" // MmMapLockedPagesSpecifyCache(list, mode, type, address, flag, flag)
)
)
}
/**
* A call to a library routine that allocates memory.
* An allocation function such as `malloc`.
*/
predicate allocationCall(FunctionCall fc) {
allocationFunction(fc.getTarget()) and
(
// realloc(ptr, 0) only frees the pointer
fc.getTarget().hasGlobalOrStdName("realloc") implies not fc.getArgument(1).getValue() = "0"
)
abstract class MallocFunction extends Function {
MallocFunction() {
allocationFunctionWithSize(this, _) or
allocationFunctionWithSizeAndMult(this, _, _) or
allocationFunctionWithSizeRealloc(this, _, _) or
allocationFunctionNoSize(this)
}
/**
* Gets the index of an argument that controls the allocation size, if any.
* The actual allocation size is the product of all size arguments *
* `getSizeMult()`. If there is no result, the size cannot be determined.
*/
int getASizeArg() {
allocationFunctionWithSize(this, result) or
allocationFunctionWithSizeAndMult(this, result, _) or
allocationFunctionWithSizeRealloc(this, result, _)
}
/**
* Gets a constant multiplier for the allocation size, in bytes (usually 1).
*/
int getSizeMult() {
result = 1
}
/**
* Gets the index of the input pointer argument to be reallocated, if this
* is a `realloc` function.
*/
int getReallocPtrArg() {
allocationFunctionWithSizeRealloc(this, _, result)
}
}
private bindingset[f] int round(float f) {
result = (f + 0.5).floor()
}
/**
* An allocation expression such as call to `malloc` or a `new` expression.
*/
abstract class AllocationExpr extends Expr {
AllocationExpr() {
exists(MallocFunction malloc |
// alloc call
this.(FunctionCall).getTarget() = malloc and
// realloc(ptr, 0) only frees the pointer
not (
exists(malloc.getReallocPtrArg()) and
this.(FunctionCall).getArgument(malloc.getASizeArg()).getValue().toInt() = 0
)
) or
this instanceof NewExpr or
this instanceof NewArrayExpr
}
/**
* Gets an expression that controls the allocation size, if any. The actual
* allocation size is the product of all size expressions * `getSizeMult()`.
* If there is no result, the size cannot be determined.
*/
Expr getASizeExpr() {
exists(FunctionCall fc | fc = this |
result = fc.getArgument(fc.getTarget().(MallocFunction).getASizeArg())
) or
// new array expr with variable size
result = this.(NewArrayExpr).getExtent()
}
/**
* Gets a constant multiplier for the allocation size, in bytes (usually 1).
*/
int getSizeMult() {
exists(FunctionCall fc | fc = this |
result = fc.getTarget().(MallocFunction).getSizeMult()
) or
(
// new array expr with variable size
exists(this.(NewArrayExpr).getExtent()) and
result = this.(NewArrayExpr).getAllocatedElementType().getSize()
)
}
/**
* Gets the size of this allocation in bytes, if it is a fixed size and that
* size can be determined.
*/
int getSizeBytes() {
(
// exp(sum(log(x))) = product(x)
result = round(sum(Expr e | e = getASizeExpr() | e.getValue().toInt().log()).exp()) * getSizeMult()
) or
result = this.(NewExpr).getAllocatedType().getSize()
or
result = this.(NewArrayExpr).getAllocatedType().getSize()
}
/**
* Gets the expression for the input pointer argument to be reallocated, if
* this is a `realloc` function.
*/
Expr getReallocPtr() {
exists(FunctionCall fc | fc = this |
result = fc.getArgument(fc.getTarget().(MallocFunction).getReallocPtrArg())
)
}
}
/**
* A library routine that allocates memory.
*
* DEPRECATED: Use the `MallocFunction` class instead of this predicate.
*/
deprecated predicate allocationFunction(Function f) {
f instanceof MallocFunction
}
/**
* A call to a library routine that allocates memory.
*
* DEPRECATED: Use `AllocationExpr` instead (this also includes `new` expressions).
*/
deprecated predicate allocationCall(FunctionCall fc) {
fc instanceof AllocationExpr
}
/**
@@ -151,40 +298,27 @@ predicate isMemoryManagementExpr(Expr e) { isAllocationExpr(e) or isDeallocation
/**
* Is e an allocation from stdlib.h (`malloc`, `realloc` etc)?
*
* DEPRECATED: Use `AllocationExpr` instead (this also includes `new` expressions).
*/
predicate isStdLibAllocationExpr(Expr e) { allocationCall(e) }
deprecated predicate isStdLibAllocationExpr(Expr e) { allocationCall(e) }
/**
* Is e some kind of allocation (`new`, `alloc`, `realloc` etc)?
*/
predicate isAllocationExpr(Expr e) {
allocationCall(e)
e.(FunctionCall) instanceof AllocationExpr
or
e = any(NewOrNewArrayExpr new | not exists(new.getPlacementPointer()))
}
/**
* Is e some kind of allocation (`new`, `alloc`, `realloc` etc) with a fixed size?
*
* DEPRECATED: Use `AllocationExpr.getSizeBytes()` instead.
*/
predicate isFixedSizeAllocationExpr(Expr allocExpr, int size) {
exists(FunctionCall fc, string name | fc = allocExpr and name = fc.getTarget().getName() |
name = "malloc" and
size = fc.getArgument(0).getValue().toInt()
or
name = "alloca" and
size = fc.getArgument(0).getValue().toInt()
or
name = "calloc" and
size = fc.getArgument(0).getValue().toInt() * fc.getArgument(1).getValue().toInt()
or
name = "realloc" and
size = fc.getArgument(1).getValue().toInt() and
size > 0 // realloc(ptr, 0) only frees the pointer
)
or
size = allocExpr.(NewExpr).getAllocatedType().getSize()
or
size = allocExpr.(NewArrayExpr).getAllocatedType().getSize()
deprecated predicate isFixedSizeAllocationExpr(Expr allocExpr, int size) {
size = allocExpr.(AllocationExpr).getSizeBytes()
}
/**