From 0a4c680e1774ead254142deec52af7eea1a30822 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 5 Nov 2020 13:37:40 +0100 Subject: [PATCH] Dataflow: Align on localStep. --- .../java/dataflow/internal/DataFlowImpl.qll | 105 ++++++++++++------ 1 file changed, 73 insertions(+), 32 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 6ad5a0ea0e7..9f803afa632 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -774,6 +774,8 @@ private module Stage2 { Cc ccAny() { result = false } + class LocalCc = Unit; + bindingset[call, c, outercc] CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } @@ -787,6 +789,23 @@ private module Stage2 { Stage1::revFlow(node, config) and exists(apa) } + bindingset[node, cc, config] + LocalCc getLocalCc(Node node, Cc cc, Configuration config) { any() } + + predicate localStep( + Node node1, Node node2, boolean preservesValue, ApNil ap, Configuration config, LocalCc lcc + ) { + ( + preservesValue = true and + localFlowStepNodeCand1(node1, node2, config) + or + preservesValue = false and + additionalLocalFlowStepNodeCand1(node1, node2, config) + ) and + exists(ap) and + exists(lcc) + } + /* Begin: Stage 2 logic. */ /** * Holds if `node` is reachable from a source in the configuration `config`. @@ -804,15 +823,15 @@ private module Stage2 { argAp = apNone() and ap = getApNil(node) or - exists(Node mid | - fwdFlow(mid, cc, argAp, ap, config) and - localFlowStepNodeCand1(mid, node, config) - ) - or - exists(Node mid | - fwdFlow(mid, cc, argAp, ap, config) and - additionalLocalFlowStepNodeCand1(mid, node, config) and - ap = false + exists(Node mid, Ap ap0, LocalCc localCc | + fwdFlow(mid, cc, argAp, ap0, config) and + localCc = getLocalCc(mid, cc, config) + | + localStep(mid, node, true, _, config, localCc) and + ap = ap0 + or + localStep(mid, node, false, ap, config, localCc) and + ap0 instanceof ApNil ) or exists(Node mid | @@ -970,13 +989,13 @@ private module Stage2 { ap instanceof ApNil or exists(Node mid | - localFlowStepNodeCand1(node, mid, config) and + localStep(node, mid, true, _, config, _) and revFlow(mid, toReturn, returnAp, ap, config) ) or exists(Node mid, ApNil nil | fwdFlow(node, _, _, ap, config) and - additionalLocalFlowStepNodeCand1(node, mid, config) and + localStep(node, mid, false, _, config, _) and revFlow(mid, toReturn, returnAp, nil, config) and ap instanceof ApNil ) @@ -1317,6 +1336,8 @@ private module Stage3 { Cc ccAny() { result = false } + class LocalCc = Unit; + bindingset[call, c, outercc] CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } @@ -1330,6 +1351,15 @@ private module Stage3 { Stage2::revFlow(node, _, _, apa, config) } + bindingset[node, cc, config] + LocalCc getLocalCc(Node node, Cc cc, Configuration config) { any() } + + predicate localStep( + Node node1, Node node2, boolean preservesValue, ApNil ap, Configuration config, LocalCc lcc + ) { + localFlowBigStep(node1, node2, preservesValue, ap, config, _) and exists(lcc) + } + /* Begin: Stage 3 logic. */ /** * Holds if `node` is reachable with access path front `ap` from a @@ -1355,14 +1385,15 @@ private module Stage3 { argAp = apNone() and ap = getApNil(node) or - exists(Node mid | - fwdFlow(mid, cc, argAp, ap, config) and - localFlowBigStep(mid, node, true, _, config, _) - ) - or - exists(Node mid, ApNil nil | - fwdFlow(mid, cc, argAp, nil, config) and - localFlowBigStep(mid, node, false, ap, config, _) + exists(Node mid, Ap ap0, LocalCc localCc | + fwdFlow(mid, cc, argAp, ap0, config) and + localCc = getLocalCc(mid, cc, config) + | + localStep(mid, node, true, _, config, localCc) and + ap = ap0 + or + localStep(mid, node, false, ap, config, localCc) and + ap0 instanceof ApNil ) or exists(Node mid | @@ -1522,13 +1553,13 @@ private module Stage3 { ap instanceof ApNil or exists(Node mid | - localFlowBigStep(node, mid, true, _, config, _) and + localStep(node, mid, true, _, config, _) and revFlow(mid, toReturn, returnAp, ap, config) ) or exists(Node mid, ApNil nil | fwdFlow(node, _, _, ap, config) and - localFlowBigStep(node, mid, false, _, config, _) and + localStep(node, mid, false, _, config, _) and revFlow(mid, toReturn, returnAp, nil, config) and ap instanceof ApNil ) @@ -1902,6 +1933,8 @@ private module Stage4 { Cc ccAny() { result instanceof CallContextAny } + class LocalCc = LocalCallContext; + bindingset[call, c, outercc] CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { c = resolveCall(call, outercc) and @@ -1924,6 +1957,18 @@ private module Stage4 { Stage3::revFlow(node, _, _, apa, config) } + bindingset[node, cc, config] + LocalCc getLocalCc(Node node, Cc cc, Configuration config) { + localFlowEntry(node, config) and + result = getLocalCallContext(cc, node.getEnclosingCallable()) + } + + predicate localStep( + Node node1, Node node2, boolean preservesValue, ApNil ap, Configuration config, LocalCc lcc + ) { + localFlowBigStep(node1, node2, preservesValue, ap.getFront(), config, lcc) + } + /* Begin: Stage 4 logic. */ /** * Holds if `node` is reachable with approximate access path `ap` from a source @@ -1945,19 +1990,15 @@ private module Stage4 { argAp = apNone() and ap = getApNil(node) or - exists(Node mid, Ap ap0, LocalCallContext localCC | + exists(Node mid, Ap ap0, LocalCc localCc | fwdFlow(mid, cc, argAp, ap0, config) and - localFlowEntry(mid, config) and - localCC = getLocalCallContext(cc, mid.getEnclosingCallable()) + localCc = getLocalCc(mid, cc, config) | - localFlowBigStep(mid, node, true, _, config, localCC) and + localStep(mid, node, true, _, config, localCc) and ap = ap0 or - exists(AccessPathFront apf | - localFlowBigStep(mid, node, false, apf, config, localCC) and - ap0 instanceof ApNil and - apf = ap.(ApNil).getFront() - ) + localStep(mid, node, false, ap, config, localCc) and + ap0 instanceof ApNil ) or exists(Node mid | @@ -2137,13 +2178,13 @@ private module Stage4 { ap instanceof ApNil or exists(Node mid | - localFlowBigStep(node, mid, true, _, config, _) and + localStep(node, mid, true, _, config, _) and revFlow(mid, toReturn, returnAp, ap, config) ) or exists(Node mid, ApNil nil | fwdFlow(node, _, _, ap, config) and - localFlowBigStep(node, mid, false, _, config, _) and + localStep(node, mid, false, _, config, _) and revFlow(mid, toReturn, returnAp, nil, config) and ap instanceof ApNil )