From b447a9e314794a5c96005c39e978925f66aae735 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 12 Nov 2026 14:22:42 +0100 Subject: [PATCH 1/2] C++: Add test with duplicated 'asExpr' results. --- cpp/ql/test/library-tests/dataflow/asExpr/test.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cpp/ql/test/library-tests/dataflow/asExpr/test.cpp b/cpp/ql/test/library-tests/dataflow/asExpr/test.cpp index 8df12588fa59..a14912d19c8d 100644 --- a/cpp/ql/test/library-tests/dataflow/asExpr/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/asExpr/test.cpp @@ -55,3 +55,12 @@ void test_postfix_crement(int *p, int q) { int *p2 = (int*)(p++); // $ asExpr="... ++" asIndirectExpr="... ++" asExpr="p(... ++)" asIndirectExpr="p(*... ++)" int q2 = (int)(q++); // $ asExpr="... ++" asExpr="q(... ++)" } + +struct C { + C(); +}; + +void test_constructor_calls() { + C c; // $ asExpr="call to C" numberOfNodes="call to C: 2" + C *p = new C; // $ asExpr="call to C" asExpr=new asIndirectExpr=new numberOfNodes="call to C: 2" +} From aed02aab77344d31ca8becd8c1c7e47054cd268d Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 12 Nov 2026 14:24:25 +0100 Subject: [PATCH 2/2] C++: Make sure 'asExpr' only has a result for the 'PostUpdateNode' when the indirection index is 1. Previously, it would also have a result for indirection idnex 0. --- cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ExprNodes.qll | 4 +++- cpp/ql/test/library-tests/dataflow/asExpr/test.cpp | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ExprNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ExprNodes.qll index 927d2ea90288..bc433942506b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ExprNodes.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ExprNodes.qll @@ -263,7 +263,9 @@ private module Cached { exists(CallInstruction call | call.getStaticCallTarget() instanceof Constructor and e = getConvertedResultExpression(call, n) and - call.getThisArgumentOperand() = node.getAddressOperand() + call.getThisArgumentOperand() = node.getAddressOperand() and + // Indirection index 0 is the `this` pointer, and 1 is the constructed object + node.getIndirectionIndex() = 1 ) } diff --git a/cpp/ql/test/library-tests/dataflow/asExpr/test.cpp b/cpp/ql/test/library-tests/dataflow/asExpr/test.cpp index a14912d19c8d..56cbfa3a8151 100644 --- a/cpp/ql/test/library-tests/dataflow/asExpr/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/asExpr/test.cpp @@ -61,6 +61,6 @@ struct C { }; void test_constructor_calls() { - C c; // $ asExpr="call to C" numberOfNodes="call to C: 2" - C *p = new C; // $ asExpr="call to C" asExpr=new asIndirectExpr=new numberOfNodes="call to C: 2" + C c; // $ asExpr="call to C" + C *p = new C; // $ asExpr="call to C" asExpr=new asIndirectExpr=new }