diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected index eb9e8efb1d2d..e5c884beb225 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -139,3 +138,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected index 58049de095de..0f39caf8a712 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -32,3 +31,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected index e8f54d3d7bae..c2a3a9427c21 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected @@ -10,7 +10,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -192,3 +191,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected index b1acebfde5b8..72818427b846 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -53,3 +52,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected index 601496e15967..c059aed52eed 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected @@ -16,7 +16,6 @@ uniqueNodeLocation missingLocation | Nodes without location: 2 | uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -98,3 +97,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected index eb1472ebfaa9..f3c6737ad169 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected @@ -5,8 +5,6 @@ uniqueNodeLocation missingLocation uniqueNodeToString | cpp11.cpp:50:15:50:16 | (no string representation) | Node should have one toString but has 0. | -missingToString -| Nodes without toString: 1 | parameterCallable localFlowIsLocal readStepIsLocal @@ -54,3 +52,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/csharp/ql/consistency-queries/DataFlowConsistency.ql b/csharp/ql/consistency-queries/DataFlowConsistency.ql index 3fcda2109619..e1eb8b15a56a 100644 --- a/csharp/ql/consistency-queries/DataFlowConsistency.ql +++ b/csharp/ql/consistency-queries/DataFlowConsistency.ql @@ -72,11 +72,44 @@ private module Input implements InputSig { } predicate reverseReadExclude(Node n) { n.asExpr() = any(AwaitExpr ae).getExpr() } -} -import MakeConsistency + predicate missingArgumentCallExclude(ArgumentNode arg) { + // TODO: Remove once object initializers are modeled properly + arg.(Private::PostUpdateNodes::ObjectInitializerNode).getInitializer() instanceof + ObjectInitializer + or + // TODO: Remove once underlying issue is fixed + exists(QualifiableExpr qe | + qe.isConditional() and + qe.getQualifier() = arg.asExpr() + ) + } -query predicate multipleToString(DataFlow::Node n, string s) { - s = strictconcat(n.toString(), ",") and - strictcount(n.toString()) > 1 + predicate multipleArgumentCallExclude(ArgumentNode arg, DataFlowCall call) { + isArgumentNode(arg, call, _) and + ( + // TODO: Remove once object initializers are modeled properly + arg = + any(Private::PostUpdateNodes::ObjectInitializerNode init | + init.argumentOf(call, _) and + init.getInitializer().getNumberOfChildren() > 1 + ) + or + exists(ControlFlow::Nodes::ElementNode cfn, ControlFlow::Nodes::Split split | + exists(arg.asExprAtNode(cfn)) + | + split = cfn.getASplit() and + not split = call.getControlFlowNode().getASplit() + or + split = call.getControlFlowNode().getASplit() and + not split = cfn.getASplit() + ) + or + call instanceof TransitiveCapturedDataFlowCall + or + call.(NonDelegateDataFlowCall).getDispatchCall().isReflection() + ) + } } + +import MakeConsistency diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index e2ee1a0f13be..dd8438900bde 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -2032,7 +2032,7 @@ abstract class PostUpdateNode extends Node { abstract Node getPreUpdateNode(); } -private module PostUpdateNodes { +module PostUpdateNodes { class ObjectCreationNode extends PostUpdateNode, ExprNode, TExprNode { private ObjectCreation oc; diff --git a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll index 44d23fb9d3f5..e13fbd882b99 100644 --- a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll +++ b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll @@ -50,6 +50,9 @@ class DispatchCall extends Internal::TDispatchCall { RuntimeCallable getADynamicTargetInCallContext(DispatchCall ctx) { result = Internal::getADynamicTargetInCallContext(this, ctx) } + + /** Holds if this call uses reflection. */ + predicate isReflection() { this instanceof Internal::TDispatchReflectionCall } } /** Internal implementation details. */ diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll index 2513a4aa3bd4..0595cbf7d3f7 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll @@ -47,6 +47,10 @@ private module Input implements InputSig { predicate identityLocalStepExclude(Node n) { not exists(n.getLocation().getFile().getRelativePath()) } + + predicate multipleArgumentCallExclude(ArgumentNode arg, DataFlowCall call) { + isArgumentNode(arg, call, _) + } } module Consistency = MakeConsistency; diff --git a/python/ql/test/experimental/dataflow/basic/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/basic/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/basic/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/basic/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/callgraph_crosstalk/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/callgraph_crosstalk/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/callgraph_crosstalk/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/callgraph_crosstalk/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/calls/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/calls/dataflow-consistency.expected index 1ca0f0cffd75..bf226e7fe62c 100644 --- a/python/ql/test/experimental/dataflow/calls/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/calls/dataflow-consistency.expected @@ -8,7 +8,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -28,3 +27,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/coverage/dataflow-consistency.expected index f4f02139bcd8..8e733266f662 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow-consistency.expected @@ -6,7 +6,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -39,3 +38,5 @@ identityLocalStep | test.py:678:9:678:12 | ControlFlowNode for SINK | Node steps to itself | | test.py:686:9:686:12 | ControlFlowNode for SINK | Node steps to itself | | test.py:692:5:692:8 | ControlFlowNode for SINK | Node steps to itself | +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/exceptions/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/exceptions/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/exceptions/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/exceptions/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/fieldflow/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/fieldflow/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/fieldflow/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/global-flow/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/global-flow/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/global-flow/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/global-flow/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/match/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/match/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/match/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/match/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/pep_328/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/pep_328/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/pep_328/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/pep_328/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/regression/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/regression/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/regression/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/regression/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/strange-essaflow/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/strange-essaflow/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/strange-essaflow/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/strange-essaflow/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/tainttracking/basic/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/tainttracking/basic/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/basic/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/tainttracking/basic/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/tainttracking/commonSanitizer/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/tainttracking/commonSanitizer/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/commonSanitizer/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/tainttracking/commonSanitizer/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/tainttracking/customSanitizer/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/tainttracking/customSanitizer/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/customSanitizer/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/tainttracking/customSanitizer/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/dataflow-consistency.expected index 0e4146fbce3f..e198873229aa 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -26,3 +25,5 @@ uniqueContentApprox identityLocalStep | test_collections.py:20:9:20:22 | ControlFlowNode for ensure_tainted | Node steps to itself | | test_unpacking.py:31:9:31:22 | ControlFlowNode for ensure_tainted | Node steps to itself | +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/dataflow-consistency.expected index d6c0a2a32b29..dab4b6d91459 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -39,3 +38,5 @@ identityLocalStep | test_collections.py:246:9:246:15 | ControlFlowNode for my_dict | Node steps to itself | | test_collections.py:246:22:246:33 | ControlFlowNode for tainted_dict | Node steps to itself | | test_for.py:24:9:24:22 | ControlFlowNode for ensure_tainted | Node steps to itself | +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/tainttracking/generator-flow/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/generator-flow/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/tainttracking/generator-flow/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/tainttracking/unwanted-global-flow/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/tainttracking/unwanted-global-flow/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/unwanted-global-flow/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/tainttracking/unwanted-global-flow/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/typetracking/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/typetracking/dataflow-consistency.expected index 2c0788860a40..e4f849ac82ba 100644 --- a/python/ql/test/experimental/dataflow/typetracking/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/typetracking/dataflow-consistency.expected @@ -4,7 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -24,3 +23,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/dataflow/variable-capture/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/variable-capture/dataflow-consistency.expected index 5eb623d991af..0cf885ef90e3 100644 --- a/python/ql/test/experimental/dataflow/variable-capture/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/variable-capture/dataflow-consistency.expected @@ -10,7 +10,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -33,3 +32,5 @@ identityLocalStep | test_collections.py:36:10:36:15 | ControlFlowNode for SOURCE | Node steps to itself | | test_collections.py:45:19:45:21 | ControlFlowNode for mod | Node steps to itself | | test_collections.py:52:13:52:21 | ControlFlowNode for mod_local | Node steps to itself | +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/experimental/library-tests/CallGraph/dataflow-consistency.expected b/python/ql/test/experimental/library-tests/CallGraph/dataflow-consistency.expected index 38fe9d04b694..cc45fe572389 100644 --- a/python/ql/test/experimental/library-tests/CallGraph/dataflow-consistency.expected +++ b/python/ql/test/experimental/library-tests/CallGraph/dataflow-consistency.expected @@ -35,7 +35,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -55,3 +54,5 @@ uniqueParameterNodeAtPosition uniqueParameterNodePosition uniqueContentApprox identityLocalStep +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/library-tests/ApiGraphs/py3/dataflow-consistency.expected b/python/ql/test/library-tests/ApiGraphs/py3/dataflow-consistency.expected index 3294938ee619..8ae8a2c21f9f 100644 --- a/python/ql/test/library-tests/ApiGraphs/py3/dataflow-consistency.expected +++ b/python/ql/test/library-tests/ApiGraphs/py3/dataflow-consistency.expected @@ -8,7 +8,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -30,3 +29,5 @@ uniqueContentApprox identityLocalStep | test_captured.py:7:22:7:22 | ControlFlowNode for p | Node steps to itself | | test_captured.py:14:26:14:27 | ControlFlowNode for pp | Node steps to itself | +missingArgumentCall +multipleArgumentCall diff --git a/python/ql/test/library-tests/frameworks/django-orm/dataflow-consistency.expected b/python/ql/test/library-tests/frameworks/django-orm/dataflow-consistency.expected index 424326355d31..7a09be9893d2 100644 --- a/python/ql/test/library-tests/frameworks/django-orm/dataflow-consistency.expected +++ b/python/ql/test/library-tests/frameworks/django-orm/dataflow-consistency.expected @@ -39,7 +39,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -missingToString parameterCallable localFlowIsLocal readStepIsLocal @@ -125,3 +124,5 @@ identityLocalStep | testapp/tests.py:16:9:16:18 | ControlFlowNode for test_names | Node steps to itself | | testapp/tests.py:25:13:25:14 | ControlFlowNode for re | Node steps to itself | | testapp/tests.py:31:9:31:18 | ControlFlowNode for test_names | Node steps to itself | +missingArgumentCall +multipleArgumentCall diff --git a/ruby/ql/consistency-queries/DataFlowConsistency.ql b/ruby/ql/consistency-queries/DataFlowConsistency.ql index 6cf0fe9a2826..b7e7e8cad6a6 100644 --- a/ruby/ql/consistency-queries/DataFlowConsistency.ql +++ b/ruby/ql/consistency-queries/DataFlowConsistency.ql @@ -35,11 +35,17 @@ private module Input implements InputSig { n.asExpr() = arg ) } + + predicate multipleArgumentCallExclude(ArgumentNode arg, DataFlowCall call) { + // An argument such as `x` in `if not x then ...` has two successors (and hence + // two calls); one for each Boolean outcome of `x`. + exists(CfgNodes::ExprCfgNode n | + arg.argumentOf(call, _) and + n = call.asCall() and + arg.asExpr().getASuccessor(any(SuccessorTypes::ConditionalSuccessor c)).getASuccessor*() = n and + n.getASplit() instanceof Split::ConditionalCompletionSplit + ) + } } import MakeConsistency - -query predicate multipleToString(DataFlow::Node n, string s) { - s = strictconcat(n.toString(), ",") and - strictcount(n.toString()) > 1 -} diff --git a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll index 1a8c6bcc6079..f91f5a45ed2a 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll @@ -7,7 +7,6 @@ private import codeql.ruby.ast.internal.Constant private import codeql.ruby.ast.internal.Literal private import ControlFlowGraph private import internal.ControlFlowGraphImpl as CfgImpl -private import internal.Splitting /** An entry node for a given scope. */ class EntryNode extends CfgNode, CfgImpl::EntryNode { diff --git a/ruby/ql/lib/codeql/ruby/controlflow/ControlFlowGraph.qll b/ruby/ql/lib/codeql/ruby/controlflow/ControlFlowGraph.qll index 3ff85f5553d6..67f0f6557942 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/ControlFlowGraph.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/ControlFlowGraph.qll @@ -4,7 +4,7 @@ private import codeql.ruby.AST private import codeql.ruby.controlflow.BasicBlocks private import SuccessorTypes private import internal.ControlFlowGraphImpl as CfgImpl -private import internal.Splitting +private import internal.Splitting as Splitting private import internal.Completion /** @@ -293,3 +293,10 @@ module SuccessorTypes { final override string toString() { result = "exit" } } } + +class Split = Splitting::Split; + +/** Provides different kinds of control flow graph splittings. */ +module Split { + class ConditionalCompletionSplit = Splitting::ConditionalCompletionSplit; +} diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/Splitting.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/Splitting.qll index e5b4036d054a..d8cfb9230d8b 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/Splitting.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/Splitting.qll @@ -115,6 +115,8 @@ private module ConditionalCompletionSplitting { } } +class ConditionalCompletionSplit = ConditionalCompletionSplitting::ConditionalCompletionSplit; + module EnsureSplitting { /** * The type of a split `ensure` node. diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImplConsistency.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImplConsistency.qll index a24f8ab794a6..a744f57b4b4a 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImplConsistency.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImplConsistency.qll @@ -58,6 +58,16 @@ signature module InputSig { /** Holds if `n` should be excluded from the consistency test `identityLocalStep`. */ default predicate identityLocalStepExclude(DataFlowLang::Node n) { none() } + + /** Holds if `arg` should be excluded from the consistency test `missingArgumentCall`. */ + default predicate missingArgumentCallExclude(DataFlowLang::ArgumentNode arg) { none() } + + /** Holds if `(arg, call)` should be excluded from the consistency test `multipleArgumentCall`. */ + default predicate multipleArgumentCallExclude( + DataFlowLang::ArgumentNode arg, DataFlowLang::DataFlowCall call + ) { + none() + } } module MakeConsistency< @@ -147,13 +157,6 @@ module MakeConsistency< ) } - query predicate missingToString(string msg) { - exists(int c | - c = strictcount(Node n | not exists(n.toString())) and - msg = "Nodes without toString: " + c - ) - } - query predicate parameterCallable(ParameterNode p, string msg) { exists(DataFlowCallable c | isParameterNode(p, c, _) and c != nodeGetEnclosingCallable(p)) and msg = "Callable mismatch for parameter." @@ -287,4 +290,20 @@ module MakeConsistency< not Input::identityLocalStepExclude(n) and msg = "Node steps to itself" } + + query predicate missingArgumentCall(ArgumentNode arg, string msg) { + not Input::missingArgumentCallExclude(arg) and + not isArgumentNode(arg, _, _) and + msg = "Missing call for argument node." + } + + query predicate multipleArgumentCall(ArgumentNode arg, DataFlowCall call, string msg) { + isArgumentNode(arg, call, _) and + not Input::multipleArgumentCallExclude(arg, call) and + strictcount(DataFlowCall call0 | + isArgumentNode(arg, call0, _) and + not Input::multipleArgumentCallExclude(arg, call0) + ) > 1 and + msg = "Multiple calls for argument node." + } }