C++: Use a 'TaintTracking::Configuration' for 'cpp/overflow-destination'.

This commit is contained in:
Mathias Vorreiter Pedersen
2022-03-09 12:07:25 +00:00
parent 275902d558
commit d7652f9742

View File

@@ -14,7 +14,10 @@
*/
import cpp
import semmle.code.cpp.security.TaintTracking
import semmle.code.cpp.ir.dataflow.TaintTracking
import semmle.code.cpp.controlflow.IRGuards
import semmle.code.cpp.security.FlowSources
import DataFlow::PathGraph
/**
* Holds if `fc` is a call to a copy operation where the size argument contains
@@ -45,9 +48,49 @@ predicate sourceSized(FunctionCall fc, Expr src) {
)
}
from FunctionCall fc, Expr vuln, Expr taintSource
predicate readsVariable(LoadInstruction load, Variable var) {
load.getSourceAddress().(VariableAddressInstruction).getASTVariable() = var
}
predicate hasUpperBoundsCheck(Variable var) {
exists(RelationalOperation oper, VariableAccess access |
oper.getAnOperand() = access and
access.getTarget() = var and
// Comparing to 0 is not an upper bound check
not oper.getAnOperand().getValue() = "0"
)
}
predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Variable checkedVar) {
readsVariable(node.asInstruction(), checkedVar) and
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
}
class OverflowDestinationConfig extends TaintTracking::Configuration {
OverflowDestinationConfig() { this = "OverflowDestinationConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
override predicate isSink(DataFlow::Node sink) { sourceSized(_, sink.asExpr()) }
override predicate isSanitizer(DataFlow::Node node) {
exists(Variable checkedVar |
readsVariable(node.asInstruction(), checkedVar) and
hasUpperBoundsCheck(checkedVar)
)
or
exists(Variable checkedVar, Operand access |
readsVariable(access.getDef(), checkedVar) and
nodeIsBarrierEqualityCandidate(node, access, checkedVar)
)
}
}
from
FunctionCall fc, OverflowDestinationConfig conf, DataFlow::PathNode source,
DataFlow::PathNode sink
where
sourceSized(fc, vuln) and
tainted(taintSource, vuln)
conf.hasFlowPath(source, sink) and
sourceSized(fc, sink.getNode().asExpr())
select fc,
"To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size."