From b32a8c2489671b9bd23b221eda3ecda54a832f06 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 10 Jul 2025 15:47:23 +0200 Subject: [PATCH 1/3] C++: Add dataflow predicate for checking if a node is the final value of a parameter --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 21 ++++++++++++++++++- .../dataflow-tests/has-parameter-flow-out.ql | 9 ++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index c72614ac5c32..635fe68c308c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -488,6 +488,25 @@ class Node extends TIRDataFlowNode { result = this.(IndirectParameterNode).getParameter() } + /** + * Holds of this node represents the `indirectionIndex`'th indirection of + * the value of an output parameter `p` just before reaching the end of a function. + */ + predicate isFinalValueOfParameter(Parameter p, int indirectionIndex) { + exists(FinalParameterNode n | n = this | + p = n.getParameter() and + indirectionIndex = n.getIndirectionIndex() + ) + } + + /** + * Holds of this node represents the value of an output parameter `p` + * just before reaching the end of a function. + */ + predicate isFinalValueOfParameter(Parameter p) { + this.isFinalValueOfParameter(p, _) + } + /** * Gets the variable corresponding to this node, if any. This can be used for * modeling flow in and out of global variables. @@ -1225,7 +1244,7 @@ import RawIndirectNodes /** * INTERNAL: do not use. * - * A node representing the value of an update parameter + * A node representing the value of an output parameter * just before reaching the end of a function. */ class FinalParameterNode extends Node, TFinalParameterNode { diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/has-parameter-flow-out.ql b/cpp/ql/test/library-tests/dataflow/dataflow-tests/has-parameter-flow-out.ql index 34afffd8e589..8f534be558d7 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/has-parameter-flow-out.ql +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/has-parameter-flow-out.ql @@ -24,10 +24,9 @@ module AstTest { module IRTest { private import semmle.code.cpp.ir.dataflow.DataFlow - private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil private string stars(int k) { - k = [0 .. max(FinalParameterNode n | | n.getIndirectionIndex())] and + k = [0 .. max(DataFlow::Node n, int i | n.isFinalValueOfParameter(_, i) | i)] and (if k = 0 then result = "" else result = "*" + stars(k - 1)) } @@ -35,14 +34,14 @@ module IRTest { string getARelevantTag() { result = "ir-def" } predicate hasActualResult(Location location, string element, string tag, string value) { - exists(Function f, Parameter p, FinalParameterNode n | + exists(Function f, Parameter p, DataFlow::Node n, int i | p.isNamed() and - n.getParameter() = p and + n.isFinalValueOfParameter(p, i) and n.getFunction() = f and location = f.getLocation() and element = p.toString() and tag = "ir-def" and - value = stars(n.getIndirectionIndex()) + p.getName() + value = stars(i) + p.getName() ) } } From 214969feaf02cd44c738d72407c0e04d6ea58300 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 10 Jul 2025 15:52:27 +0200 Subject: [PATCH 2/3] C++: Add change note --- cpp/ql/lib/change-notes/2025-07-10-final.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cpp/ql/lib/change-notes/2025-07-10-final.md diff --git a/cpp/ql/lib/change-notes/2025-07-10-final.md b/cpp/ql/lib/change-notes/2025-07-10-final.md new file mode 100644 index 000000000000..8e6b3dba2662 --- /dev/null +++ b/cpp/ql/lib/change-notes/2025-07-10-final.md @@ -0,0 +1,4 @@ +--- +category: feature +--- +* Added a `isFinalValueOfParameter` predicate to DataFlow::Node which holds when a dataflow node represents the final value of an output parameter of a function. From 96c379a076e92e9793bf2b4c1942672719207ba6 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 10 Jul 2025 15:56:11 +0200 Subject: [PATCH 3/3] C++: Fix formatting and typo --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 635fe68c308c..38a4d827a4da 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -489,7 +489,7 @@ class Node extends TIRDataFlowNode { } /** - * Holds of this node represents the `indirectionIndex`'th indirection of + * Holds if this node represents the `indirectionIndex`'th indirection of * the value of an output parameter `p` just before reaching the end of a function. */ predicate isFinalValueOfParameter(Parameter p, int indirectionIndex) { @@ -500,12 +500,10 @@ class Node extends TIRDataFlowNode { } /** - * Holds of this node represents the value of an output parameter `p` + * Holds if this node represents the value of an output parameter `p` * just before reaching the end of a function. */ - predicate isFinalValueOfParameter(Parameter p) { - this.isFinalValueOfParameter(p, _) - } + predicate isFinalValueOfParameter(Parameter p) { this.isFinalValueOfParameter(p, _) } /** * Gets the variable corresponding to this node, if any. This can be used for