From 0c546c9125c48fc4d01ecc498b03c2a49f16069e Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 19 Aug 2024 09:40:59 +0200 Subject: [PATCH] temp2 --- .../codeql/dataflow/internal/DataFlowImpl.qll | 50 +++- .../dataflow/internal/DataFlowImplCommon.qll | 260 ++++++++++-------- 2 files changed, 183 insertions(+), 127 deletions(-) diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index c15fab4d9b508..23f3f0917f551 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -1535,14 +1535,6 @@ module MakeImpl Lang> { fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t } - bindingset[storeSource, c, readTarget] - pragma[inline_late] - private predicate storeMayReachReadInlineLate( - NodeEx storeSource, Content c, NodeEx readTarget - ) { - Param::storeMayReachRead(storeSource, c, readTarget) - } - pragma[nomagic] private predicate fwdFlow0( NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, @@ -1731,7 +1723,7 @@ module MakeImpl Lang> { ( exists(NodeEx storeSource | fwdFlowConsCandStoreReadMatchingEnabled(storeSource, t1, ap1, c, t2, ap2) and - storeMayReachReadInlineLate(storeSource, c, node2) + storeMayReachRead(storeSource, c, node2) ) or fwdFlowConsCandStoreReadMatchingDisabled(t1, ap1, c, t2, ap2) @@ -2276,7 +2268,7 @@ module MakeImpl Lang> { | exists(NodeEx readTarget | revFlowConsCandStoreReadMatchingEnabled(readTarget, ap0, c, ap) and - storeMayReachReadInlineLate(node, c, readTarget) + storeMayReachRead(node, c, readTarget) ) or revFlowConsCandStoreReadMatchingDisabled(ap0, c, ap) @@ -3430,6 +3422,27 @@ module MakeImpl Lang> { private module StoreReadMatchingInput implements StoreReadMatchingInputSig { class NodeEx = NodeExAlias; + predicate nodeRange(NodeEx node, boolean fromArg) { + exists(PrevStage::Ap ap | + PrevStage::revFlowAp(node, ap) and + ( + ap = true + or + PrevStage::storeStepCand(node, ap, _, _, _, _) + or + PrevStage::readStepCand(_, _, node) + ) + | + exists(PrevStage::Cc cc | PrevStage::fwdFlow(node, _, cc, _, _, _, _, ap, _) | + PrevStage::instanceofCcCall(cc) and + fromArg = true + or + PrevStage::instanceofCcNoCall(cc) and + fromArg = false + ) + ) + } + predicate localValueStep(NodeEx node1, NodeEx node2) { exists(FlowState state, PrevStage::ApOption returnAp | PrevStage::revFlow(node1, pragma[only_bind_into](state), _, @@ -3442,12 +3455,23 @@ module MakeImpl Lang> { predicate jumpValueStep = jumpStepEx/2; + pragma[nomagic] + private predicate flowThroughOutOfCall(RetNodeEx ret, NodeEx out) { + exists(DataFlowCall call, CcCall ccc, ReturnKindExt kind | + PrevStage::callEdgeReturn(call, _, ret, kind, out, true, true) and + PrevStage::callMayFlowThroughRev(call) and + PrevStage::returnMayFlowThrough(ret, _, true, kind) and + matchesCall(ccc, call) + ) + } + predicate callEdgeArgParam(NodeEx arg, NodeEx param) { - PrevStage::callEdgeArgParam(_, _, arg, param, true, _) + PrevStage::callEdgeArgParam(_, _, arg, param, true, true) } - predicate callEdgeReturn(NodeEx ret, NodeEx out) { - PrevStage::callEdgeReturn(_, _, ret, _, out, true, _) + predicate callEdgeReturn(NodeEx ret, NodeEx out, boolean mayFlowThrough) { + PrevStage::callEdgeReturn(_, _, ret, _, out, true, true) and + if flowThroughOutOfCall(ret, out) then mayFlowThrough = true else mayFlowThrough = false } predicate readContentStep = PrevStage::readStepCand/3; diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll index 20e5220f8cfd1..a7d8f4bbe0589 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll @@ -2358,13 +2358,15 @@ module MakeImplCommon Lang> { string toString(); } + predicate nodeRange(NodeEx node, boolean fromArg); + predicate localValueStep(NodeEx node1, NodeEx node2); predicate jumpValueStep(NodeEx node1, NodeEx node2); predicate callEdgeArgParam(NodeEx arg, NodeEx param); - predicate callEdgeReturn(NodeEx ret, NodeEx out); + predicate callEdgeReturn(NodeEx ret, NodeEx out, boolean mayFlowThrough); predicate readContentStep(NodeEx node1, Content c, NodeEx node2); @@ -2392,101 +2394,124 @@ module MakeImplCommon Lang> { * 3. Which reads may have _a_ matching store (called `aStoreMayReachRead` below). */ module StoreReadMatching { + private import codeql.util.Boolean private import Input - pragma[nomagic] - private predicate valueStep(NodeEx node1, NodeEx node2) { - localValueStep(node1, node2) - or - jumpValueStep(node1, node2) - or - callEdgeArgParam(node1, node2) - or - callEdgeReturn(node1, node2) - } - private signature module StoreReachesReadInputSig { int iteration(); - predicate storeMayReachReadDelta(NodeEx storeSource, Content c, NodeEx readTarget); + predicate storeMayReachReadDelta( + NodeEx storeSource, Content c, NodeEx readTarget, boolean fromArg1, boolean fromArg2 + ); - predicate storeMayReachReadPrev(NodeEx storeSource, Content c, NodeEx readTarget); + predicate storeMayReachReadPrev( + NodeEx storeSource, Content c, NodeEx readTarget, boolean fromArg1, boolean fromArg2 + ); } - private signature class UsesPrevDeltaInfoSig { - string toString(); + private newtype TNodeOrContent = + TNodeOrContentNode(NodeEx n, Boolean usesPrevDelta, boolean fromArg) { nodeRange(n, fromArg) } or + TNodeOrContentStoreContent(Content c) { storeContentStep(_, c, _) } or + TNodeOrContentReadContent(Content c) { readContentStep(_, c, _) } + + private class NodeOrContent extends TNodeOrContent { + NodeEx asNodeEx(boolean usesPrevDelta, boolean fromArg) { + this = TNodeOrContentNode(result, usesPrevDelta, fromArg) + } + + Content asStoreContent() { this = TNodeOrContentStoreContent(result) } - boolean toBoolean(); + Content asReadContent() { this = TNodeOrContentReadContent(result) } + + string toString() { + result = this.asStoreContent().toString() + or + result = this.asReadContent().toString() + or + result = this.asNodeEx(_, _).toString() + } } - private module StoreReachesRead< - StoreReachesReadInputSig Prev, UsesPrevDeltaInfoSig UsesPrevDeltaInfo> implements + private module StoreReachesRead implements StoreReachesReadInputSig { int iteration() { result = Prev::iteration() + 1 } private predicate enabled() { accessPathConfigLimit() > Prev::iteration() } - private newtype TNodeOrContent = - TNodeOrContentNode(NodeEx n, UsesPrevDeltaInfo usesPrevDelta) { enabled() } or - TNodeOrContentStoreContent(Content c) { enabled() and storeContentStep(_, c, _) } or - TNodeOrContentReadContent(Content c) { enabled() and readContentStep(_, c, _) } - - private class NodeOrContent extends TNodeOrContent { - NodeEx asNodeEx(UsesPrevDeltaInfo usesPrevDelta) { - this = TNodeOrContentNode(result, usesPrevDelta) - } - - Content asStoreContent() { this = TNodeOrContentStoreContent(result) } - - Content asReadContent() { this = TNodeOrContentReadContent(result) } + private predicate usesPrevDelta(Boolean usesPrevDelta) { + // in the first iteration there is no previous delta to use + if iteration() > 1 then usesPrevDelta = true else any() + } - string toString() { - result = this.asStoreContent().toString() + pragma[nomagic] + private predicate stepNode( + NodeOrContent node1, NodeEx n2, boolean usesPrevDelta1, boolean usesPrevDelta2, + Boolean fromArg1, Boolean fromArg2 + ) { + enabled() and + exists(NodeEx n1 | n1 = node1.asNodeEx(usesPrevDelta1, fromArg1) | + usesPrevDelta1 = usesPrevDelta2 and + ( + localValueStep(n1, n2) and + fromArg1 = fromArg2 + or + jumpValueStep(n1, n2) and + fromArg2 = false + or + callEdgeArgParam(n1, n2) and + fromArg2 = true + or + exists(boolean mayFlowThrough | callEdgeReturn(n1, n2, mayFlowThrough) | + fromArg1 = false or mayFlowThrough = true + ) + ) or - result = this.asReadContent().toString() + Prev::storeMayReachReadDelta(n1, _, n2, fromArg1, fromArg2) and + usesPrevDelta2 = true or - result = this.asNodeEx(_).toString() - } + Prev::storeMayReachReadPrev(n1, _, n2, fromArg1, fromArg2) and + usesPrevDelta1 = usesPrevDelta2 + ) } pragma[nomagic] private predicate step(NodeOrContent node1, NodeOrContent node2) { exists( - NodeEx n1, NodeEx n2, UsesPrevDeltaInfo usesPrevDelta1, UsesPrevDeltaInfo usesPrevDelta2 + NodeEx n2, boolean usesPrevDelta1, boolean usesPrevDelta2, boolean fromArg1, + boolean fromArg2 | - n1 = node1.asNodeEx(usesPrevDelta1) and - n2 = node2.asNodeEx(usesPrevDelta2) - | - valueStep(n1, n2) and - pragma[only_bind_into](pragma[only_bind_out](usesPrevDelta2)) = - pragma[only_bind_into](pragma[only_bind_out](usesPrevDelta1)) - or - Prev::storeMayReachReadDelta(n1, _, n2) and usesPrevDelta2.toBoolean() = true - or - Prev::storeMayReachReadPrev(n1, _, n2) and - pragma[only_bind_into](pragma[only_bind_out](usesPrevDelta2)) = - pragma[only_bind_into](pragma[only_bind_out](usesPrevDelta1)) - ) - or - exists(NodeEx n2, Content c, UsesPrevDeltaInfo usesPrevDelta2 | - n2 = node2.asNodeEx(usesPrevDelta2) and - c = node1.asStoreContent() and - storeContentStep(_, c, n2) and - usesPrevDelta2.toBoolean() = false + n2 = node2.asNodeEx(usesPrevDelta2, fromArg2) and + stepNode(node1, n2, usesPrevDelta1, usesPrevDelta2, fromArg1, fromArg2) ) or - exists(NodeEx n1, Content c, UsesPrevDeltaInfo usesPrevDelta1 | - n1 = node1.asNodeEx(usesPrevDelta1) and - c = node2.asReadContent() and - readContentStep(n1, c, _) and - usesPrevDelta1.toBoolean() = true + enabled() and + ( + exists(NodeEx n2, Content c, boolean usesPrevDelta2 | + n2 = node2.asNodeEx(usesPrevDelta2, _) and + c = node1.asStoreContent() and + storeContentStep(_, c, n2) and + usesPrevDelta2 = false + ) + or + exists(NodeEx n1, Content c, boolean usesPrevDelta1 | + n1 = node1.asNodeEx(usesPrevDelta1, _) and + c = node2.asReadContent() and + readContentStep(n1, c, _) and + usesPrevDelta(usesPrevDelta1) + ) ) } - private predicate isStoreContent(NodeOrContent c) { exists(c.asStoreContent()) } + private predicate isStoreContent(NodeOrContent c) { + enabled() and + exists(c.asStoreContent()) + } - private predicate isReadContent(NodeOrContent c) { exists(c.asReadContent()) } + private predicate isReadContent(NodeOrContent c) { + enabled() and + exists(c.asReadContent()) + } private predicate contentReachesReadTc(NodeOrContent node1, NodeOrContent node2) = doublyBoundedFastTC(step/2, isStoreContent/1, isReadContent/1)(node1, node2) @@ -2498,6 +2523,7 @@ module MakeImplCommon Lang> { } additional predicate contentIsReadAndStored(Content c) { + enabled() and exists(NodeOrContent n1, NodeOrContent n2 | contentReachesReadTc(n1, n2) and contentIsReadAndStoredJoin(n1, n2, c) @@ -2506,10 +2532,10 @@ module MakeImplCommon Lang> { pragma[nomagic] private predicate isStoreTarget0(NodeOrContent node, Content c) { - exists(UsesPrevDeltaInfo usesPrevDelta | + exists(boolean usesPrevDelta | contentIsReadAndStored(c) and - storeContentStep(_, c, node.asNodeEx(usesPrevDelta)) and - usesPrevDelta.toBoolean() = false + storeContentStep(_, c, node.asNodeEx(usesPrevDelta, _)) and + usesPrevDelta = false ) } @@ -2517,10 +2543,10 @@ module MakeImplCommon Lang> { pragma[nomagic] private predicate isReadSource0(NodeOrContent node, Content c) { - exists(UsesPrevDeltaInfo usesPrevDelta | + exists(boolean usesPrevDelta | contentIsReadAndStored(c) and - readContentStep(node.asNodeEx(usesPrevDelta), c, _) and - usesPrevDelta.toBoolean() = true + readContentStep(node.asNodeEx(usesPrevDelta, _), c, _) and + usesPrevDelta(usesPrevDelta) ) } @@ -2566,93 +2592,99 @@ module MakeImplCommon Lang> { doublyBoundedFastTC(step/2, isStoreTargetPruned/1, isReadSourcePruned/1)(node1, node2) pragma[nomagic] - private predicate storeMayReachReadDeltaJoinLeft(NodeEx node1, Content c, NodeOrContent node2) { - exists(UsesPrevDeltaInfo usesPrevDelta | - storeMayReachARead(node2, c) and - storeContentStep(node1, c, node2.asNodeEx(usesPrevDelta)) and - usesPrevDelta.toBoolean() = false + private predicate storeMayReachReadDeltaJoinLeft( + NodeEx node1, Content c, NodeOrContent node2, boolean fromArg + ) { + exists(boolean usesPrevDelta | + storeMayReachARead(pragma[only_bind_into](node2), pragma[only_bind_into](c)) and + storeContentStep(node1, c, node2.asNodeEx(usesPrevDelta, fromArg)) and + usesPrevDelta = false ) } pragma[nomagic] - private predicate storeMayReachReadDeltaJoinRight(NodeOrContent node1, Content c, NodeEx node2) { - exists(UsesPrevDeltaInfo usesPrevDelta | - aStoreMayReachRead(node1, c) and - readContentStep(node1.asNodeEx(usesPrevDelta), c, node2) and - usesPrevDelta.toBoolean() = true + private predicate storeMayReachReadDeltaJoinRight( + NodeOrContent node1, Content c, NodeEx node2, boolean fromArg + ) { + exists(boolean usesPrevDelta | + aStoreMayReachRead(pragma[only_bind_into](node1), pragma[only_bind_into](c)) and + readContentStep(node1.asNodeEx(usesPrevDelta, fromArg), c, node2) and + usesPrevDelta(usesPrevDelta) ) } pragma[nomagic] - predicate storeMayReachReadDelta(NodeEx storeSource, Content c, NodeEx readTarget) { + predicate storeMayReachReadDelta( + NodeEx storeSource, Content c, NodeEx readTarget, boolean fromArg1, boolean fromArg2 + ) { exists(NodeOrContent storeTarget, NodeOrContent readSource | storeMayReachReadTc(storeTarget, readSource) and - storeMayReachReadDeltaJoinLeft(storeSource, c, storeTarget) and - storeMayReachReadDeltaJoinRight(readSource, c, readTarget) + storeMayReachReadDeltaJoinLeft(storeSource, c, storeTarget, fromArg1) and + storeMayReachReadDeltaJoinRight(readSource, c, readTarget, fromArg2) ) and - not Prev::storeMayReachReadPrev(storeSource, c, readTarget) + not Prev::storeMayReachReadPrev(storeSource, c, readTarget, fromArg1, fromArg2) } pragma[nomagic] - predicate storeMayReachReadPrev(NodeEx storeSource, Content c, NodeEx readTarget) { - Prev::storeMayReachReadPrev(storeSource, c, readTarget) + predicate storeMayReachReadPrev( + NodeEx storeSource, Content c, NodeEx readTarget, boolean fromArg1, boolean fromArg2 + ) { + Prev::storeMayReachReadPrev(storeSource, c, readTarget, fromArg1, fromArg2) or - Prev::storeMayReachReadDelta(storeSource, c, readTarget) + Prev::storeMayReachReadDelta(storeSource, c, readTarget, fromArg1, fromArg2) } } module Iteration0 implements StoreReachesReadInputSig { int iteration() { result = 0 } - predicate storeMayReachReadDelta(NodeEx node1, Content c, NodeEx node2) { none() } - - predicate storeMayReachReadPrev(NodeEx node1, Content c, NodeEx node2) { none() } - } + predicate storeMayReachReadDelta( + NodeEx node1, Content c, NodeEx node2, boolean fromArg1, boolean fromArg2 + ) { + none() + } - // in the first iteration there is no previous delta to use - private class UsesPrevDeltaInfoUnit extends Unit { - boolean toBoolean() { result = [false, true] } + predicate storeMayReachReadPrev( + NodeEx node1, Content c, NodeEx node2, boolean fromArg1, boolean fromArg2 + ) { + none() + } } private module StoreReachesRead1 implements StoreReachesReadInputSig { - private module M = StoreReachesRead; + private module M = StoreReachesRead; import M - predicate storeMayReachReadDelta(NodeEx storeSource, Content c, NodeEx readTarget) { - M::storeMayReachReadDelta(storeSource, c, readTarget) + predicate storeMayReachReadDelta( + NodeEx storeSource, Content c, NodeEx readTarget, boolean fromArg1, boolean fromArg2 + ) { + M::storeMayReachReadDelta(storeSource, c, readTarget, fromArg1, fromArg2) or // special case only needed for the first iteration: a store immediately followed by a read exists(NodeEx storeTargetReadSource | StoreReachesRead1::contentIsReadAndStored(c) and storeContentStep(storeSource, c, storeTargetReadSource) and readContentStep(storeTargetReadSource, c, readTarget) - ) + ) and + nodeRange(storeSource, fromArg1) and + nodeRange(readTarget, fromArg2) and + fromArg1 = fromArg2 } } - private import codeql.util.Boolean - - private class UsesPrevDeltaInfoBoolean extends Boolean { - boolean toBoolean() { result = this } - } - - private module StoreReachesRead2 = - StoreReachesRead; + private module StoreReachesRead2 = StoreReachesRead; - private module StoreReachesRead3 = - StoreReachesRead; + private module StoreReachesRead3 = StoreReachesRead; - private module StoreReachesRead4 = - StoreReachesRead; + private module StoreReachesRead4 = StoreReachesRead; - private module StoreReachesRead5 = - StoreReachesRead; + private module StoreReachesRead5 = StoreReachesRead; predicate storeMayReachRead(NodeEx storeSource, Content c, NodeEx readTarget) { - StoreReachesRead5::storeMayReachReadDelta(storeSource, c, readTarget) + StoreReachesRead5::storeMayReachReadDelta(storeSource, c, readTarget, _, _) or - StoreReachesRead5::storeMayReachReadPrev(storeSource, c, readTarget) + StoreReachesRead5::storeMayReachReadPrev(storeSource, c, readTarget, _, _) } } }