From dbe1ca928b89c2a7edb3e8d3d1d856dfaeb138a9 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 2 Jul 2021 11:59:20 +0200 Subject: [PATCH] Dataflow: Simplify call context checks. --- .../dataflow/internal/DataFlowImplCommon.qll | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index e16a8185d72..728f7b56c42 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -1117,16 +1117,44 @@ ReturnPosition getReturnPosition(ReturnNodeExt ret) { 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) { - resolveReturn(innercc, inner, call) + innercc instanceof CallContextAny + or + exists(DataFlowCallable c0, DataFlowCall call0 | + callEnclosingCallable(call0, inner) and + innercc = TReturn(c0, call0) and + c0 = prunedViableImplInCallContextReverse(call0, call) + ) } +/** + * 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) { - calltarget = resolveCall(call, cc) + 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)`. + */ bindingset[cc, callable] predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) { cc instanceof CallContextAny and callable = viableCallableExt(call) @@ -1138,6 +1166,10 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall ) } +/** + * Resolves a call from `call` in `cc` to `result`. This is equivalent to + * `result = viableCallableExt(call) and checkCallContextCall(cc, call, result)`. + */ bindingset[call, cc] DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) { exists(DataFlowCall ctx | cc = TSpecificCall(ctx) |