Merge pull request #12408 from jketema/merge-main

C++: use-use dataflow merge main
This commit is contained in:
Mathias Vorreiter Pedersen
2023-03-07 13:05:30 +00:00
committed by GitHub
925 changed files with 77774 additions and 172565 deletions

View File

@@ -19,7 +19,7 @@ import semmle.code.cpp.security.FunctionWithWrappers
import semmle.code.cpp.security.FlowSources
import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.dataflow.TaintTracking
import DataFlow::PathGraph
import TaintedPath::PathGraph
/**
* A function for opening a file.
@@ -70,18 +70,16 @@ predicate hasUpperBoundsCheck(Variable var) {
)
}
class TaintedPathConfiguration extends TaintTracking::Configuration {
TaintedPathConfiguration() { this = "TaintedPathConfiguration" }
module TaintedPathConfiguration implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node instanceof FlowSource }
override predicate isSource(DataFlow::Node node) { node instanceof FlowSource }
override predicate isSink(DataFlow::Node node) {
predicate isSink(DataFlow::Node node) {
exists(FileFunction fileFunction |
fileFunction.outermostWrapperFunctionCall(node.asIndirectArgument(), _)
)
}
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
node.asExpr().(Call).getTarget().getUnspecifiedType() instanceof ArithmeticType
or
exists(LoadInstruction load, Variable checkedVar |
@@ -92,13 +90,15 @@ class TaintedPathConfiguration extends TaintTracking::Configuration {
}
}
module TaintedPath = TaintTracking::Make<TaintedPathConfiguration>;
from
FileFunction fileFunction, Expr taintedArg, FlowSource taintSource, TaintedPathConfiguration cfg,
DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode, string callChain
FileFunction fileFunction, Expr taintedArg, FlowSource taintSource,
TaintedPath::PathNode sourceNode, TaintedPath::PathNode sinkNode, string callChain
where
taintedArg = sinkNode.getNode().asIndirectArgument() and
fileFunction.outermostWrapperFunctionCall(taintedArg, callChain) and
cfg.hasFlowPath(sourceNode, sinkNode) and
TaintedPath::hasFlowPath(sourceNode, sinkNode) and
taintSource = sourceNode.getNode()
select taintedArg, sourceNode, sinkNode,
"This argument to a file access function is derived from $@ and then passed to " + callChain + ".",

View File

@@ -22,7 +22,7 @@ import semmle.code.cpp.ir.dataflow.TaintTracking
import semmle.code.cpp.ir.dataflow.TaintTracking2
import semmle.code.cpp.security.FlowSources
import semmle.code.cpp.models.implementations.Strcat
import DataFlow::PathGraph
import ExecTaint::PathGraph
/**
* Holds if `incoming` is a string that is used in a format or concatenation function resulting
@@ -55,29 +55,30 @@ predicate interestingConcatenation(DataFlow::Node incoming, DataFlow::Node outgo
)
}
class ConcatState extends DataFlow::FlowState {
ConcatState() { this = "ConcatState" }
newtype TState =
TConcatState() or
TExecState(DataFlow::Node incoming, DataFlow::Node outgoing) {
interestingConcatenation(pragma[only_bind_into](incoming), pragma[only_bind_into](outgoing))
}
class ConcatState extends TConcatState {
string toString() { result = "ConcatState" }
}
class ExecState extends DataFlow::FlowState {
class ExecState extends TExecState {
DataFlow::Node incoming;
DataFlow::Node outgoing;
ExecState() {
this =
"ExecState (" + incoming.getLocation() + " | " + incoming + ", " + outgoing.getLocation() +
" | " + outgoing + ")" and
interestingConcatenation(pragma[only_bind_into](incoming), pragma[only_bind_into](outgoing))
}
ExecState() { this = TExecState(incoming, outgoing) }
DataFlow::Node getIncomingNode() { result = incoming }
DataFlow::Node getOutgoingNode() { result = outgoing }
/** Holds if this is a possible `ExecState` for `sink`. */
predicate isFeasibleForSink(DataFlow::Node sink) {
any(ExecStateConfiguration conf).hasFlow(outgoing, sink)
}
predicate isFeasibleForSink(DataFlow::Node sink) { ExecState::hasFlow(outgoing, sink) }
string toString() { result = "ExecState" }
}
predicate isSinkImpl(DataFlow::Node sink, Expr command, string callChain) {
@@ -85,7 +86,7 @@ predicate isSinkImpl(DataFlow::Node sink, Expr command, string callChain) {
shellCommand(command, callChain)
}
predicate isSanitizerImpl(DataFlow::Node node) {
predicate isBarrierImpl(DataFlow::Node node) {
node.asExpr().getUnspecifiedType() instanceof IntegralType
or
node.asExpr().getUnspecifiedType() instanceof FloatingPointType
@@ -96,56 +97,57 @@ predicate isSanitizerImpl(DataFlow::Node node) {
* given sink. This avoids a cartesian product between all sinks and all `ExecState`s in
* `ExecTaintConfiguration::isSink`.
*/
class ExecStateConfiguration extends TaintTracking2::Configuration {
ExecStateConfiguration() { this = "ExecStateConfiguration" }
module ExecStateConfiguration implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { any(ExecState state).getOutgoingNode() = source }
override predicate isSource(DataFlow::Node source) {
any(ExecState state).getOutgoingNode() = source
}
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _, _) }
override predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _, _) }
predicate isBarrier(DataFlow::Node node) { isBarrierImpl(node) }
override predicate isSanitizer(DataFlow::Node node) { isSanitizerImpl(node) }
override predicate isSanitizerOut(DataFlow::Node node) {
isSink(node, _) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
predicate isBarrierOut(DataFlow::Node node) {
isSink(node) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
}
}
class ExecTaintConfiguration extends TaintTracking::Configuration {
ExecTaintConfiguration() { this = "ExecTaintConfiguration" }
module ExecState = TaintTracking::Make<ExecStateConfiguration>;
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
module ExecTaintConfiguration implements DataFlow::StateConfigSig {
class FlowState = TState;
predicate isSource(DataFlow::Node source, FlowState state) {
source instanceof FlowSource and
state instanceof ConcatState
}
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
any(ExecStateConfiguration conf).isSink(sink) and
predicate isSink(DataFlow::Node sink, FlowState state) {
ExecStateConfiguration::isSink(sink) and
state.(ExecState).isFeasibleForSink(sink)
}
override predicate isAdditionalTaintStep(
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
DataFlow::FlowState state2
predicate isAdditionalFlowStep(
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
) {
state1 instanceof ConcatState and
state2.(ExecState).getIncomingNode() = node1 and
state2.(ExecState).getOutgoingNode() = node2
}
override predicate isSanitizer(DataFlow::Node node) { isSanitizerImpl(node) }
predicate isBarrier(DataFlow::Node node) { isBarrierImpl(node) }
override predicate isSanitizerOut(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node, FlowState state) { none() }
predicate isBarrierOut(DataFlow::Node node) {
isSink(node, _) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
}
}
module ExecTaint = TaintTracking::MakeWithState<ExecTaintConfiguration>;
from
ExecTaintConfiguration conf, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode,
string taintCause, string callChain, DataFlow::Node concatResult, Expr command
ExecTaint::PathNode sourceNode, ExecTaint::PathNode sinkNode, string taintCause, string callChain,
DataFlow::Node concatResult, Expr command
where
conf.hasFlowPath(sourceNode, sinkNode) and
ExecTaint::hasFlowPath(sourceNode, sinkNode) and
taintCause = sourceNode.getNode().(FlowSource).getSourceType() and
isSinkImpl(sinkNode.getNode(), command, callChain) and
concatResult = sinkNode.getState().(ExecState).getOutgoingNode()

View File

@@ -19,7 +19,7 @@ import semmle.code.cpp.ir.dataflow.TaintTracking
import semmle.code.cpp.ir.IR
import semmle.code.cpp.controlflow.IRGuards
import semmle.code.cpp.security.FlowSources
import DataFlow::PathGraph
import TaintedAllocationSize::PathGraph
/**
* Holds if `alloc` is an allocation, and `tainted` is a child of it that is a
@@ -54,14 +54,12 @@ predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Va
predicate isFlowSource(FlowSource source, string sourceType) { sourceType = source.getSourceType() }
class TaintedAllocationSizeConfiguration extends TaintTracking::Configuration {
TaintedAllocationSizeConfiguration() { this = "TaintedAllocationSizeConfiguration" }
module TaintedAllocationSizeConfiguration implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isFlowSource(source, _) }
override predicate isSource(DataFlow::Node source) { isFlowSource(source, _) }
predicate isSink(DataFlow::Node sink) { allocSink(_, sink) }
override predicate isSink(DataFlow::Node sink) { allocSink(_, sink) }
override predicate isSanitizer(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
exists(Expr e | e = node.asExpr() |
// There can be two separate reasons for `convertedExprMightOverflow` not holding:
// 1. `e` really cannot overflow.
@@ -97,12 +95,14 @@ class TaintedAllocationSizeConfiguration extends TaintTracking::Configuration {
}
}
module TaintedAllocationSize = TaintTracking::Make<TaintedAllocationSizeConfiguration>;
from
Expr alloc, DataFlow::PathNode source, DataFlow::PathNode sink, string taintCause,
TaintedAllocationSizeConfiguration conf
Expr alloc, TaintedAllocationSize::PathNode source, TaintedAllocationSize::PathNode sink,
string taintCause
where
isFlowSource(source.getNode(), taintCause) and
conf.hasFlowPath(source, sink) and
TaintedAllocationSize::hasFlowPath(source, sink) and
allocSink(alloc, sink.getNode())
select alloc, source, sink, "This allocation size is derived from $@ and might overflow.",
source.getNode(), "user input (" + taintCause + ")"