From c6df9505c0589499f0027e718cb2d0c60278eeda Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 15 May 2025 15:05:17 +0100 Subject: [PATCH 1/4] C++: Add tests to exercise the upcoming behavior of function dispatch when there are model-generated summaries AND source definitions. --- .../dataflow/external-models/flow.expected | 75 ++++++++++++++----- .../dataflow/external-models/flow.ext.yml | 5 +- .../dataflow/external-models/sinks.expected | 11 ++- .../dataflow/external-models/sources.expected | 2 +- .../dataflow/external-models/steps.expected | 7 +- .../dataflow/external-models/steps.ext.yml | 5 +- .../dataflow/external-models/test.cpp | 27 ++++++- 7 files changed, 104 insertions(+), 28 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/external-models/flow.expected b/cpp/ql/test/library-tests/dataflow/external-models/flow.expected index 3a87f947742b..2b2f0dcdf0c7 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/flow.expected +++ b/cpp/ql/test/library-tests/dataflow/external-models/flow.expected @@ -10,14 +10,32 @@ edges | asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:6 | | asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | | | asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:10 | -| test.cpp:4:5:4:11 | [summary param] 0 in ymlStep | test.cpp:4:5:4:11 | [summary] to write: ReturnValue in ymlStep | provenance | MaD:969 | -| test.cpp:7:10:7:18 | call to ymlSource | test.cpp:7:10:7:18 | call to ymlSource | provenance | Src:MaD:967 | -| test.cpp:7:10:7:18 | call to ymlSource | test.cpp:11:10:11:10 | x | provenance | Sink:MaD:968 | -| test.cpp:7:10:7:18 | call to ymlSource | test.cpp:13:18:13:18 | x | provenance | | -| test.cpp:13:10:13:16 | call to ymlStep | test.cpp:13:10:13:16 | call to ymlStep | provenance | | -| test.cpp:13:10:13:16 | call to ymlStep | test.cpp:15:10:15:10 | y | provenance | Sink:MaD:968 | -| test.cpp:13:18:13:18 | x | test.cpp:4:5:4:11 | [summary param] 0 in ymlStep | provenance | | -| test.cpp:13:18:13:18 | x | test.cpp:13:10:13:16 | call to ymlStep | provenance | MaD:969 | +| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:969 | +| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:970 | +| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:971 | +| test.cpp:7:5:7:30 | [summary param] 0 in ymlStepGenerated_with_body | test.cpp:7:5:7:30 | [summary] to write: ReturnValue in ymlStepGenerated_with_body | provenance | MaD:972 | +| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:10:10:10:18 | call to ymlSource | provenance | Src:MaD:967 | +| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:14:10:14:10 | x | provenance | Sink:MaD:968 | +| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:17:24:17:24 | x | provenance | | +| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:21:27:21:27 | x | provenance | | +| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:25:35:25:35 | x | provenance | | +| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:35:38:35:38 | x | provenance | | +| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | | +| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:18:10:18:10 | y | provenance | Sink:MaD:968 | +| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | provenance | | +| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:969 | +| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | | +| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:22:10:22:10 | z | provenance | Sink:MaD:968 | +| test.cpp:21:27:21:27 | x | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | provenance | | +| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:970 | +| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | | +| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:26:10:26:11 | y2 | provenance | Sink:MaD:968 | +| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | provenance | | +| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:971 | +| test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body | test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body | provenance | | +| test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body | test.cpp:36:10:36:11 | z3 | provenance | Sink:MaD:968 | +| test.cpp:35:38:35:38 | x | test.cpp:7:5:7:30 | [summary param] 0 in ymlStepGenerated_with_body | provenance | | +| test.cpp:35:38:35:38 | x | test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body | provenance | MaD:972 | nodes | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | semmle.label | [summary param] *0 in buffer | | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | semmle.label | [summary] to write: ReturnValue in buffer | @@ -31,15 +49,36 @@ nodes | asio_streams.cpp:100:64:100:71 | *send_str | semmle.label | *send_str | | asio_streams.cpp:101:7:101:17 | send_buffer | semmle.label | send_buffer | | asio_streams.cpp:103:29:103:39 | *send_buffer | semmle.label | *send_buffer | -| test.cpp:4:5:4:11 | [summary param] 0 in ymlStep | semmle.label | [summary param] 0 in ymlStep | -| test.cpp:4:5:4:11 | [summary] to write: ReturnValue in ymlStep | semmle.label | [summary] to write: ReturnValue in ymlStep | -| test.cpp:7:10:7:18 | call to ymlSource | semmle.label | call to ymlSource | -| test.cpp:7:10:7:18 | call to ymlSource | semmle.label | call to ymlSource | -| test.cpp:11:10:11:10 | x | semmle.label | x | -| test.cpp:13:10:13:16 | call to ymlStep | semmle.label | call to ymlStep | -| test.cpp:13:10:13:16 | call to ymlStep | semmle.label | call to ymlStep | -| test.cpp:13:18:13:18 | x | semmle.label | x | -| test.cpp:15:10:15:10 | y | semmle.label | y | +| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | semmle.label | [summary param] 0 in ymlStepManual | +| test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | semmle.label | [summary] to write: ReturnValue in ymlStepManual | +| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | semmle.label | [summary param] 0 in ymlStepGenerated | +| test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | semmle.label | [summary] to write: ReturnValue in ymlStepGenerated | +| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | semmle.label | [summary param] 0 in ymlStepManual_with_body | +| test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | semmle.label | [summary] to write: ReturnValue in ymlStepManual_with_body | +| test.cpp:7:5:7:30 | [summary param] 0 in ymlStepGenerated_with_body | semmle.label | [summary param] 0 in ymlStepGenerated_with_body | +| test.cpp:7:5:7:30 | [summary] to write: ReturnValue in ymlStepGenerated_with_body | semmle.label | [summary] to write: ReturnValue in ymlStepGenerated_with_body | +| test.cpp:10:10:10:18 | call to ymlSource | semmle.label | call to ymlSource | +| test.cpp:10:10:10:18 | call to ymlSource | semmle.label | call to ymlSource | +| test.cpp:14:10:14:10 | x | semmle.label | x | +| test.cpp:17:10:17:22 | call to ymlStepManual | semmle.label | call to ymlStepManual | +| test.cpp:17:10:17:22 | call to ymlStepManual | semmle.label | call to ymlStepManual | +| test.cpp:17:24:17:24 | x | semmle.label | x | +| test.cpp:18:10:18:10 | y | semmle.label | y | +| test.cpp:21:10:21:25 | call to ymlStepGenerated | semmle.label | call to ymlStepGenerated | +| test.cpp:21:10:21:25 | call to ymlStepGenerated | semmle.label | call to ymlStepGenerated | +| test.cpp:21:27:21:27 | x | semmle.label | x | +| test.cpp:22:10:22:10 | z | semmle.label | z | +| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | semmle.label | call to ymlStepManual_with_body | +| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | semmle.label | call to ymlStepManual_with_body | +| test.cpp:25:35:25:35 | x | semmle.label | x | +| test.cpp:26:10:26:11 | y2 | semmle.label | y2 | +| test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body | semmle.label | call to ymlStepGenerated_with_body | +| test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body | semmle.label | call to ymlStepGenerated_with_body | +| test.cpp:35:38:35:38 | x | semmle.label | x | +| test.cpp:36:10:36:11 | z3 | semmle.label | z3 | subpaths | asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | asio_streams.cpp:100:44:100:62 | call to buffer | -| test.cpp:13:18:13:18 | x | test.cpp:4:5:4:11 | [summary param] 0 in ymlStep | test.cpp:4:5:4:11 | [summary] to write: ReturnValue in ymlStep | test.cpp:13:10:13:16 | call to ymlStep | +| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual | +| test.cpp:21:27:21:27 | x | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | test.cpp:21:10:21:25 | call to ymlStepGenerated | +| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | +| test.cpp:35:38:35:38 | x | test.cpp:7:5:7:30 | [summary param] 0 in ymlStepGenerated_with_body | test.cpp:7:5:7:30 | [summary] to write: ReturnValue in ymlStepGenerated_with_body | test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body | diff --git a/cpp/ql/test/library-tests/dataflow/external-models/flow.ext.yml b/cpp/ql/test/library-tests/dataflow/external-models/flow.ext.yml index 42ca51bc4248..12dbf7d4cd23 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/flow.ext.yml +++ b/cpp/ql/test/library-tests/dataflow/external-models/flow.ext.yml @@ -13,4 +13,7 @@ extensions: pack: codeql/cpp-all extensible: summaryModel data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance - - ["", "", False, "ymlStep", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] \ No newline at end of file + - ["", "", False, "ymlStepManual", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["", "", False, "ymlStepGenerated", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["", "", False, "ymlStepManual_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["", "", False, "ymlStepGenerated_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"] \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected b/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected index 392c0bc03c1a..2c2338a7dcc6 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected +++ b/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected @@ -1,5 +1,10 @@ | asio_streams.cpp:93:29:93:39 | *recv_buffer | remote-sink | | asio_streams.cpp:103:29:103:39 | *send_buffer | remote-sink | -| test.cpp:9:10:9:10 | 0 | test-sink | -| test.cpp:11:10:11:10 | x | test-sink | -| test.cpp:15:10:15:10 | y | test-sink | +| test.cpp:12:10:12:10 | 0 | test-sink | +| test.cpp:14:10:14:10 | x | test-sink | +| test.cpp:18:10:18:10 | y | test-sink | +| test.cpp:22:10:22:10 | z | test-sink | +| test.cpp:26:10:26:11 | y2 | test-sink | +| test.cpp:29:10:29:11 | y3 | test-sink | +| test.cpp:33:10:33:11 | z2 | test-sink | +| test.cpp:36:10:36:11 | z3 | test-sink | diff --git a/cpp/ql/test/library-tests/dataflow/external-models/sources.expected b/cpp/ql/test/library-tests/dataflow/external-models/sources.expected index aa85e74fc034..3e71025e7ff1 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/sources.expected +++ b/cpp/ql/test/library-tests/dataflow/external-models/sources.expected @@ -1,2 +1,2 @@ | asio_streams.cpp:87:34:87:44 | read_until output argument | remote | -| test.cpp:7:10:7:18 | call to ymlSource | local | +| test.cpp:10:10:10:18 | call to ymlSource | local | diff --git a/cpp/ql/test/library-tests/dataflow/external-models/steps.expected b/cpp/ql/test/library-tests/dataflow/external-models/steps.expected index 2bc7fb6b49aa..aab2691cda1e 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/steps.expected +++ b/cpp/ql/test/library-tests/dataflow/external-models/steps.expected @@ -1,2 +1,7 @@ | asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | -| test.cpp:13:18:13:18 | x | test.cpp:13:10:13:16 | call to ymlStep | +| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | +| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | +| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | +| test.cpp:28:35:28:35 | 0 | test.cpp:28:11:28:33 | call to ymlStepManual_with_body | +| test.cpp:32:38:32:38 | 0 | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | +| test.cpp:35:38:35:38 | x | test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body | diff --git a/cpp/ql/test/library-tests/dataflow/external-models/steps.ext.yml b/cpp/ql/test/library-tests/dataflow/external-models/steps.ext.yml index c8a195b7aa6e..da9448b8e8f1 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/steps.ext.yml +++ b/cpp/ql/test/library-tests/dataflow/external-models/steps.ext.yml @@ -3,4 +3,7 @@ extensions: pack: codeql/cpp-all extensible: summaryModel data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance - - ["", "", False, "ymlStep", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["", "", False, "ymlStepManual", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["", "", False, "ymlStepGenerated", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["", "", False, "ymlStepManual_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["", "", False, "ymlStepGenerated_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"] diff --git a/cpp/ql/test/library-tests/dataflow/external-models/test.cpp b/cpp/ql/test/library-tests/dataflow/external-models/test.cpp index aa50f6715f21..b443b368b017 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/external-models/test.cpp @@ -1,7 +1,10 @@ int ymlSource(); void ymlSink(int value); -int ymlStep(int value); +int ymlStepManual(int value); +int ymlStepGenerated(int value); +int ymlStepManual_with_body(int value1, int value2) { return value2; } +int ymlStepGenerated_with_body(int value, int value2) { return value2; } void test() { int x = ymlSource(); @@ -10,7 +13,25 @@ void test() { ymlSink(x); // $ ir - int y = ymlStep(x); - + // ymlStepManual is manually modeled so we should always use the model + int y = ymlStepManual(x); ymlSink(y); // $ ir + + // ymlStepGenerated is modeled by the model generator so we should use the model only if there is no body + int z = ymlStepGenerated(x); + ymlSink(z); // $ ir + + // ymlStepManual_with_body is manually modeled so we should always use the model + int y2 = ymlStepManual_with_body(x, 0); + ymlSink(y2); // $ ir + + int y3 = ymlStepManual_with_body(0, x); + ymlSink(y3); // clean + + // ymlStepGenerated_with_body is modeled by the model generator so we should use the model only if there is no body + int z2 = ymlStepGenerated_with_body(0, x); + ymlSink(z2); // $ MISSING: ir + + int z3 = ymlStepGenerated_with_body(x, 0); + ymlSink(z3); // $ SPURIOUS: ir } From 69a1a87aa40a70ecbd4351aa14b4e26e3fe96225 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 15 May 2025 15:25:29 +0100 Subject: [PATCH 2/4] C++: Update semantics of picking the static call target in dataflow. --- .../ir/dataflow/internal/DataFlowPrivate.qll | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index e517a75edf97..f0a0fd7cdb39 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -1164,15 +1164,27 @@ class DataFlowCall extends TDataFlowCall { Function getStaticCallSourceTarget() { none() } /** - * Gets the target of this call. If a summarized callable exists for the - * target this is chosen, and otherwise the callable is the implementation - * from the source code. + * Gets the target of this call. We use the following strategy for deciding + * between the source callable and a summarized callable: + * - If there is a manual summary then we always use the manual summary. + * - If there is a source callable and we only have generated summaries + * we use the source callable. + * - If there is no source callable then we use the summary regardless of + * whether is it manual or generated. */ - DataFlowCallable getStaticCallTarget() { + final DataFlowCallable getStaticCallTarget() { exists(Function target | target = this.getStaticCallSourceTarget() | - not exists(TSummarizedCallable(target)) and + // Don't use the source callable if there is a manual model for the + // target + not exists(SummarizedCallable sc | + sc.asSummarizedCallable() = target and + sc.asSummarizedCallable().applyManualModel() + ) and result.asSourceCallable() = target or + // When there is no function body, or when we have a manual model then + // we dispatch to the summary. + (not target.hasDefinition() or result.asSummarizedCallable().applyManualModel()) and result.asSummarizedCallable() = target ) } From e75dcd27f505b50e2bec14bec09f29a17c7b40af Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 15 May 2025 15:28:13 +0100 Subject: [PATCH 3/4] C++: Accept test changes. --- .../dataflow/external-models/flow.expected | 28 ++++++++++--------- .../dataflow/external-models/test.cpp | 4 +-- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/external-models/flow.expected b/cpp/ql/test/library-tests/dataflow/external-models/flow.expected index 2b2f0dcdf0c7..66709332e61a 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/flow.expected +++ b/cpp/ql/test/library-tests/dataflow/external-models/flow.expected @@ -13,13 +13,14 @@ edges | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:969 | | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:970 | | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:971 | -| test.cpp:7:5:7:30 | [summary param] 0 in ymlStepGenerated_with_body | test.cpp:7:5:7:30 | [summary] to write: ReturnValue in ymlStepGenerated_with_body | provenance | MaD:972 | +| test.cpp:7:47:7:52 | value2 | test.cpp:7:64:7:69 | value2 | provenance | | +| test.cpp:7:64:7:69 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | provenance | | | test.cpp:10:10:10:18 | call to ymlSource | test.cpp:10:10:10:18 | call to ymlSource | provenance | Src:MaD:967 | | test.cpp:10:10:10:18 | call to ymlSource | test.cpp:14:10:14:10 | x | provenance | Sink:MaD:968 | | test.cpp:10:10:10:18 | call to ymlSource | test.cpp:17:24:17:24 | x | provenance | | | test.cpp:10:10:10:18 | call to ymlSource | test.cpp:21:27:21:27 | x | provenance | | | test.cpp:10:10:10:18 | call to ymlSource | test.cpp:25:35:25:35 | x | provenance | | -| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:35:38:35:38 | x | provenance | | +| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:32:41:32:41 | x | provenance | | | test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | | | test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:18:10:18:10 | y | provenance | Sink:MaD:968 | | test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | provenance | | @@ -32,10 +33,10 @@ edges | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:26:10:26:11 | y2 | provenance | Sink:MaD:968 | | test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | provenance | | | test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:971 | -| test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body | test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body | provenance | | -| test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body | test.cpp:36:10:36:11 | z3 | provenance | Sink:MaD:968 | -| test.cpp:35:38:35:38 | x | test.cpp:7:5:7:30 | [summary param] 0 in ymlStepGenerated_with_body | provenance | | -| test.cpp:35:38:35:38 | x | test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body | provenance | MaD:972 | +| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | provenance | | +| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:33:10:33:11 | z2 | provenance | Sink:MaD:968 | +| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | provenance | | +| test.cpp:32:41:32:41 | x | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | provenance | | nodes | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | semmle.label | [summary param] *0 in buffer | | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | semmle.label | [summary] to write: ReturnValue in buffer | @@ -55,8 +56,9 @@ nodes | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | semmle.label | [summary] to write: ReturnValue in ymlStepGenerated | | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | semmle.label | [summary param] 0 in ymlStepManual_with_body | | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | semmle.label | [summary] to write: ReturnValue in ymlStepManual_with_body | -| test.cpp:7:5:7:30 | [summary param] 0 in ymlStepGenerated_with_body | semmle.label | [summary param] 0 in ymlStepGenerated_with_body | -| test.cpp:7:5:7:30 | [summary] to write: ReturnValue in ymlStepGenerated_with_body | semmle.label | [summary] to write: ReturnValue in ymlStepGenerated_with_body | +| test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | semmle.label | *ymlStepGenerated_with_body | +| test.cpp:7:47:7:52 | value2 | semmle.label | value2 | +| test.cpp:7:64:7:69 | value2 | semmle.label | value2 | | test.cpp:10:10:10:18 | call to ymlSource | semmle.label | call to ymlSource | | test.cpp:10:10:10:18 | call to ymlSource | semmle.label | call to ymlSource | | test.cpp:14:10:14:10 | x | semmle.label | x | @@ -72,13 +74,13 @@ nodes | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | semmle.label | call to ymlStepManual_with_body | | test.cpp:25:35:25:35 | x | semmle.label | x | | test.cpp:26:10:26:11 | y2 | semmle.label | y2 | -| test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body | semmle.label | call to ymlStepGenerated_with_body | -| test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body | semmle.label | call to ymlStepGenerated_with_body | -| test.cpp:35:38:35:38 | x | semmle.label | x | -| test.cpp:36:10:36:11 | z3 | semmle.label | z3 | +| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | semmle.label | call to ymlStepGenerated_with_body | +| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | semmle.label | call to ymlStepGenerated_with_body | +| test.cpp:32:41:32:41 | x | semmle.label | x | +| test.cpp:33:10:33:11 | z2 | semmle.label | z2 | subpaths | asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | asio_streams.cpp:100:44:100:62 | call to buffer | | test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual | | test.cpp:21:27:21:27 | x | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | test.cpp:21:10:21:25 | call to ymlStepGenerated | | test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | -| test.cpp:35:38:35:38 | x | test.cpp:7:5:7:30 | [summary param] 0 in ymlStepGenerated_with_body | test.cpp:7:5:7:30 | [summary] to write: ReturnValue in ymlStepGenerated_with_body | test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body | +| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | diff --git a/cpp/ql/test/library-tests/dataflow/external-models/test.cpp b/cpp/ql/test/library-tests/dataflow/external-models/test.cpp index b443b368b017..a0b12004074b 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/external-models/test.cpp @@ -30,8 +30,8 @@ void test() { // ymlStepGenerated_with_body is modeled by the model generator so we should use the model only if there is no body int z2 = ymlStepGenerated_with_body(0, x); - ymlSink(z2); // $ MISSING: ir + ymlSink(z2); // $ ir int z3 = ymlStepGenerated_with_body(x, 0); - ymlSink(z3); // $ SPURIOUS: ir + ymlSink(z3); // clean } From d31ddad832d8a451b3937a9a83103c9f8586e0f2 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 15 May 2025 18:04:57 +0100 Subject: [PATCH 4/4] C++: Small refactoring. --- .../code/cpp/ir/dataflow/internal/DataFlowPrivate.qll | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index f0a0fd7cdb39..073d7a4bbc9b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -1143,6 +1143,10 @@ private newtype TDataFlowCall = FlowSummaryImpl::Private::summaryCallbackRange(c, receiver) } +private predicate summarizedCallableIsManual(SummarizedCallable sc) { + sc.asSummarizedCallable().applyManualModel() +} + /** * A function call relevant for data flow. This includes calls from source * code and calls inside library callables with a flow summary. @@ -1178,13 +1182,13 @@ class DataFlowCall extends TDataFlowCall { // target not exists(SummarizedCallable sc | sc.asSummarizedCallable() = target and - sc.asSummarizedCallable().applyManualModel() + summarizedCallableIsManual(sc) ) and result.asSourceCallable() = target or // When there is no function body, or when we have a manual model then // we dispatch to the summary. - (not target.hasDefinition() or result.asSummarizedCallable().applyManualModel()) and + (not target.hasDefinition() or summarizedCallableIsManual(result)) and result.asSummarizedCallable() = target ) }