Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions csharp/ql/test/utils/modelgenerator/dataflow/Summaries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,12 @@ public void Apply(Action<object> a, object o)
{
a(o);
}

private void CallApply()
{
// Test that this call to `Apply` does not interfere with the flow summaries generated for `Apply`
Apply(x => x, null);
}
}

public static class HigherOrderExtensionMethods
Expand Down
8 changes: 4 additions & 4 deletions shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {

Cc ccNone();

CcCall ccSomeCall();
CcCall ccSomeCall(boolean isSource);

/*
* The following `instanceof` predicates are necessary for proper
Expand Down Expand Up @@ -566,7 +566,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
Nd node, Cc cc, SummaryCtx summaryCtx, Typ t, Ap ap, ApApprox apa, TypOption stored
) {
sourceNode(node) and
(if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and
(if hasSourceCallCtx() then cc = ccSomeCall(true) else cc = ccNone()) and
summaryCtx.isSourceCtx() and
t = getNodeTyp(node) and
ap instanceof ApNil and
Expand Down Expand Up @@ -2080,7 +2080,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {

override predicate isSource() {
sourceNode(node) and
(if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and
(if hasSourceCallCtx() then cc = ccSomeCall(true) else cc = ccNone()) and
summaryCtx.isSourceCtx() and
t = getNodeTyp(node) and
ap instanceof ApNil
Expand Down Expand Up @@ -2716,7 +2716,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {

Cc ccNone() { result = false }

CcCall ccSomeCall() { result = true }
CcCall ccSomeCall(boolean isSource) { result = true and isSource = [false, true] }

predicate instanceofCc(Cc cc) { any() }

Expand Down
35 changes: 26 additions & 9 deletions shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,10 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
tgts = strictcount(Callable tgt | relevantCallEdgeIn(call, tgt)) and
ctxtgts < tgts
)
or
// If only a single lambda can reach `call`, we still want to check for the call
// context, since lambdas outside the codebase may reach as well
exists(viableCallableLambda(call, TCallSome(ctx)))
}

/**
Expand Down Expand Up @@ -619,7 +623,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
TSpecificCall(CallSet calls, DispatchSet tgts, UnreachableSetOption unreachable) {
hasCtx(_, calls, tgts, unreachable)
} or
TSomeCall() or
TSomeCall(Boolean isSource) or
TReturn(Callable c, Call call) { reducedViableImplInReturn(c, call) }

/**
Expand All @@ -632,9 +636,10 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
* dispatch targets for all of `calls` to the set of dispatch targets in
* `tgts`, and/or the specific call prunes unreachable nodes in the
* current callable as given by `unreachable`.
* - `TSomeCall()` : Flow entered through a parameter. The
* - `TSomeCall(boolean isSource)` : Flow entered through a parameter. The
* originating call does not improve the set of dispatch targets for any
* method call in the current callable and was therefore not recorded.
* method call in the current callable and was therefore not recorded. `isSource`
* indicates whether the call context is for a flow source when using `FlowFeature`s.
* - `TReturn(Callable c, Call call)` : Flow reached `call` from `c` and
* this dispatch target of `call` implies a reduced set of dispatch origins
* to which data may flow if it should reach a `return` statement.
Expand All @@ -656,7 +661,13 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
}

private class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
private boolean isSource;

CallContextSomeCall() { this = TSomeCall(isSource) }

override string toString() {
if isSource = true then result = "CcSomeCallSource" else result = "CcSomeCall"
}
}

private class CallContextReturn extends CallContextNoCall, TReturn {
Expand Down Expand Up @@ -707,7 +718,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
pragma[inline]
predicate matchesCall(CcCall cc, Call call) {
cc = Input2::getSpecificCallContextCall(call, _) or
cc = ccSomeCall()
cc = ccSomeCall(false)
}

class CcNoCall = CallContextNoCall;
Expand All @@ -716,7 +727,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {

Cc ccNone() { result instanceof CallContextAny }

CcCall ccSomeCall() { result instanceof CallContextSomeCall }
CcCall ccSomeCall(boolean isSource) { result = TSomeCall(isSource) }

predicate instanceofCc(Cc cc) { any() }

Expand All @@ -739,7 +750,13 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
/** Holds if `call` does not have a reduced set of dispatch targets in call context `ctx`. */
bindingset[call, ctx]
predicate viableImplNotCallContextReduced(Call call, CallContext ctx) {
not Input2::callContextAffectsDispatch(call, ctx)
not Input2::callContextAffectsDispatch(call, ctx) and
// When sources have call contexts (using `FlowFeature`s), we check that `call` can
// dispatch in all possible call contexts
not (
ctx = TSomeCall(true) and
Input2::callContextAffectsDispatch(call, _)
)
}

/**
Expand Down Expand Up @@ -822,7 +839,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
CallContextCall getCallContextCall(Call call, Callable c) {
if recordCallSiteDispatch(call, c)
then result = Input2::getSpecificCallContextCall(call, c)
else result = TSomeCall()
else result = TSomeCall(false)
}
}

Expand Down Expand Up @@ -850,7 +867,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
CallContextCall getCallContextCall(Call call, Callable c) {
if recordCallSite(call, c)
then result = Input2::getSpecificCallContextCall(call, c)
else result = TSomeCall()
else result = TSomeCall(false)
}
}
}
Expand Down
Loading