From 0e2ec0dfb4d8c11b1d062e31240f1684d5bcb391 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Tue, 20 Oct 2020 17:29:26 +0200 Subject: [PATCH] Python: Remove cartesian product in `TKwOverflowNode` With CP: (0s) Tuple counts for dom#DataFlowPublic::TKwOverflowNode#ff: 1209 ~0% {2} r1 = JOIN project#AstGenerated::Function_::getKwarg_dispred#ff AS L WITH ObjectAPI::CallableValue::getScope_dispred#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1>, L.<0> 4329 ~0% {3} r2 = JOIN r1 WITH DataFlowPrivate::ArgumentPassing::connects#bb_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1>, r1.<1>, r1.<0> 7819 ~2% {4} r3 = JOIN r2 WITH Flow::CallNode::getArgByName_dispred#fff AS R ON FIRST 1 OUTPUT r2.<1>, r2.<2>, r2.<0>, R.<1> 7114 ~1% {4} r4 = r3 AND NOT Function::Function::getArgByName_dispred#fff_01#antijoin_rhs AS R(r3.<0>, r3.<3>) 7114 ~76% {2} r5 = SCAN r4 OUTPUT r4.<2>, r4.<1> 1123 ~0% {1} r6 = JOIN project#Exprs::Call::getKwargs_dispred#ff AS L WITH py_flow_bb_node_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1> 1123 ~0% {1} r7 = JOIN r6 WITH Flow::CallNode#class#f AS R ON FIRST 1 OUTPUT r6.<0> 1357707 ~0% {2} r8 = JOIN r7 WITH project#AstGenerated::Function_::getKwarg_dispred#ff AS R CARTESIAN PRODUCT OUTPUT R.<0>, r7.<0> 1357707 ~0% {2} r9 = JOIN r8 WITH ObjectAPI::CallableValue::getScope_dispred#ff_10#join_rhs AS R ON FIRST 1 OUTPUT r8.<1>, R.<1> 1364821 ~0% {2} r10 = r5 \/ r9 return r10 Without CP: (13s) Tuple counts for dom#DataFlowPublic::TKwOverflowNode#ff: 1209 ~0% {2} r1 = JOIN project#AstGenerated::Function_::getKwarg_dispred#ff AS L WITH ObjectAPI::CallableValue::getScope_dispred#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1>, L.<0> 19175 ~4% {3} r2 = JOIN r1 WITH DataFlowPrivate::ArgumentPassing::connects#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1>, r1.<1>, r1.<0> 7819 ~2% {4} r3 = JOIN r2 WITH Flow::CallNode::getArgByName_dispred#fff AS R ON FIRST 1 OUTPUT r2.<1>, r2.<2>, r2.<0>, R.<1> 7114 ~1% {4} r4 = r3 AND NOT Function::Function::getArgByName_dispred#fff_01#antijoin_rhs AS R(r3.<0>, r3.<3>) 7114 ~76% {2} r5 = SCAN r4 OUTPUT r4.<2>, r4.<1> 1123 ~0% {1} r6 = JOIN project#Exprs::Call::getKwargs_dispred#ff AS L WITH py_flow_bb_node_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1> 574 ~0% {2} r7 = JOIN r6 WITH DataFlowPrivate::ArgumentPassing::connects#ff AS R ON FIRST 1 OUTPUT R.<1>, r6.<0> 524 ~1% {3} r8 = JOIN r7 WITH ObjectAPI::CallableValue::getScope_dispred#ff AS R ON FIRST 1 OUTPUT R.<1>, r7.<1>, r7.<0> 291 ~0% {2} r9 = JOIN r8 WITH project#AstGenerated::Function_::getKwarg_dispred#ff AS R ON FIRST 1 OUTPUT r8.<1>, r8.<2> 7405 ~72% {2} r10 = r5 \/ r9 return r10 --- .../ql/src/experimental/dataflow/internal/DataFlowPrivate.qll | 2 +- python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll b/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll index e1d111753b9..fbfc4bdb5e2 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll @@ -292,7 +292,7 @@ private Node update(Node node) { * `y`. There is a dataflow step from `**{"y": 1, "a": 3}` to `[**d]` to transfer the content and * a clearing of content at key `y` for node `[**d]`, since that value has been unpacked. */ -private module ArgumentPassing { +module ArgumentPassing { /** * Holds if `call` represents a `DataFlowCall` to a `DataFlowCallable` represented by `callable`. * diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll b/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll index 10d489953ce..e0c6248b590 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll @@ -49,6 +49,7 @@ newtype TNode = TKwOverflowNode(CallNode call, CallableValue callable) { exists(getKeywordOverflowArg(call, callable, _)) or + ArgumentPassing::connects(call, callable) and exists(call.getNode().getKwargs()) and callable.getScope().hasKwArg() } or