mirror of
https://github.com/github/codeql.git
synced 2025-12-21 19:26:31 +01:00
C++: Make the 'getBufferSize' a lot more like the pre-use-use flow implementation.
This commit is contained in:
@@ -73,67 +73,29 @@ 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
|
|
||||||
* 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) {
|
|
||||||
getBufferSizeCand0(e1) and
|
|
||||||
(
|
|
||||||
exists(Variable bufferVar, Class parentClass, VariableAccess parentPtr, int bufferSize |
|
|
||||||
e1 = parentPtr
|
|
||||||
|
|
|
||||||
bufferVar = e2.(VariableAccess).getTarget() and
|
|
||||||
// buffer is the parentPtr->bufferVar of a 'variable size struct'
|
|
||||||
memberMayBeVarSize(parentClass, bufferVar) and
|
|
||||||
parentPtr = e2.(VariableAccess).getQualifier() and
|
|
||||||
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
|
|
||||||
(
|
|
||||||
if exists(bufferVar.getType().getSize())
|
|
||||||
then bufferSize = bufferVar.getType().getSize()
|
|
||||||
else bufferSize = 0
|
|
||||||
) and
|
|
||||||
delta = bufferSize - parentClass.getSize()
|
|
||||||
)
|
|
||||||
or
|
|
||||||
DataFlow::localExprFlowStep(e1, e2) and
|
|
||||||
delta = 0
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
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).
|
* Get the size in bytes of the buffer pointed to by an expression (if this can be determined).
|
||||||
*/
|
*/
|
||||||
|
language[monotonicAggregates]
|
||||||
int getBufferSize(Expr bufferExpr, Element why) {
|
int getBufferSize(Expr bufferExpr, Element why) {
|
||||||
result = max( | | getBufferSizeCand(bufferExpr, _)) and
|
result = isSource(bufferExpr, why)
|
||||||
result = getBufferSizeCand(bufferExpr, why)
|
or
|
||||||
|
exists(Class parentClass, VariableAccess parentPtr, int bufferSize, Variable bufferVar |
|
||||||
|
bufferVar = bufferExpr.(VariableAccess).getTarget() and
|
||||||
|
// buffer is the parentPtr->bufferVar of a 'variable size struct'
|
||||||
|
memberMayBeVarSize(parentClass, bufferVar) and
|
||||||
|
why = bufferVar and
|
||||||
|
parentPtr = bufferExpr.(VariableAccess).getQualifier() and
|
||||||
|
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
|
||||||
|
result = getBufferSize(parentPtr, _) + bufferSize - parentClass.getSize()
|
||||||
|
|
|
||||||
|
if exists(bufferVar.getType().getSize())
|
||||||
|
then bufferSize = bufferVar.getType().getSize()
|
||||||
|
else bufferSize = 0
|
||||||
|
)
|
||||||
|
or
|
||||||
|
// dataflow (all sources must be the same size)
|
||||||
|
result = unique(Expr def | DataFlow::localExprFlowStep(def, bufferExpr) | getBufferSize(def, _)) and
|
||||||
|
// find reason
|
||||||
|
exists(Expr def | DataFlow::localExprFlowStep(def, bufferExpr) | exists(getBufferSize(def, why)))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user