C++: Add an interface for blocking flow out of functions that reach a certain argument.

This commit is contained in:
Mathias Vorreiter Pedersen
2024-02-06 16:05:32 +00:00
parent 525f27173d
commit e539aca337
2 changed files with 50 additions and 1 deletions

View File

@@ -2,8 +2,11 @@ private import codeql.ssa.Ssa as SsaImplCommon
private import semmle.code.cpp.ir.IR
private import DataFlowUtil
private import DataFlowImplCommon as DataFlowImplCommon
private import semmle.code.cpp.ir.dataflow.internal.ModelUtil
private import semmle.code.cpp.models.interfaces.Allocation as Alloc
private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow
private import semmle.code.cpp.models.interfaces.FlowOutBarrier as FOB
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as FIO
private import semmle.code.cpp.ir.internal.IRCppLanguage
private import DataFlowPrivate
private import ssa0.SsaInternals as SsaInternals0
@@ -784,10 +787,30 @@ private Node getAPriorDefinition(SsaDefOrUse defOrUse) {
)
}
/**
* Holds if there should not be use-use flow out of `n` (or a conversion that
* flows to `n`).
*/
private predicate modeledFlowBarrier(Node n) {
exists(FIO::FunctionInput input, CallInstruction call |
call.getStaticCallTarget().(FOB::FlowOutBarrierFunction).isFlowOutBarrier(input) and
n = callInput(call, input)
)
or
exists(Operand operand, Instruction instr, Node n0, int indirectionIndex |
modeledFlowBarrier(n0) and
nodeHasInstruction(n0, instr, indirectionIndex) and
conversionFlow(operand, instr, false, _) and
nodeHasOperand(n, operand, indirectionIndex)
)
}
/** Holds if there is def-use or use-use flow from `nodeFrom` to `nodeTo`. */
predicate ssaFlow(Node nodeFrom, Node nodeTo) {
exists(Node nFrom, boolean uncertain, SsaDefOrUse defOrUse |
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and nodeFrom != nodeTo
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and
not modeledFlowBarrier(nFrom) and
nodeFrom != nodeTo
|
if uncertain = true then nodeFrom = [nFrom, getAPriorDefinition(defOrUse)] else nodeFrom = nFrom
)

View File

@@ -0,0 +1,26 @@
/**
* Provides an abstract class for blocking flow out of functions. To use this
* QL library, create a QL class extending `FlowOutBarrierFunction` with a
* characteristic predicate that selects the function or set of functions you
* are modeling. Within that class, override the predicates provided by
* `FlowOutBarrierFunction` to match the flow within that function.
*/
import semmle.code.cpp.Function
import FunctionInputsAndOutputs
/**
* A library function for which flow should not continue after reaching one
* of its inputs.
*
* For example, since `std::swap(a, b)` swaps the values pointed to by `a`
* and `b` there should not be use-use flow out of `a` or `b`.
*/
abstract class FlowOutBarrierFunction extends Function {
/**
* Holds if use-use flow should not continue onwards after reaching
* the argument, qualifier, or buffer represented by `input`.
*/
pragma[nomagic]
abstract predicate isFlowOutBarrier(FunctionInput input);
}