AllocationExpr.getSizeMult() now analyzes the size expression of function calls.

This yields more precise size information in a lot of the common cases of C allocation code,
as the common pattern malloc(count * sizeof(type)) is now understood.
This commit is contained in:
Cornelius Riemenschneider
2020-04-23 02:05:31 +02:00
parent 247fc42ec5
commit 293e6466d4
2 changed files with 37 additions and 5 deletions

View File

@@ -255,6 +255,24 @@ class OperatorNewAllocationFunction extends AllocationFunction {
}
}
pragma[inline]
private predicate deconstructSizeExpr(Expr sizeExpr, Expr lengthExpr, int sizeof) {
sizeExpr instanceof MulExpr and
exists(SizeofOperator sizeofOp |
sizeofOp = sizeExpr.(MulExpr).getAnOperand() and
lengthExpr = sizeExpr.(MulExpr).getAnOperand() and
sizeofOp != lengthExpr and
sizeof = sizeofOp.getValue().toInt()
)
or
not exists(int s, SizeofOperator sizeofOp |
sizeofOp = sizeExpr.(MulExpr).getAnOperand() and
s = sizeofOp.(SizeofOperator).getValue().toInt()
) and
lengthExpr = sizeExpr and
sizeof = 1
}
/**
* An allocation expression that is a function call, such as call to `malloc`.
*/
@@ -272,7 +290,21 @@ class CallAllocationExpr extends AllocationExpr, FunctionCall {
not exists(NewOrNewArrayExpr new | new.getAllocatorCall() = this)
}
override Expr getSizeExpr() { result = getArgument(target.getSizeArg()) }
override Expr getSizeExpr() {
exists(Expr sizeExpr | sizeExpr = getArgument(target.getSizeArg()) |
if exists(target.getSizeMult())
then result = sizeExpr
else (
exists(Expr lengthExpr |
deconstructSizeExpr(sizeExpr, lengthExpr, _) and
result = lengthExpr
)
or
not exists(Expr lengthExpr | deconstructSizeExpr(sizeExpr, lengthExpr, _)) and
result = sizeExpr
)
)
}
override int getSizeMult() {
// malloc with multiplier argument that is a constant
@@ -280,7 +312,7 @@ class CallAllocationExpr extends AllocationExpr, FunctionCall {
or
// malloc with no multiplier argument
not exists(target.getSizeMult()) and
result = 1
deconstructSizeExpr(getArgument(target.getSizeArg()), _, result)
}
override int getSizeBytes() { result = getSizeExpr().getValue().toInt() * getSizeMult() }

View File

@@ -86,11 +86,11 @@ allocationExprs
| allocators.cpp:144:13:144:31 | new[] | getSizeExpr = x, getSizeMult = 900, requiresDealloc |
| allocators.cpp:149:8:149:19 | call to operator new | getSizeBytes = 4, getSizeExpr = sizeof(int), getSizeMult = 1, requiresDealloc |
| allocators.cpp:156:3:156:8 | call to malloc | getSizeBytes = 5, getSizeExpr = 5, getSizeMult = 1, requiresDealloc |
| allocators.cpp:157:3:157:8 | call to malloc | getSizeBytes = 20, getSizeExpr = ... * ..., getSizeMult = 1, requiresDealloc |
| allocators.cpp:157:3:157:8 | call to malloc | getSizeBytes = 20, getSizeExpr = 5, getSizeMult = 4, requiresDealloc |
| allocators.cpp:158:3:158:8 | call to malloc | getSizeExpr = count, getSizeMult = 1, requiresDealloc |
| allocators.cpp:159:3:159:8 | call to malloc | getSizeExpr = ... * ..., getSizeMult = 1, requiresDealloc |
| allocators.cpp:159:3:159:8 | call to malloc | getSizeExpr = count, getSizeMult = 4, requiresDealloc |
| allocators.cpp:160:3:160:8 | call to malloc | getSizeExpr = ... + ..., getSizeMult = 1, requiresDealloc |
| allocators.cpp:161:3:161:8 | call to malloc | getSizeExpr = ... * ..., getSizeMult = 1, requiresDealloc |
| allocators.cpp:161:3:161:8 | call to malloc | getSizeExpr = count, getSizeMult = 8, requiresDealloc |
deallocationFunctions
| allocators.cpp:11:6:11:20 | operator delete | getFreedArg = 0 |
| allocators.cpp:12:6:12:22 | operator delete[] | getFreedArg = 0 |