C++: Make the 'getBufferSize' a lot more like the pre-use-use flow implementation.

This commit is contained in:
Mathias Vorreiter Pedersen
2022-12-16 12:58:45 +00:00
parent 31b4dda7bd
commit c06f7259cf

View File

@@ -74,66 +74,28 @@ private int isSource(Expr bufferExpr, Element why) {
} }
/** /**
* Holds if `e2` is an expression that is derived from `e1` such that if `e1[n]` is a * Get the size in bytes of the buffer pointed to by an expression (if this can be determined).
* well-defined expression for some number `n`, then `e2[n + delta]` is also a well-defined
* expression.
*/ */
private predicate step(Expr e1, Expr e2, int delta) { language[monotonicAggregates]
getBufferSizeCand0(e1) and int getBufferSize(Expr bufferExpr, Element why) {
( result = isSource(bufferExpr, why)
exists(Variable bufferVar, Class parentClass, VariableAccess parentPtr, int bufferSize | or
e1 = parentPtr exists(Class parentClass, VariableAccess parentPtr, int bufferSize, Variable bufferVar |
| bufferVar = bufferExpr.(VariableAccess).getTarget() and
bufferVar = e2.(VariableAccess).getTarget() and
// buffer is the parentPtr->bufferVar of a 'variable size struct' // buffer is the parentPtr->bufferVar of a 'variable size struct'
memberMayBeVarSize(parentClass, bufferVar) and memberMayBeVarSize(parentClass, bufferVar) and
parentPtr = e2.(VariableAccess).getQualifier() and why = bufferVar and
parentPtr = bufferExpr.(VariableAccess).getQualifier() and
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
( result = getBufferSize(parentPtr, _) + bufferSize - parentClass.getSize()
|
if exists(bufferVar.getType().getSize()) if exists(bufferVar.getType().getSize())
then bufferSize = bufferVar.getType().getSize() then bufferSize = bufferVar.getType().getSize()
else bufferSize = 0 else bufferSize = 0
) and
delta = bufferSize - parentClass.getSize()
) )
or or
DataFlow::localExprFlowStep(e1, e2) and // dataflow (all sources must be the same size)
delta = 0 result = unique(Expr def | DataFlow::localExprFlowStep(def, bufferExpr) | getBufferSize(def, _)) and
) // find reason
} exists(Expr def | DataFlow::localExprFlowStep(def, bufferExpr) | exists(getBufferSize(def, why)))
pragma[nomagic]
private predicate getBufferSizeCand0(Expr e) {
exists(isSource(e, _))
or
exists(Expr e0 |
getBufferSizeCand0(e0) and
step(e0, e, _)
)
}
/**
* Get the size in bytes of the buffer pointed to by an expression (if this can be determined).
*
* NOTE: There can be multiple `(result, why)` for a given `bufferExpr`.
*/
private int getBufferSizeCand(Expr bufferExpr, Element why) {
getBufferSizeCand0(bufferExpr) and
(
result = isSource(bufferExpr, why)
or
exists(Expr e0, int delta, int size |
size = getBufferSizeCand(e0, why) and
step(e0, bufferExpr, delta) and
result = size + delta
)
)
}
/**
* Get the size in bytes of the buffer pointed to by an expression (if this can be determined).
*/
int getBufferSize(Expr bufferExpr, Element why) {
result = max( | | getBufferSizeCand(bufferExpr, _)) and
result = getBufferSizeCand(bufferExpr, why)
} }