From c9e9322143f57b24f49d27bf33e0001765b4c093 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 24 Nov 2025 12:02:54 +0000 Subject: [PATCH 1/9] C++: Add an example of missing MaD supporrt for non-type template parameters. --- .../library-tests/dataflow/external-models/flow.ext.yml | 3 ++- .../dataflow/external-models/sinks.expected | 1 + .../dataflow/external-models/sources.expected | 1 + .../test/library-tests/dataflow/external-models/test.cpp | 9 +++++++++ 4 files changed, 13 insertions(+), 1 deletion(-) 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 f0df3e749e6..8e200aabfbd 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 @@ -17,4 +17,5 @@ extensions: - ["", "", 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"] - - ["", "", False, "callWithArgument", "", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"] \ No newline at end of file + - ["", "", False, "callWithArgument", "", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"] + - ["", "", False, "callWithNonTypeTemplate", "(const T &)", "", "Argument[*0]", "ReturnValue", "value", "manual"] \ 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 0cc01c8165e..51c2180f113 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected +++ b/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected @@ -13,3 +13,4 @@ | test.cpp:75:11:75:11 | y | test-sink | | test.cpp:83:11:83:11 | y | test-sink | | test.cpp:89:11:89:11 | y | test-sink | +| test.cpp:113:10:113:10 | y | 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 401fffdbd59..fc975299737 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/sources.expected +++ b/cpp/ql/test/library-tests/dataflow/external-models/sources.expected @@ -2,6 +2,7 @@ | test.cpp:10:10:10:18 | call to ymlSource | local | | test.cpp:56:8:56:16 | call to ymlSource | local | | test.cpp:94:10:94:18 | call to ymlSource | local | +| test.cpp:111:10:111:18 | call to ymlSource | local | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | local | | windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | local | | windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | local | 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 f357b934b2f..830cd8e081f 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/external-models/test.cpp @@ -102,4 +102,13 @@ void test_callWithArgument() { } callWithArgument(StructWithOperatorCall_has_constructor_2(), x); callWithArgument(StructWithOperatorCall_no_constructor_2(), x); +} + +template +T callWithNonTypeTemplate(const T&); + +void test_callWithNonTypeTemplate() { + int x = ymlSource(); + int y = callWithNonTypeTemplate<10, int>(x); + ymlSink(y); // $ MISSING: ir } \ No newline at end of file From 732e55df11e4776c83ad010ae5e7b12377d33b91 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 24 Nov 2025 12:06:24 +0000 Subject: [PATCH 2/9] C++: Ignore template non-type parameters in MaD signature matching. --- .../semmle/code/cpp/dataflow/ExternalFlow.qll | 51 +++++++++++++++---- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll index b71a46f6961..6c60296b56a 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll @@ -15,16 +15,17 @@ * reading. * 1. The `namespace` column selects a namespace. * 2. The `type` column selects a type within that namespace. This column can - * introduce template names that can be mentioned in the `signature` column. + * introduce template type names that can be mentioned in the `signature` column. * For example, `vector` introduces the template names `T` and - * `Allocator`. + * `Allocator`. Non-type template parameters cannot be specified. * 3. The `subtypes` is a boolean that indicates whether to jump to an * arbitrary subtype of that type. Set this to `false` if leaving the `type` * blank (for example, a free function). * 4. The `name` column optionally selects a specific named member of the type. - * Like the `type` column, this column can introduce template names that can - * be mentioned in the `signature` column. For example, `insert` - * introduces the template name `InputIt`. + * Like the `type` column, this column can introduce template type names + * that can be mentioned in the `signature` column. For example, + * `insert` introduces the template name `InputIt`. Non-type + * template parameters cannot be specified. * 5. The `signature` column optionally restricts the named member. If * `signature` is blank then no such filtering is done. The format of the * signature is a comma-separated list of types enclosed in parentheses. The @@ -633,6 +634,21 @@ string getParameterTypeWithoutTemplateArguments(Function f, int n, boolean canon canonical = true } +/** Gets the `i`'th supported template parameter for `templateFunction`. */ +private Locatable getSupportedFunctionTemplateArgument(Function templateFunction, int i) { + result = + rank[i + 1](int j, TypeTemplateParameter ttp | + ttp = templateFunction.getTemplateArgument(j) + | + ttp order by j + ) +} + +/** Gets the number of supported template parameters for `templateFunction`. */ +private int getNumberOfSupportedFunctionTemplateArguments(Function templateFunction) { + result = count(int i | exists(getSupportedFunctionTemplateArgument(templateFunction, i)) | i) +} + /** * Normalize the `n`'th parameter of `f` by replacing template names * with `func:N` (where `N` is the index of the template). @@ -640,18 +656,34 @@ string getParameterTypeWithoutTemplateArguments(Function f, int n, boolean canon private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remaining) { exists(Function templateFunction | templateFunction = getFullyTemplatedFunction(f) and - remaining = templateFunction.getNumberOfTemplateArguments() and + remaining = getNumberOfSupportedFunctionTemplateArguments(templateFunction) and result = getParameterTypeWithoutTemplateArguments(templateFunction, n, _) ) or exists(string mid, TypeTemplateParameter tp, Function templateFunction | mid = getTypeNameWithoutFunctionTemplates(f, n, remaining + 1) and templateFunction = getFullyTemplatedFunction(f) and - tp = templateFunction.getTemplateArgument(remaining) and + tp = getSupportedFunctionTemplateArgument(templateFunction, remaining) + | result = mid.replaceAll(tp.getName(), "func:" + remaining.toString()) ) } +/** Gets the `i`'th support template parameter for `templateClass`. */ +private Locatable getSupportedClassTemplateArgument(Class templateClass, int i) { + result = + rank[i + 1](int j, TypeTemplateParameter ttp | + ttp = templateClass.getTemplateArgument(j) + | + ttp order by j + ) +} + +/** Gets the number of supported template parameters for `templateClass`. */ +private int getNumberOfSupportedClassTemplateArguments(Class templateClass) { + result = count(int i | exists(getSupportedClassTemplateArgument(templateClass, i)) | i) +} + /** * Normalize the `n`'th parameter of `f` by replacing template names * with `class:N` (where `N` is the index of the template). @@ -661,7 +693,7 @@ private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining // If there is a declaring type then we start by expanding the function templates exists(Class template | isClassConstructedFrom(f.getDeclaringType(), template) and - remaining = template.getNumberOfTemplateArguments() and + remaining = getNumberOfSupportedClassTemplateArguments(template) and result = getTypeNameWithoutFunctionTemplates(f, n, 0) ) or @@ -673,7 +705,8 @@ private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining exists(string mid, TypeTemplateParameter tp, Class template | mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and isClassConstructedFrom(f.getDeclaringType(), template) and - tp = template.getTemplateArgument(remaining) and + tp = getSupportedClassTemplateArgument(template, remaining) + | result = mid.replaceAll(tp.getName(), "class:" + remaining.toString()) ) } From 98879d0f1afb2f893191bd56a1ca374013fbedaa Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 24 Nov 2025 12:06:38 +0000 Subject: [PATCH 3/9] C++: Accept test changes. --- .../dataflow/external-models/flow.expected | 45 +++++++++++++------ .../dataflow/external-models/test.cpp | 2 +- 2 files changed, 32 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 b1f984680ad..95b4e2ef8b4 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/flow.expected +++ b/cpp/ql/test/library-tests/dataflow/external-models/flow.expected @@ -30,13 +30,14 @@ models | 29 | Summary: ; ; false; RtlMoveMemory; ; ; Argument[*@1]; Argument[*@0]; value; manual | | 30 | Summary: ; ; false; RtlMoveVolatileMemory; ; ; Argument[*@1]; Argument[*@0]; value; manual | | 31 | Summary: ; ; false; callWithArgument; ; ; Argument[1]; Argument[0].Parameter[0]; value; manual | -| 32 | Summary: ; ; false; pthread_create; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual | -| 33 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated | -| 34 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual | -| 35 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual | -| 36 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual | +| 32 | Summary: ; ; false; callWithNonTypeTemplate; (const T &); ; Argument[*0]; ReturnValue; value; manual | +| 33 | Summary: ; ; false; pthread_create; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual | +| 34 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated | +| 35 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual | +| 36 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual | +| 37 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual | edges -| 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 | provenance | MaD:36 | +| 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 | provenance | MaD:37 | | asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:17 | | asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:17 Sink:MaD:2 | | asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:98:7:98:14 | send_str | provenance | TaintFunction | @@ -45,10 +46,10 @@ edges | asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | | | asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:2 | | 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:36 | -| 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:34 | -| 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:33 | -| 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:35 | +| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:37 | +| 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:35 | +| 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:34 | +| 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:36 | | 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:16 | @@ -60,15 +61,15 @@ edges | 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:1 | | 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:34 | +| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:35 | | 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:1 | | 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:33 | +| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:34 | | 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:1 | | 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:35 | +| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:36 | | 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:1 | | test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | provenance | | @@ -76,7 +77,7 @@ edges | test.cpp:46:30:46:32 | *arg [x] | test.cpp:47:12:47:19 | *arg [x] | provenance | | | test.cpp:47:12:47:19 | *arg [x] | test.cpp:48:13:48:13 | *s [x] | provenance | | | test.cpp:48:13:48:13 | *s [x] | test.cpp:48:16:48:16 | x | provenance | Sink:MaD:1 | -| test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | provenance | MaD:32 | +| test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | provenance | MaD:33 | | test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | test.cpp:46:30:46:32 | *arg [x] | provenance | | | test.cpp:56:2:56:2 | *s [post update] [x] | test.cpp:59:55:59:64 | *& ... [x] | provenance | | | test.cpp:56:2:56:18 | ... = ... | test.cpp:56:2:56:2 | *s [post update] [x] | provenance | | @@ -103,6 +104,13 @@ edges | test.cpp:101:26:101:26 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | | | test.cpp:103:63:103:63 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | | | test.cpp:104:62:104:62 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | | +| test.cpp:108:3:108:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:108:3:108:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | provenance | MaD:32 | +| test.cpp:111:10:111:18 | call to ymlSource | test.cpp:111:10:111:18 | call to ymlSource | provenance | Src:MaD:16 | +| test.cpp:111:10:111:18 | call to ymlSource | test.cpp:112:43:112:43 | *x | provenance | | +| test.cpp:112:10:112:41 | call to callWithNonTypeTemplate | test.cpp:112:10:112:41 | call to callWithNonTypeTemplate | provenance | | +| test.cpp:112:10:112:41 | call to callWithNonTypeTemplate | test.cpp:113:10:113:10 | y | provenance | Sink:MaD:1 | +| test.cpp:112:43:112:43 | *x | test.cpp:108:3:108:25 | [summary param] *0 in callWithNonTypeTemplate | provenance | | +| test.cpp:112:43:112:43 | *x | test.cpp:112:10:112:41 | call to callWithNonTypeTemplate | provenance | MaD:32 | | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | provenance | MaD:18 | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:22:15:22:29 | *call to GetCommandLineA | provenance | Src:MaD:3 | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:24:8:24:11 | * ... | provenance | | @@ -314,6 +322,14 @@ nodes | test.cpp:101:26:101:26 | x | semmle.label | x | | test.cpp:103:63:103:63 | x | semmle.label | x | | test.cpp:104:62:104:62 | x | semmle.label | x | +| test.cpp:108:3:108:25 | [summary param] *0 in callWithNonTypeTemplate | semmle.label | [summary param] *0 in callWithNonTypeTemplate | +| test.cpp:108:3:108:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | semmle.label | [summary] to write: ReturnValue in callWithNonTypeTemplate | +| test.cpp:111:10:111:18 | call to ymlSource | semmle.label | call to ymlSource | +| test.cpp:111:10:111:18 | call to ymlSource | semmle.label | call to ymlSource | +| test.cpp:112:10:112:41 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate | +| test.cpp:112:10:112:41 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate | +| test.cpp:112:43:112:43 | *x | semmle.label | *x | +| test.cpp:113:10:113:10 | y | semmle.label | y | | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | semmle.label | [summary param] *0 in CommandLineToArgvA | | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | semmle.label | [summary] to write: ReturnValue[**] in CommandLineToArgvA | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA | @@ -472,6 +488,7 @@ subpaths | 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: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 | +| test.cpp:112:43:112:43 | *x | test.cpp:108:3:108:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:108:3:108:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | test.cpp:112:10:112:41 | call to callWithNonTypeTemplate | | windows.cpp:27:36:27:38 | *cmd | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | windows.cpp:27:17:27:34 | **call to CommandLineToArgvA | | windows.cpp:537:40:537:41 | *& ... | windows.cpp:473:17:473:37 | [summary param] *1 in RtlCopyVolatileMemory | windows.cpp:473:17:473:37 | [summary param] *0 in RtlCopyVolatileMemory [Return] | windows.cpp:537:27:537:37 | RtlCopyVolatileMemory output argument | | windows.cpp:542:38:542:39 | *& ... | windows.cpp:479:17:479:35 | [summary param] *1 in RtlCopyDeviceMemory | windows.cpp:479:17:479:35 | [summary param] *0 in RtlCopyDeviceMemory [Return] | windows.cpp:542:25:542:35 | RtlCopyDeviceMemory output argument | 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 830cd8e081f..ce5179e3157 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/external-models/test.cpp @@ -110,5 +110,5 @@ T callWithNonTypeTemplate(const T&); void test_callWithNonTypeTemplate() { int x = ymlSource(); int y = callWithNonTypeTemplate<10, int>(x); - ymlSink(y); // $ MISSING: ir + ymlSink(y); // $ ir } \ No newline at end of file From fd566780a6e15acbe02935f34d42566d93114f75 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 24 Nov 2025 12:17:06 +0000 Subject: [PATCH 4/9] Update cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll index 6c60296b56a..a269427971e 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll @@ -669,7 +669,7 @@ private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remain ) } -/** Gets the `i`'th support template parameter for `templateClass`. */ +/** Gets the `i`'th supported template parameter for `templateClass`. */ private Locatable getSupportedClassTemplateArgument(Class templateClass, int i) { result = rank[i + 1](int j, TypeTemplateParameter ttp | From 6bae58e29c23c5322377d8b0493c1a115f7d9cf9 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 24 Nov 2025 12:35:19 +0000 Subject: [PATCH 5/9] C++: Accept more test changes. --- .../taint-tests/test_mad-signatures.expected | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected index 2409e711e6d..e0002aa9c03 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected @@ -26843,6 +26843,24 @@ getParameterTypeName | atl.cpp:71:5:71:17 | _U_STRINGorID | 0 | unsigned int | | atl.cpp:72:5:72:17 | _U_STRINGorID | 0 | LPCTSTR | | atl.cpp:72:5:72:17 | _U_STRINGorID | 0 | const char * | +| atl.cpp:96:5:96:10 | CA2AEX | 0 | LPCSTR | +| atl.cpp:96:5:96:10 | CA2AEX | 0 | const char * | +| atl.cpp:96:5:96:10 | CA2AEX | 1 | UINT | +| atl.cpp:96:5:96:10 | CA2AEX | 1 | unsigned int | +| atl.cpp:97:5:97:10 | CA2AEX | 0 | LPCSTR | +| atl.cpp:97:5:97:10 | CA2AEX | 0 | const char * | +| atl.cpp:124:5:124:11 | CA2CAEX | 0 | LPCSTR | +| atl.cpp:124:5:124:11 | CA2CAEX | 0 | const char * | +| atl.cpp:124:5:124:11 | CA2CAEX | 1 | UINT | +| atl.cpp:124:5:124:11 | CA2CAEX | 1 | unsigned int | +| atl.cpp:125:5:125:11 | CA2CAEX | 0 | LPCSTR | +| atl.cpp:125:5:125:11 | CA2CAEX | 0 | const char * | +| atl.cpp:149:5:149:10 | CA2WEX | 0 | LPCSTR | +| atl.cpp:149:5:149:10 | CA2WEX | 0 | const char * | +| atl.cpp:149:5:149:10 | CA2WEX | 1 | UINT | +| atl.cpp:149:5:149:10 | CA2WEX | 1 | unsigned int | +| atl.cpp:150:5:150:10 | CA2WEX | 0 | LPCSTR | +| atl.cpp:150:5:150:10 | CA2WEX | 0 | const char * | | atl.cpp:196:12:196:14 | Add | 0 | INARGTYPclass:0 | | atl.cpp:198:12:198:17 | Append | 0 | const CAtlArray & | | atl.cpp:199:10:199:13 | Copy | 0 | const CAtlArray & | @@ -27083,6 +27101,10 @@ getParameterTypeName | atl.cpp:940:10:940:18 | SetString | 0 | PCXSTR | | atl.cpp:940:10:940:18 | SetString | 0 | const class:0 * | | atl.cpp:942:11:942:20 | operator[] | 0 | int | +| atl.cpp:1018:10:1018:10 | operator= | 0 | MakeOther && | +| atl.cpp:1018:10:1018:10 | operator= | 0 | const MakeOther & | +| atl.cpp:1023:10:1023:10 | operator= | 0 | MakeOther && | +| atl.cpp:1023:10:1023:10 | operator= | 0 | const MakeOther & | | atl.cpp:1036:5:1036:12 | CStringT | 0 | const VARIANT & | | atl.cpp:1036:5:1036:12 | CStringT | 0 | const tagVARIANT & | | atl.cpp:1037:5:1037:12 | CStringT | 0 | const VARIANT & | @@ -27286,6 +27308,8 @@ getParameterTypeName | standalone_iterators.cpp:20:7:20:7 | operator= | 0 | const int_iterator_by_trait & | | standalone_iterators.cpp:20:7:20:7 | operator= | 0 | int_iterator_by_trait && | | standalone_iterators.cpp:23:27:23:36 | operator++ | 0 | int | +| standalone_iterators.cpp:28:13:28:13 | operator= | 0 | const iterator_traits & | +| standalone_iterators.cpp:28:13:28:13 | operator= | 0 | iterator_traits && | | standalone_iterators.cpp:36:7:36:7 | operator= | 0 | const non_iterator & | | standalone_iterators.cpp:36:7:36:7 | operator= | 0 | non_iterator && | | standalone_iterators.cpp:39:18:39:27 | operator++ | 0 | int | @@ -27297,6 +27321,8 @@ getParameterTypeName | standalone_iterators.cpp:66:30:66:39 | operator++ | 0 | int | | standalone_iterators.cpp:68:30:68:39 | operator-- | 0 | int | | standalone_iterators.cpp:70:31:70:39 | operator= | 0 | int | +| standalone_iterators.cpp:74:13:74:13 | operator= | 0 | const iterator_traits & | +| standalone_iterators.cpp:74:13:74:13 | operator= | 0 | iterator_traits && | | standalone_iterators.cpp:82:7:82:7 | container | 0 | const container & | | standalone_iterators.cpp:82:7:82:7 | container | 0 | container && | | standalone_iterators.cpp:82:7:82:7 | operator= | 0 | const container & | From faa55f50e7c9d454251801bf2ce5f376a1cf09c3 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 25 Nov 2025 14:52:26 +0000 Subject: [PATCH 6/9] C++: Add another test with a template function whose non-type template parameter is in tail position. --- .../dataflow/external-models/flow.expected | 39 ++++++++++++------- .../dataflow/external-models/sinks.expected | 3 +- .../dataflow/external-models/sources.expected | 2 +- .../dataflow/external-models/test.cpp | 12 ++++-- 4 files changed, 38 insertions(+), 18 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 95b4e2ef8b4..a6b2c9d5e3a 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/flow.expected +++ b/cpp/ql/test/library-tests/dataflow/external-models/flow.expected @@ -105,12 +105,18 @@ edges | test.cpp:103:63:103:63 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | | | test.cpp:104:62:104:62 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | | | test.cpp:108:3:108:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:108:3:108:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | provenance | MaD:32 | -| test.cpp:111:10:111:18 | call to ymlSource | test.cpp:111:10:111:18 | call to ymlSource | provenance | Src:MaD:16 | -| test.cpp:111:10:111:18 | call to ymlSource | test.cpp:112:43:112:43 | *x | provenance | | -| test.cpp:112:10:112:41 | call to callWithNonTypeTemplate | test.cpp:112:10:112:41 | call to callWithNonTypeTemplate | provenance | | -| test.cpp:112:10:112:41 | call to callWithNonTypeTemplate | test.cpp:113:10:113:10 | y | provenance | Sink:MaD:1 | -| test.cpp:112:43:112:43 | *x | test.cpp:108:3:108:25 | [summary param] *0 in callWithNonTypeTemplate | provenance | | -| test.cpp:112:43:112:43 | *x | test.cpp:112:10:112:41 | call to callWithNonTypeTemplate | provenance | MaD:32 | +| test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:111:3:111:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | provenance | MaD:32 | +| test.cpp:114:10:114:18 | call to ymlSource | test.cpp:114:10:114:18 | call to ymlSource | provenance | Src:MaD:16 | +| test.cpp:114:10:114:18 | call to ymlSource | test.cpp:115:44:115:44 | *x | provenance | | +| test.cpp:114:10:114:18 | call to ymlSource | test.cpp:118:44:118:44 | *x | provenance | | +| test.cpp:115:11:115:42 | call to callWithNonTypeTemplate | test.cpp:115:11:115:42 | call to callWithNonTypeTemplate | provenance | | +| test.cpp:115:11:115:42 | call to callWithNonTypeTemplate | test.cpp:116:10:116:11 | y1 | provenance | Sink:MaD:1 | +| test.cpp:115:44:115:44 | *x | test.cpp:108:3:108:25 | [summary param] *0 in callWithNonTypeTemplate | provenance | | +| test.cpp:115:44:115:44 | *x | test.cpp:115:11:115:42 | call to callWithNonTypeTemplate | provenance | MaD:32 | +| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | provenance | | +| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | test.cpp:119:10:119:11 | y2 | provenance | Sink:MaD:1 | +| test.cpp:118:44:118:44 | *x | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | provenance | | +| test.cpp:118:44:118:44 | *x | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | provenance | MaD:32 | | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | provenance | MaD:18 | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:22:15:22:29 | *call to GetCommandLineA | provenance | Src:MaD:3 | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:24:8:24:11 | * ... | provenance | | @@ -324,12 +330,18 @@ nodes | test.cpp:104:62:104:62 | x | semmle.label | x | | test.cpp:108:3:108:25 | [summary param] *0 in callWithNonTypeTemplate | semmle.label | [summary param] *0 in callWithNonTypeTemplate | | test.cpp:108:3:108:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | semmle.label | [summary] to write: ReturnValue in callWithNonTypeTemplate | -| test.cpp:111:10:111:18 | call to ymlSource | semmle.label | call to ymlSource | -| test.cpp:111:10:111:18 | call to ymlSource | semmle.label | call to ymlSource | -| test.cpp:112:10:112:41 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate | -| test.cpp:112:10:112:41 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate | -| test.cpp:112:43:112:43 | *x | semmle.label | *x | -| test.cpp:113:10:113:10 | y | semmle.label | y | +| test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | semmle.label | [summary param] *0 in callWithNonTypeTemplate | +| test.cpp:111:3:111:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | semmle.label | [summary] to write: ReturnValue in callWithNonTypeTemplate | +| test.cpp:114:10:114:18 | call to ymlSource | semmle.label | call to ymlSource | +| test.cpp:114:10:114:18 | call to ymlSource | semmle.label | call to ymlSource | +| test.cpp:115:11:115:42 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate | +| test.cpp:115:11:115:42 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate | +| test.cpp:115:44:115:44 | *x | semmle.label | *x | +| test.cpp:116:10:116:11 | y1 | semmle.label | y1 | +| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate | +| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate | +| test.cpp:118:44:118:44 | *x | semmle.label | *x | +| test.cpp:119:10:119:11 | y2 | semmle.label | y2 | | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | semmle.label | [summary param] *0 in CommandLineToArgvA | | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | semmle.label | [summary] to write: ReturnValue[**] in CommandLineToArgvA | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA | @@ -488,7 +500,8 @@ subpaths | 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: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 | -| test.cpp:112:43:112:43 | *x | test.cpp:108:3:108:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:108:3:108:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | test.cpp:112:10:112:41 | call to callWithNonTypeTemplate | +| test.cpp:115:44:115:44 | *x | test.cpp:108:3:108:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:108:3:108:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | test.cpp:115:11:115:42 | call to callWithNonTypeTemplate | +| test.cpp:118:44:118:44 | *x | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:111:3:111:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | | windows.cpp:27:36:27:38 | *cmd | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | windows.cpp:27:17:27:34 | **call to CommandLineToArgvA | | windows.cpp:537:40:537:41 | *& ... | windows.cpp:473:17:473:37 | [summary param] *1 in RtlCopyVolatileMemory | windows.cpp:473:17:473:37 | [summary param] *0 in RtlCopyVolatileMemory [Return] | windows.cpp:537:27:537:37 | RtlCopyVolatileMemory output argument | | windows.cpp:542:38:542:39 | *& ... | windows.cpp:479:17:479:35 | [summary param] *1 in RtlCopyDeviceMemory | windows.cpp:479:17:479:35 | [summary param] *0 in RtlCopyDeviceMemory [Return] | windows.cpp:542:25:542:35 | RtlCopyDeviceMemory output argument | 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 51c2180f113..e28349b7159 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected +++ b/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected @@ -13,4 +13,5 @@ | test.cpp:75:11:75:11 | y | test-sink | | test.cpp:83:11:83:11 | y | test-sink | | test.cpp:89:11:89:11 | y | test-sink | -| test.cpp:113:10:113:10 | y | test-sink | +| test.cpp:116:10:116:11 | y1 | test-sink | +| test.cpp:119:10:119:11 | y2 | 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 fc975299737..cb7e06b801d 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/sources.expected +++ b/cpp/ql/test/library-tests/dataflow/external-models/sources.expected @@ -2,7 +2,7 @@ | test.cpp:10:10:10:18 | call to ymlSource | local | | test.cpp:56:8:56:16 | call to ymlSource | local | | test.cpp:94:10:94:18 | call to ymlSource | local | -| test.cpp:111:10:111:18 | call to ymlSource | local | +| test.cpp:114:10:114:18 | call to ymlSource | local | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | local | | windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | local | | windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | local | 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 ce5179e3157..6a021431bd9 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/external-models/test.cpp @@ -107,8 +107,14 @@ void test_callWithArgument() { template T callWithNonTypeTemplate(const T&); +template +T callWithNonTypeTemplate(const T&); + void test_callWithNonTypeTemplate() { int x = ymlSource(); - int y = callWithNonTypeTemplate<10, int>(x); - ymlSink(y); // $ ir -} \ No newline at end of file + int y1 = callWithNonTypeTemplate<10, int>(x); + ymlSink(y1); // $ ir + + int y2 = callWithNonTypeTemplate(x); + ymlSink(y2); // $ ir +} From 05737af165f8fca31c7744b26f46743a9298b835 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 25 Nov 2025 14:54:47 +0000 Subject: [PATCH 7/9] C++: Only support non-type template parameters in tail position. --- .../semmle/code/cpp/dataflow/ExternalFlow.qll | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll index a269427971e..ebf82a59dfa 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll @@ -634,14 +634,13 @@ string getParameterTypeWithoutTemplateArguments(Function f, int n, boolean canon canonical = true } -/** Gets the `i`'th supported template parameter for `templateFunction`. */ -private Locatable getSupportedFunctionTemplateArgument(Function templateFunction, int i) { +/** + * Gets the largest index of a template parameter of `templateFunction` that + * is a type template parameter. + */ +private int getLastTypeTemplateFunctionParameterIndex(Function templateFunction) { result = - rank[i + 1](int j, TypeTemplateParameter ttp | - ttp = templateFunction.getTemplateArgument(j) - | - ttp order by j - ) + max(int index | templateFunction.getTemplateArgument(index) instanceof TypeTemplateParameter) } /** Gets the number of supported template parameters for `templateFunction`. */ @@ -649,6 +648,14 @@ private int getNumberOfSupportedFunctionTemplateArguments(Function templateFunct result = count(int i | exists(getSupportedFunctionTemplateArgument(templateFunction, i)) | i) } +/** Gets the `i`'th supported template parameter for `templateFunction`. */ +private Locatable getSupportedFunctionTemplateArgument(Function templateFunction, int i) { + result = templateFunction.getTemplateArgument(i) and + // We don't yet support non-type template parameters in the middle of a + // template parameter list + i <= getLastTypeTemplateFunctionParameterIndex(templateFunction) +} + /** * Normalize the `n`'th parameter of `f` by replacing template names * with `func:N` (where `N` is the index of the template). @@ -669,14 +676,21 @@ private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remain ) } +/** + * Gets the largest index of a template parameter of `templateFunction` that + * is a type template parameter. + */ +private int getLastTypeTemplateClassParameterIndex(Class templateClass) { + result = + max(int index | templateClass.getTemplateArgument(index) instanceof TypeTemplateParameter) +} + /** Gets the `i`'th supported template parameter for `templateClass`. */ private Locatable getSupportedClassTemplateArgument(Class templateClass, int i) { - result = - rank[i + 1](int j, TypeTemplateParameter ttp | - ttp = templateClass.getTemplateArgument(j) - | - ttp order by j - ) + result = templateClass.getTemplateArgument(i) and + // We don't yet support non-type template parameters in the middle of a + // template parameter list + i <= getLastTypeTemplateClassParameterIndex(templateClass) } /** Gets the number of supported template parameters for `templateClass`. */ From 0deac833e4542fb49b251c8433a1628a762821f7 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 25 Nov 2025 14:59:09 +0000 Subject: [PATCH 8/9] C++: Accept test changes. --- .../dataflow/external-models/flow.expected | 13 ------------- .../library-tests/dataflow/external-models/test.cpp | 2 +- 2 files changed, 1 insertion(+), 14 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 a6b2c9d5e3a..d47ae8950fb 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/flow.expected +++ b/cpp/ql/test/library-tests/dataflow/external-models/flow.expected @@ -104,15 +104,9 @@ edges | test.cpp:101:26:101:26 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | | | test.cpp:103:63:103:63 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | | | test.cpp:104:62:104:62 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | | -| test.cpp:108:3:108:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:108:3:108:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | provenance | MaD:32 | | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:111:3:111:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | provenance | MaD:32 | | test.cpp:114:10:114:18 | call to ymlSource | test.cpp:114:10:114:18 | call to ymlSource | provenance | Src:MaD:16 | -| test.cpp:114:10:114:18 | call to ymlSource | test.cpp:115:44:115:44 | *x | provenance | | | test.cpp:114:10:114:18 | call to ymlSource | test.cpp:118:44:118:44 | *x | provenance | | -| test.cpp:115:11:115:42 | call to callWithNonTypeTemplate | test.cpp:115:11:115:42 | call to callWithNonTypeTemplate | provenance | | -| test.cpp:115:11:115:42 | call to callWithNonTypeTemplate | test.cpp:116:10:116:11 | y1 | provenance | Sink:MaD:1 | -| test.cpp:115:44:115:44 | *x | test.cpp:108:3:108:25 | [summary param] *0 in callWithNonTypeTemplate | provenance | | -| test.cpp:115:44:115:44 | *x | test.cpp:115:11:115:42 | call to callWithNonTypeTemplate | provenance | MaD:32 | | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | provenance | | | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | test.cpp:119:10:119:11 | y2 | provenance | Sink:MaD:1 | | test.cpp:118:44:118:44 | *x | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | provenance | | @@ -328,16 +322,10 @@ nodes | test.cpp:101:26:101:26 | x | semmle.label | x | | test.cpp:103:63:103:63 | x | semmle.label | x | | test.cpp:104:62:104:62 | x | semmle.label | x | -| test.cpp:108:3:108:25 | [summary param] *0 in callWithNonTypeTemplate | semmle.label | [summary param] *0 in callWithNonTypeTemplate | -| test.cpp:108:3:108:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | semmle.label | [summary] to write: ReturnValue in callWithNonTypeTemplate | | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | semmle.label | [summary param] *0 in callWithNonTypeTemplate | | test.cpp:111:3:111:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | semmle.label | [summary] to write: ReturnValue in callWithNonTypeTemplate | | test.cpp:114:10:114:18 | call to ymlSource | semmle.label | call to ymlSource | | test.cpp:114:10:114:18 | call to ymlSource | semmle.label | call to ymlSource | -| test.cpp:115:11:115:42 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate | -| test.cpp:115:11:115:42 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate | -| test.cpp:115:44:115:44 | *x | semmle.label | *x | -| test.cpp:116:10:116:11 | y1 | semmle.label | y1 | | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate | | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate | | test.cpp:118:44:118:44 | *x | semmle.label | *x | @@ -500,7 +488,6 @@ subpaths | 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: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 | -| test.cpp:115:44:115:44 | *x | test.cpp:108:3:108:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:108:3:108:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | test.cpp:115:11:115:42 | call to callWithNonTypeTemplate | | test.cpp:118:44:118:44 | *x | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:111:3:111:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | | windows.cpp:27:36:27:38 | *cmd | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | windows.cpp:27:17:27:34 | **call to CommandLineToArgvA | | windows.cpp:537:40:537:41 | *& ... | windows.cpp:473:17:473:37 | [summary param] *1 in RtlCopyVolatileMemory | windows.cpp:473:17:473:37 | [summary param] *0 in RtlCopyVolatileMemory [Return] | windows.cpp:537:27:537:37 | RtlCopyVolatileMemory output argument | 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 6a021431bd9..af11ff958f5 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/external-models/test.cpp @@ -113,7 +113,7 @@ T callWithNonTypeTemplate(const T&); void test_callWithNonTypeTemplate() { int x = ymlSource(); int y1 = callWithNonTypeTemplate<10, int>(x); - ymlSink(y1); // $ ir + ymlSink(y1); // $ MISSING: ir int y2 = callWithNonTypeTemplate(x); ymlSink(y2); // $ ir From 73b6fa69a988119086f875ad6142549fa14bdc7e Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 25 Nov 2025 15:03:26 +0000 Subject: [PATCH 9/9] C++: Fix Code Scanning alert. --- cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll index ebf82a59dfa..69e32d23ec1 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll @@ -677,7 +677,7 @@ private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remain } /** - * Gets the largest index of a template parameter of `templateFunction` that + * Gets the largest index of a template parameter of `templateClass` that * is a type template parameter. */ private int getLastTypeTemplateClassParameterIndex(Class templateClass) {