From acd85a35f5c46d00703849354e5d99e141897d9b Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 11 Oct 2024 13:42:32 +0200 Subject: [PATCH] Data flow: Prevent quadratic blowup in `Stage6Param::localStep` --- .../codeql/dataflow/internal/DataFlowImpl.qll | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index 483cf1315a45e..782a1349314c3 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -3790,7 +3790,7 @@ module MakeImpl Lang> { import CallContextSensitivity import NoLocalCallContext - private module BigStepInput implements PrevStage::LocalFlowBigStepInputSig { + additional module BigStepInput implements PrevStage::LocalFlowBigStepInputSig { bindingset[node1, state1] bindingset[node2, state2] predicate localStep( @@ -4411,11 +4411,36 @@ module MakeImpl Lang> { import LocalCallContext private module BigStepInput implements PrevStage::LocalFlowBigStepInputSig { + private predicate smallStep = Stage3Param::BigStepInput::localStep/8; + + private predicate localStepCand( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2 + ) { + PrevStage::revFlow(node1, state1, _) and + smallStep(node1, state1, node2, state2, _, _, _, _) + or + exists(FlowState midState, NodeEx midNode | + localStepCand(node1, state1, midNode, midState) and + smallStep(midNode, midState, node2, state2, _, _, _, _) and + not Stage5Param::localStep(midNode, midState, _, _, _, _, _, _) + ) + } + + /** + * When calculating `localFlowBigStep` based on `Stage5Param::localStep`, which + * is already a big-step relation, we must be careful to avoid quadratic blowup. + * + * This is achieved by restricting `Stage5Param::localStep` to those node pairs + * reacheable via 1 or more `smallStep`s, where any intermediate node is not + * already part of `Stage5Param::localStep`. + */ + pragma[nomagic] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, DataFlowType t, LocalCallContext lcc, string label ) { - Stage3Param::localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc, label) and + localStepCand(node1, state1, node2, state2) and + Stage5Param::localStep(node1, state1, node2, state2, preservesValue, t, lcc, label) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) }