mirror of
https://github.com/github/codeql.git
synced 2026-04-26 17:25:19 +02:00
C++: Add an interface for blocking flow out of functions that reach a certain argument.
This commit is contained in:
@@ -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
|
||||
)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user