mirror of
https://github.com/github/codeql.git
synced 2026-04-26 17:25:19 +02:00
Merge pull request #13983 from hvitved/dataflow/reduced-dispatch-early-join
Data flow: Earlier call-context based dispatch filtering
This commit is contained in:
@@ -190,6 +190,8 @@ module MakeImpl<InputSig Lang> {
|
||||
|
||||
private class ArgNodeEx extends NodeEx {
|
||||
ArgNodeEx() { this.asNode() instanceof ArgNode }
|
||||
|
||||
DataFlowCall getCall() { this.asNode().(ArgNode).argumentOf(result, _) }
|
||||
}
|
||||
|
||||
private class ParamNodeEx extends NodeEx {
|
||||
@@ -1145,11 +1147,20 @@ module MakeImpl<InputSig Lang> {
|
||||
|
||||
class LocalCc;
|
||||
|
||||
bindingset[call, c, outercc]
|
||||
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc);
|
||||
DataFlowCallable viableImplCallContextReduced(DataFlowCall call, CcCall ctx);
|
||||
|
||||
bindingset[call, c, innercc]
|
||||
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc);
|
||||
bindingset[call, ctx]
|
||||
predicate viableImplNotCallContextReduced(DataFlowCall call, Cc ctx);
|
||||
|
||||
bindingset[call, c]
|
||||
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c);
|
||||
|
||||
DataFlowCallable viableImplCallContextReducedReverse(DataFlowCall call, CcNoCall ctx);
|
||||
|
||||
predicate viableImplNotCallContextReducedReverse(CcNoCall ctx);
|
||||
|
||||
bindingset[call, c]
|
||||
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call);
|
||||
|
||||
bindingset[node, cc]
|
||||
LocalCc getLocalCc(NodeEx node, Cc cc);
|
||||
@@ -1191,21 +1202,24 @@ module MakeImpl<InputSig Lang> {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowIntoCallApa(
|
||||
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa
|
||||
DataFlowCall call, DataFlowCallable c, ArgNodeEx arg, ParamNodeEx p,
|
||||
boolean allowsFieldFlow, ApApprox apa
|
||||
) {
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow) and
|
||||
PrevStage::revFlowAp(p, pragma[only_bind_into](apa)) and
|
||||
PrevStage::revFlowAp(arg, pragma[only_bind_into](apa))
|
||||
PrevStage::revFlowAp(arg, pragma[only_bind_into](apa)) and
|
||||
c = p.getEnclosingCallable()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowOutOfCallApa(
|
||||
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow,
|
||||
ApApprox apa
|
||||
DataFlowCall call, DataFlowCallable c, RetNodeEx ret, ReturnKindExt kind, NodeEx out,
|
||||
boolean allowsFieldFlow, ApApprox apa
|
||||
) {
|
||||
flowOutOfCall(call, ret, kind, out, allowsFieldFlow) and
|
||||
PrevStage::revFlowAp(out, pragma[only_bind_into](apa)) and
|
||||
PrevStage::revFlowAp(ret, pragma[only_bind_into](apa))
|
||||
PrevStage::revFlowAp(ret, pragma[only_bind_into](apa)) and
|
||||
c = ret.getEnclosingCallable()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -1214,7 +1228,7 @@ module MakeImpl<InputSig Lang> {
|
||||
ApApprox argApa, ApApprox apa
|
||||
) {
|
||||
exists(ReturnKindExt kind |
|
||||
flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa) and
|
||||
flowOutOfCallApa(call, _, ret, kind, out, allowsFieldFlow, apa) and
|
||||
PrevStage::callMayFlowThroughRev(call) and
|
||||
PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) and
|
||||
matchesCall(ccc, call)
|
||||
@@ -1332,16 +1346,7 @@ module MakeImpl<InputSig Lang> {
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(
|
||||
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
|
||||
DataFlowCallable inner
|
||||
|
|
||||
fwdFlow(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa) and
|
||||
flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
cc = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
fwdFlowOut(node, state, cc, summaryCtx, argT, argAp, t, ap, apa)
|
||||
or
|
||||
// flow through a callable
|
||||
exists(
|
||||
@@ -1408,15 +1413,115 @@ module MakeImpl<InputSig Lang> {
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[call, ctx]
|
||||
pragma[inline_late]
|
||||
private DataFlowCallable viableImplCallContextReducedInlineLate(
|
||||
DataFlowCall call, CcCall ctx
|
||||
) {
|
||||
result = viableImplCallContextReduced(call, ctx)
|
||||
}
|
||||
|
||||
bindingset[arg, ctx]
|
||||
pragma[inline_late]
|
||||
private DataFlowCallable viableImplCallContextReducedInlineLate(
|
||||
DataFlowCall call, ArgNodeEx arg, CcCall ctx
|
||||
) {
|
||||
call = arg.getCall() and
|
||||
result = viableImplCallContextReducedInlineLate(call, ctx)
|
||||
}
|
||||
|
||||
bindingset[call]
|
||||
pragma[inline_late]
|
||||
private predicate flowIntoCallApaInlineLate(
|
||||
DataFlowCall call, DataFlowCallable c, ArgNodeEx arg, ParamNodeEx p,
|
||||
boolean allowsFieldFlow, ApApprox apa
|
||||
) {
|
||||
flowIntoCallApa(call, c, arg, p, allowsFieldFlow, apa)
|
||||
}
|
||||
|
||||
bindingset[call, ctx]
|
||||
pragma[inline_late]
|
||||
private predicate viableImplNotCallContextReducedInlineLate(DataFlowCall call, Cc ctx) {
|
||||
viableImplNotCallContextReduced(call, ctx)
|
||||
}
|
||||
|
||||
bindingset[arg, outercc]
|
||||
pragma[inline_late]
|
||||
private predicate viableImplArgNotCallContextReduced(
|
||||
DataFlowCall call, ArgNodeEx arg, Cc outercc
|
||||
) {
|
||||
call = arg.getCall() and
|
||||
viableImplNotCallContextReducedInlineLate(call, outercc)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowIn(
|
||||
DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc,
|
||||
ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa
|
||||
) {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(arg, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and
|
||||
flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
(
|
||||
inner = viableImplCallContextReducedInlineLate(call, arg, outercc)
|
||||
or
|
||||
viableImplArgNotCallContextReduced(call, arg, outercc)
|
||||
) and
|
||||
flowIntoCallApaInlineLate(call, inner, arg, p, allowsFieldFlow, apa)
|
||||
|
|
||||
innercc = getCallContextCall(call, inner) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[ctx, result]
|
||||
pragma[inline_late]
|
||||
private DataFlowCallable viableImplCallContextReducedReverseInlineLate(
|
||||
DataFlowCall call, CcNoCall ctx
|
||||
) {
|
||||
result = viableImplCallContextReducedReverse(call, ctx)
|
||||
}
|
||||
|
||||
bindingset[call]
|
||||
pragma[inline_late]
|
||||
private predicate flowOutOfCallApaInlineLate(
|
||||
DataFlowCall call, DataFlowCallable c, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
ApApprox apa
|
||||
) {
|
||||
flowOutOfCallApa(call, c, ret, _, out, allowsFieldFlow, apa)
|
||||
}
|
||||
|
||||
bindingset[c, ret, apa, innercc]
|
||||
pragma[inline_late]
|
||||
pragma[noopt]
|
||||
private predicate flowOutOfCallApaNotCallContextReduced(
|
||||
DataFlowCall call, DataFlowCallable c, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
ApApprox apa, CcNoCall innercc
|
||||
) {
|
||||
viableImplNotCallContextReducedReverse(innercc) and
|
||||
flowOutOfCallApa(call, c, ret, _, out, allowsFieldFlow, apa)
|
||||
}
|
||||
|
||||
// inline to reduce number of iterations
|
||||
pragma[inline]
|
||||
private predicate fwdFlowOut(
|
||||
NodeEx out, FlowState state, CcNoCall outercc, ParamNodeOption summaryCtx, TypOption argT,
|
||||
ApOption argAp, Typ t, Ap ap, ApApprox apa
|
||||
) {
|
||||
exists(
|
||||
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
|
||||
DataFlowCallable inner
|
||||
|
|
||||
fwdFlow(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
(
|
||||
inner = viableImplCallContextReducedReverseInlineLate(call, innercc) and
|
||||
flowOutOfCallApaInlineLate(call, inner, ret, out, allowsFieldFlow, apa)
|
||||
or
|
||||
flowOutOfCallApaNotCallContextReduced(call, inner, ret, out, allowsFieldFlow, apa,
|
||||
innercc)
|
||||
)
|
||||
|
|
||||
outercc = getCallContextReturn(inner, call) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
@@ -1518,7 +1623,7 @@ module MakeImpl<InputSig Lang> {
|
||||
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap
|
||||
) {
|
||||
exists(ApApprox argApa, Typ argT |
|
||||
flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p),
|
||||
flowIntoCallApa(call, _, pragma[only_bind_into](arg), pragma[only_bind_into](p),
|
||||
allowsFieldFlow, argApa) and
|
||||
fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), pragma[only_bind_into](argAp),
|
||||
argApa) and
|
||||
@@ -1529,24 +1634,23 @@ module MakeImpl<InputSig Lang> {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowIntoCallAp(
|
||||
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap
|
||||
) {
|
||||
exists(ApApprox apa |
|
||||
flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and
|
||||
fwdFlow(arg, _, _, _, _, _, _, ap, apa)
|
||||
private predicate flowIntoCallAp(DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Ap ap) {
|
||||
exists(ApApprox apa, boolean allowsFieldFlow |
|
||||
flowIntoCallApa(call, _, arg, p, allowsFieldFlow, apa) and
|
||||
fwdFlow(arg, _, _, _, _, _, _, ap, apa) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowOutOfCallAp(
|
||||
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow,
|
||||
Ap ap
|
||||
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, Ap ap
|
||||
) {
|
||||
exists(ApApprox apa |
|
||||
flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and
|
||||
exists(ApApprox apa, boolean allowsFieldFlow |
|
||||
flowOutOfCallApa(call, _, ret, _, out, allowsFieldFlow, apa) and
|
||||
fwdFlow(ret, _, _, _, _, _, _, ap, apa) and
|
||||
pos = ret.getReturnPosition()
|
||||
pos = ret.getReturnPosition() and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1627,10 +1731,9 @@ module MakeImpl<InputSig Lang> {
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
exists(ParamNodeEx p |
|
||||
revFlow(p, state, TReturnCtxNone(), returnAp, ap) and
|
||||
flowIntoCallAp(_, node, p, allowsFieldFlow, ap) and
|
||||
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
|
||||
flowIntoCallAp(_, node, p, ap) and
|
||||
returnCtx = TReturnCtxNone()
|
||||
)
|
||||
or
|
||||
@@ -1680,10 +1783,9 @@ module MakeImpl<InputSig Lang> {
|
||||
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state,
|
||||
ReturnCtx returnCtx, ApOption returnAp, Ap ap
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
exists(NodeEx out |
|
||||
revFlow(out, state, returnCtx, returnAp, ap) and
|
||||
flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
flowOutOfCallAp(call, ret, pos, out, ap)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1872,11 +1974,22 @@ module MakeImpl<InputSig Lang> {
|
||||
bindingset[node, cc]
|
||||
LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
|
||||
bindingset[call, c, outercc]
|
||||
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
|
||||
DataFlowCallable viableImplCallContextReduced(DataFlowCall call, CcCall ctx) { none() }
|
||||
|
||||
bindingset[call, c, innercc]
|
||||
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
bindingset[call, ctx]
|
||||
predicate viableImplNotCallContextReduced(DataFlowCall call, Cc ctx) { any() }
|
||||
|
||||
bindingset[call, c]
|
||||
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c) { any() }
|
||||
|
||||
DataFlowCallable viableImplCallContextReducedReverse(DataFlowCall call, CcNoCall ctx) {
|
||||
none()
|
||||
}
|
||||
|
||||
predicate viableImplNotCallContextReducedReverse(CcNoCall ctx) { any() }
|
||||
|
||||
bindingset[call, c]
|
||||
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
|
||||
}
|
||||
|
||||
private module Level1CallContext {
|
||||
@@ -1899,9 +2012,17 @@ module MakeImpl<InputSig Lang> {
|
||||
bindingset[node, cc]
|
||||
LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
|
||||
|
||||
bindingset[call, c, outercc]
|
||||
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
|
||||
checkCallContextCall(outercc, call, c) and
|
||||
DataFlowCallable viableImplCallContextReduced(DataFlowCall call, CcCall ctx) {
|
||||
result = prunedViableImplInCallContext(call, ctx)
|
||||
}
|
||||
|
||||
bindingset[call, ctx]
|
||||
predicate viableImplNotCallContextReduced(DataFlowCall call, Cc ctx) {
|
||||
noPrunedViableImplInCallContext(call, ctx)
|
||||
}
|
||||
|
||||
bindingset[call, c]
|
||||
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c) {
|
||||
if recordDataFlowCallSiteDispatch(call, c)
|
||||
then result = TSpecificCall(call)
|
||||
else result = TSomeCall()
|
||||
@@ -1918,18 +2039,33 @@ module MakeImpl<InputSig Lang> {
|
||||
node.getEnclosingCallable())
|
||||
}
|
||||
|
||||
bindingset[call, c, outercc]
|
||||
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
|
||||
checkCallContextCall(outercc, call, c) and
|
||||
DataFlowCallable viableImplCallContextReduced(DataFlowCall call, CcCall ctx) {
|
||||
result = prunedViableImplInCallContext(call, ctx)
|
||||
}
|
||||
|
||||
bindingset[call, ctx]
|
||||
predicate viableImplNotCallContextReduced(DataFlowCall call, Cc ctx) {
|
||||
noPrunedViableImplInCallContext(call, ctx)
|
||||
}
|
||||
|
||||
bindingset[call, c]
|
||||
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c) {
|
||||
if recordDataFlowCallSite(call, c)
|
||||
then result = TSpecificCall(call)
|
||||
else result = TSomeCall()
|
||||
}
|
||||
}
|
||||
|
||||
bindingset[call, c, innercc]
|
||||
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
|
||||
checkCallContextReturn(innercc, c, call) and
|
||||
DataFlowCallable viableImplCallContextReducedReverse(DataFlowCall call, CcNoCall ctx) {
|
||||
call = prunedViableImplInCallContextReverse(result, ctx)
|
||||
}
|
||||
|
||||
predicate viableImplNotCallContextReducedReverse(CcNoCall ctx) {
|
||||
ctx instanceof CallContextAny
|
||||
}
|
||||
|
||||
bindingset[call, c]
|
||||
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,9 +750,11 @@ module MakeImplCommon<InputSig Lang> {
|
||||
* makes a difference.
|
||||
*/
|
||||
cached
|
||||
DataFlowCallable prunedViableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
|
||||
result = viableImplInCallContextExt(call, ctx) and
|
||||
reducedViableImplInCallContext(call, _, ctx)
|
||||
DataFlowCallable prunedViableImplInCallContext(DataFlowCall call, CallContextSpecificCall ctx) {
|
||||
exists(DataFlowCall outer | ctx = TSpecificCall(outer) |
|
||||
result = viableImplInCallContextExt(call, outer) and
|
||||
reducedViableImplInCallContext(call, _, outer)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -772,15 +774,20 @@ module MakeImplCommon<InputSig Lang> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a viable run-time dispatch target for the call `call` in the
|
||||
* context `ctx`. This is restricted to those calls and results for which
|
||||
* the return flow from the result to `call` restricts the possible context
|
||||
* `ctx`.
|
||||
* Gets a viable call site for the return from `callable` in call context
|
||||
* `ctx`. This is restricted to those callables and contexts for which
|
||||
* the possible call sites are restricted.
|
||||
*/
|
||||
cached
|
||||
DataFlowCallable prunedViableImplInCallContextReverse(DataFlowCall call, DataFlowCall ctx) {
|
||||
result = viableImplInCallContextExt(call, ctx) and
|
||||
reducedViableImplInReturn(result, call)
|
||||
DataFlowCall prunedViableImplInCallContextReverse(
|
||||
DataFlowCallable callable, CallContextReturn ctx
|
||||
) {
|
||||
exists(DataFlowCallable c0, DataFlowCall call0 |
|
||||
callEnclosingCallable(call0, callable) and
|
||||
ctx = TReturn(c0, call0) and
|
||||
c0 = viableImplInCallContextExt(call0, result) and
|
||||
reducedViableImplInReturn(c0, call0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1278,72 +1285,39 @@ module MakeImplCommon<InputSig Lang> {
|
||||
result = getReturnPosition0(ret, ret.getKind())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether `inner` can return to `call` in the call context `innercc`.
|
||||
* Assumes a context of `inner = viableCallableExt(call)`.
|
||||
*/
|
||||
bindingset[innercc, inner, call]
|
||||
predicate checkCallContextReturn(CallContext innercc, DataFlowCallable inner, DataFlowCall call) {
|
||||
innercc instanceof CallContextAny
|
||||
or
|
||||
exists(DataFlowCallable c0, DataFlowCall call0 |
|
||||
callEnclosingCallable(call0, inner) and
|
||||
innercc = TReturn(c0, call0) and
|
||||
c0 = prunedViableImplInCallContextReverse(call0, call)
|
||||
/** Holds if `call` does not have a reduced set of dispatch targets in call context `ctx`. */
|
||||
bindingset[call, ctx]
|
||||
predicate noPrunedViableImplInCallContext(DataFlowCall call, CallContext ctx) {
|
||||
exists(DataFlowCall outer | ctx = TSpecificCall(outer) |
|
||||
not reducedViableImplInCallContext(call, _, outer)
|
||||
)
|
||||
or
|
||||
ctx instanceof CallContextSomeCall
|
||||
or
|
||||
ctx instanceof CallContextAny
|
||||
or
|
||||
ctx instanceof CallContextReturn
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether `call` can resolve to `calltarget` in the call context `cc`.
|
||||
* Assumes a context of `calltarget = viableCallableExt(call)`.
|
||||
*/
|
||||
bindingset[cc, call, calltarget]
|
||||
predicate checkCallContextCall(CallContext cc, DataFlowCall call, DataFlowCallable calltarget) {
|
||||
exists(DataFlowCall ctx | cc = TSpecificCall(ctx) |
|
||||
if reducedViableImplInCallContext(call, _, ctx)
|
||||
then calltarget = prunedViableImplInCallContext(call, ctx)
|
||||
else any()
|
||||
)
|
||||
or
|
||||
cc instanceof CallContextSomeCall
|
||||
or
|
||||
cc instanceof CallContextAny
|
||||
or
|
||||
cc instanceof CallContextReturn
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a return from `callable` in `cc` to `call`. This is equivalent to
|
||||
* `callable = viableCallableExt(call) and checkCallContextReturn(cc, callable, call)`.
|
||||
* Resolves a return from `callable` in `cc` to `call`.
|
||||
*/
|
||||
bindingset[cc, callable]
|
||||
predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) {
|
||||
cc instanceof CallContextAny and callable = viableCallableExt(call)
|
||||
or
|
||||
exists(DataFlowCallable c0, DataFlowCall call0 |
|
||||
callEnclosingCallable(call0, callable) and
|
||||
cc = TReturn(c0, call0) and
|
||||
c0 = prunedViableImplInCallContextReverse(call0, call)
|
||||
)
|
||||
call = prunedViableImplInCallContextReverse(callable, cc)
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a call from `call` in `cc` to `result`. This is equivalent to
|
||||
* `result = viableCallableExt(call) and checkCallContextCall(cc, call, result)`.
|
||||
* Resolves a call from `call` in `cc` to `result`.
|
||||
*/
|
||||
bindingset[call, cc]
|
||||
DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
|
||||
exists(DataFlowCall ctx | cc = TSpecificCall(ctx) |
|
||||
if reducedViableImplInCallContext(call, _, ctx)
|
||||
then result = prunedViableImplInCallContext(call, ctx)
|
||||
else result = viableCallableExt(call)
|
||||
)
|
||||
result = prunedViableImplInCallContext(call, cc)
|
||||
or
|
||||
result = viableCallableExt(call) and cc instanceof CallContextSomeCall
|
||||
or
|
||||
result = viableCallableExt(call) and cc instanceof CallContextAny
|
||||
or
|
||||
result = viableCallableExt(call) and cc instanceof CallContextReturn
|
||||
noPrunedViableImplInCallContext(call, cc) and
|
||||
result = viableCallableExt(call)
|
||||
}
|
||||
|
||||
/** An optional Boolean value. */
|
||||
|
||||
Reference in New Issue
Block a user