From 46a07fa9b2cd79298f257042bd1f9fa153a5aa42 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 9 Sep 2020 18:22:06 +0100 Subject: [PATCH 1/8] C++: Model std::stringstream::str. --- .../cpp/models/implementations/StdString.qll | 17 +++++++++++++++++ .../dataflow/taint-tests/localTaint.expected | 15 +++++++++++++++ .../dataflow/taint-tests/stringstream.cpp | 14 +++++++------- .../dataflow/taint-tests/taint.expected | 7 +++++++ .../dataflow/taint-tests/test_diff.expected | 7 +++++++ 5 files changed, 53 insertions(+), 7 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 8d4fdd8700c7..73bd07ef269e 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -352,3 +352,20 @@ class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction { output.isParameterDeref(0) } } + +/** + * The `std::stringstream` function `str`. + */ +class StdStringStreamStr extends TaintFunction { + StdStringStreamStr() { this.hasQualifiedName("std", "basic_stringstream", "str") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from qualifier to return value (if any) + input.isQualifierObject() and + output.isReturnValue() + or + // flow from first parameter (if any) to qualifier + input.isParameterDeref(0) and + output.isQualifierObject() + } +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 08d0a3216390..6a98bb1cfcc9 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1425,16 +1425,29 @@ | stringstream.cpp:35:7:35:9 | ss5 | stringstream.cpp:35:11:35:11 | call to operator<< | | | stringstream.cpp:35:14:35:14 | t | stringstream.cpp:35:7:35:9 | ref arg ss5 | TAINT | | stringstream.cpp:35:14:35:14 | t | stringstream.cpp:35:11:35:11 | call to operator<< | TAINT | +| stringstream.cpp:42:7:42:9 | ss1 | stringstream.cpp:42:11:42:13 | call to str | TAINT | +| stringstream.cpp:43:7:43:9 | ss2 | stringstream.cpp:43:11:43:13 | call to str | TAINT | +| stringstream.cpp:44:7:44:9 | ss3 | stringstream.cpp:44:11:44:13 | call to str | TAINT | +| stringstream.cpp:45:7:45:9 | ss4 | stringstream.cpp:45:11:45:13 | call to str | TAINT | +| stringstream.cpp:46:7:46:9 | ss5 | stringstream.cpp:46:11:46:13 | call to str | TAINT | | stringstream.cpp:48:2:48:4 | ref arg ss6 | stringstream.cpp:49:2:49:4 | ss6 | | | stringstream.cpp:48:2:48:4 | ref arg ss6 | stringstream.cpp:52:7:52:9 | ss6 | | +| stringstream.cpp:48:2:48:4 | ss6 | stringstream.cpp:48:6:48:8 | call to str | TAINT | | stringstream.cpp:48:10:48:14 | abc | stringstream.cpp:48:10:48:14 | call to basic_string | TAINT | +| stringstream.cpp:48:10:48:14 | call to basic_string | stringstream.cpp:48:2:48:4 | ref arg ss6 | TAINT | | stringstream.cpp:49:2:49:4 | ref arg ss6 | stringstream.cpp:52:7:52:9 | ss6 | | +| stringstream.cpp:49:2:49:4 | ss6 | stringstream.cpp:49:6:49:8 | call to str | TAINT | | stringstream.cpp:49:10:49:15 | call to source | stringstream.cpp:49:10:49:17 | call to basic_string | TAINT | +| stringstream.cpp:49:10:49:17 | call to basic_string | stringstream.cpp:49:2:49:4 | ref arg ss6 | TAINT | | stringstream.cpp:50:2:50:4 | ref arg ss7 | stringstream.cpp:51:2:51:4 | ss7 | | | stringstream.cpp:50:2:50:4 | ref arg ss7 | stringstream.cpp:53:7:53:9 | ss7 | | +| stringstream.cpp:50:2:50:4 | ss7 | stringstream.cpp:50:6:50:8 | call to str | TAINT | | stringstream.cpp:50:10:50:15 | call to source | stringstream.cpp:50:10:50:17 | call to basic_string | TAINT | +| stringstream.cpp:50:10:50:17 | call to basic_string | stringstream.cpp:50:2:50:4 | ref arg ss7 | TAINT | | stringstream.cpp:51:2:51:4 | ref arg ss7 | stringstream.cpp:53:7:53:9 | ss7 | | +| stringstream.cpp:51:2:51:4 | ss7 | stringstream.cpp:51:6:51:8 | call to str | TAINT | | stringstream.cpp:51:10:51:14 | abc | stringstream.cpp:51:10:51:14 | call to basic_string | TAINT | +| stringstream.cpp:51:10:51:14 | call to basic_string | stringstream.cpp:51:2:51:4 | ref arg ss7 | TAINT | | stringstream.cpp:55:7:55:9 | ref arg ss8 | stringstream.cpp:58:7:58:9 | ss8 | | | stringstream.cpp:56:7:56:9 | ref arg ss9 | stringstream.cpp:59:7:59:9 | ss9 | | | stringstream.cpp:57:7:57:10 | ref arg ss10 | stringstream.cpp:60:7:60:10 | ss10 | | @@ -1470,6 +1483,8 @@ | stringstream.cpp:78:7:78:9 | ref arg ss2 | stringstream.cpp:81:7:81:9 | ss2 | | | stringstream.cpp:78:7:78:9 | ref arg ss2 | stringstream.cpp:83:7:83:9 | ss2 | | | stringstream.cpp:78:14:78:15 | ref arg v2 | stringstream.cpp:85:7:85:8 | v2 | | +| stringstream.cpp:82:7:82:9 | ss1 | stringstream.cpp:82:11:82:13 | call to str | TAINT | +| stringstream.cpp:83:7:83:9 | ss2 | stringstream.cpp:83:11:83:13 | call to str | TAINT | | stringstream.cpp:90:18:90:23 | call to basic_string | stringstream.cpp:92:24:92:25 | s1 | | | stringstream.cpp:90:19:90:23 | abc | stringstream.cpp:90:18:90:23 | call to basic_string | TAINT | | stringstream.cpp:91:18:91:26 | call to basic_string | stringstream.cpp:93:24:93:25 | s2 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp index e656277c5671..9cae03894898 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp @@ -40,17 +40,17 @@ void test_stringstream_string(int amount) sink(ss4); // tainted sink(ss5); // tainted sink(ss1.str()); - sink(ss2.str()); // tainted [NOT DETECTED] - sink(ss3.str()); // tainted [NOT DETECTED] - sink(ss4.str()); // tainted [NOT DETECTED] - sink(ss5.str()); // tainted [NOT DETECTED] + sink(ss2.str()); // tainted + sink(ss3.str()); // tainted + sink(ss4.str()); // tainted + sink(ss5.str()); // tainted ss6.str("abc"); ss6.str(source()); // (overwrites) ss7.str(source()); ss7.str("abc"); // (overwrites) - sink(ss6); // tainted [NOT DETECTED] - sink(ss7); + sink(ss6); // tainted + sink(ss7); // [FALSE POSITIVE] sink(ss8.put('a')); sink(ss9.put(ns_char::source())); // tainted [NOT DETECTED] @@ -80,7 +80,7 @@ void test_stringstream_int(int source) sink(ss1); sink(ss2); // tainted sink(ss1.str()); - sink(ss2.str()); // tainted [NOT DETECTED] + sink(ss2.str()); // tainted sink(v1); sink(v2); // tainted [NOT DETECTED] } diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 7e0006fb3adf..e5d0ca7ab732 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -164,8 +164,15 @@ | stringstream.cpp:39:7:39:9 | ss3 | stringstream.cpp:33:23:33:28 | call to source | | stringstream.cpp:40:7:40:9 | ss4 | stringstream.cpp:34:14:34:19 | call to source | | stringstream.cpp:41:7:41:9 | ss5 | stringstream.cpp:29:16:29:21 | call to source | +| stringstream.cpp:43:11:43:13 | call to str | stringstream.cpp:32:14:32:19 | call to source | +| stringstream.cpp:44:11:44:13 | call to str | stringstream.cpp:33:23:33:28 | call to source | +| stringstream.cpp:45:11:45:13 | call to str | stringstream.cpp:34:14:34:19 | call to source | +| stringstream.cpp:46:11:46:13 | call to str | stringstream.cpp:29:16:29:21 | call to source | +| stringstream.cpp:52:7:52:9 | ss6 | stringstream.cpp:49:10:49:15 | call to source | +| stringstream.cpp:53:7:53:9 | ss7 | stringstream.cpp:50:10:50:15 | call to source | | stringstream.cpp:76:11:76:11 | call to operator<< | stringstream.cpp:70:32:70:37 | source | | stringstream.cpp:81:7:81:9 | ss2 | stringstream.cpp:70:32:70:37 | source | +| stringstream.cpp:83:11:83:13 | call to str | stringstream.cpp:70:32:70:37 | source | | stringstream.cpp:143:11:143:11 | call to operator<< | stringstream.cpp:143:14:143:19 | call to source | | structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source | | structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index 6c497b79e1e3..a4cb807355aa 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -180,8 +180,15 @@ | stringstream.cpp:39:7:39:9 | stringstream.cpp:33:23:33:28 | AST only | | stringstream.cpp:40:7:40:9 | stringstream.cpp:34:14:34:19 | AST only | | stringstream.cpp:41:7:41:9 | stringstream.cpp:29:16:29:21 | AST only | +| stringstream.cpp:43:11:43:13 | stringstream.cpp:32:14:32:19 | AST only | +| stringstream.cpp:44:11:44:13 | stringstream.cpp:33:23:33:28 | AST only | +| stringstream.cpp:45:11:45:13 | stringstream.cpp:34:14:34:19 | AST only | +| stringstream.cpp:46:11:46:13 | stringstream.cpp:29:16:29:21 | AST only | +| stringstream.cpp:52:7:52:9 | stringstream.cpp:49:10:49:15 | AST only | +| stringstream.cpp:53:7:53:9 | stringstream.cpp:50:10:50:15 | AST only | | stringstream.cpp:76:11:76:11 | stringstream.cpp:70:32:70:37 | AST only | | stringstream.cpp:81:7:81:9 | stringstream.cpp:70:32:70:37 | AST only | +| stringstream.cpp:83:11:83:13 | stringstream.cpp:70:32:70:37 | AST only | | stringstream.cpp:143:11:143:11 | stringstream.cpp:143:14:143:21 | IR only | | stringstream.cpp:143:11:143:22 | stringstream.cpp:143:14:143:19 | IR only | | stringstream.cpp:143:11:143:22 | stringstream.cpp:143:14:143:21 | IR only | From 66a5c38eef2a0980549e8588b8f326fd2662eb4c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 10 Sep 2020 09:51:01 +0100 Subject: [PATCH 2/8] C++: Model std::stringstream constructor. --- .../cpp/models/implementations/StdString.qll | 21 +++++++++++++++++++ .../dataflow/taint-tests/localTaint.expected | 10 +++++++++ .../dataflow/taint-tests/stringstream.cpp | 12 +++++------ .../dataflow/taint-tests/taint.expected | 6 ++++++ .../dataflow/taint-tests/test_diff.expected | 6 ++++++ 5 files changed, 49 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 73bd07ef269e..f48b0555de68 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -353,6 +353,27 @@ class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction { } } +/** + * Additional model for `std::stringstream` constructors that take a string + * input parameter. + */ +class StdStringStreamConstructor extends Constructor, TaintFunction { + StdStringStreamConstructor() { this.getDeclaringType().hasQualifiedName("std", "basic_stringstream") } + + /** + * Gets the index of a parameter to this function that is a string. + */ + int getAStringParameterIndex() { + getParameter(result).getType() instanceof ReferenceType // `const std::basic_string &` + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // taint flow from any parameter of string type to the returned object + input.isParameterDeref(getAStringParameterIndex()) and + output.isReturnValue() // TODO: this should be `isQualifierObject` by our current definitions, but that flow is not yet supported. + } +} + /** * The `std::stringstream` function `str`. */ diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 6a98bb1cfcc9..75a105da0a6c 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1489,12 +1489,16 @@ | stringstream.cpp:90:19:90:23 | abc | stringstream.cpp:90:18:90:23 | call to basic_string | TAINT | | stringstream.cpp:91:18:91:26 | call to basic_string | stringstream.cpp:93:24:93:25 | s2 | | | stringstream.cpp:91:19:91:24 | call to source | stringstream.cpp:91:18:91:26 | call to basic_string | TAINT | +| stringstream.cpp:92:24:92:25 | s1 | stringstream.cpp:92:24:92:26 | call to basic_stringstream | TAINT | | stringstream.cpp:92:24:92:26 | call to basic_stringstream | stringstream.cpp:102:7:102:9 | ss1 | | +| stringstream.cpp:93:24:93:25 | s2 | stringstream.cpp:93:24:93:26 | call to basic_stringstream | TAINT | | stringstream.cpp:93:24:93:26 | call to basic_stringstream | stringstream.cpp:103:7:103:9 | ss2 | | | stringstream.cpp:94:25:94:49 | call to basic_stringstream | stringstream.cpp:104:7:104:9 | ss3 | | | stringstream.cpp:94:44:94:48 | abc | stringstream.cpp:94:44:94:48 | call to basic_string | TAINT | +| stringstream.cpp:94:44:94:48 | call to basic_string | stringstream.cpp:94:25:94:49 | call to basic_stringstream | TAINT | | stringstream.cpp:95:25:95:52 | call to basic_stringstream | stringstream.cpp:105:7:105:9 | ss4 | | | stringstream.cpp:95:44:95:49 | call to source | stringstream.cpp:95:44:95:51 | call to basic_string | TAINT | +| stringstream.cpp:95:44:95:51 | call to basic_string | stringstream.cpp:95:25:95:52 | call to basic_stringstream | TAINT | | stringstream.cpp:96:20:96:22 | call to basic_stringstream | stringstream.cpp:99:7:99:9 | ss5 | | | stringstream.cpp:96:20:96:22 | call to basic_stringstream | stringstream.cpp:106:7:106:9 | ss5 | | | stringstream.cpp:97:20:97:22 | call to basic_stringstream | stringstream.cpp:100:7:100:9 | ss6 | | @@ -1503,20 +1507,26 @@ | stringstream.cpp:99:13:99:36 | call to basic_stringstream | stringstream.cpp:99:7:99:9 | ref arg ss5 | TAINT | | stringstream.cpp:99:13:99:36 | call to basic_stringstream | stringstream.cpp:99:11:99:11 | call to operator= | TAINT | | stringstream.cpp:99:31:99:35 | abc | stringstream.cpp:99:31:99:35 | call to basic_string | TAINT | +| stringstream.cpp:99:31:99:35 | call to basic_string | stringstream.cpp:99:13:99:36 | call to basic_stringstream | TAINT | | stringstream.cpp:100:7:100:9 | ref arg ss6 | stringstream.cpp:107:7:107:9 | ss6 | | | stringstream.cpp:100:13:100:39 | call to basic_stringstream | stringstream.cpp:100:7:100:9 | ref arg ss6 | TAINT | | stringstream.cpp:100:13:100:39 | call to basic_stringstream | stringstream.cpp:100:11:100:11 | call to operator= | TAINT | | stringstream.cpp:100:31:100:36 | call to source | stringstream.cpp:100:31:100:38 | call to basic_string | TAINT | +| stringstream.cpp:100:31:100:38 | call to basic_string | stringstream.cpp:100:13:100:39 | call to basic_stringstream | TAINT | | stringstream.cpp:112:24:112:28 | abc | stringstream.cpp:112:24:112:28 | call to basic_string | TAINT | +| stringstream.cpp:112:24:112:28 | call to basic_string | stringstream.cpp:112:24:112:29 | call to basic_stringstream | TAINT | | stringstream.cpp:112:24:112:29 | call to basic_stringstream | stringstream.cpp:117:2:117:4 | ss1 | | | stringstream.cpp:112:24:112:29 | call to basic_stringstream | stringstream.cpp:120:7:120:9 | ss1 | | | stringstream.cpp:113:24:113:29 | call to source | stringstream.cpp:113:24:113:31 | call to basic_string | TAINT | +| stringstream.cpp:113:24:113:31 | call to basic_string | stringstream.cpp:113:24:113:32 | call to basic_stringstream | TAINT | | stringstream.cpp:113:24:113:32 | call to basic_stringstream | stringstream.cpp:117:11:117:13 | ss2 | | | stringstream.cpp:113:24:113:32 | call to basic_stringstream | stringstream.cpp:121:7:121:9 | ss2 | | | stringstream.cpp:114:24:114:28 | abc | stringstream.cpp:114:24:114:28 | call to basic_string | TAINT | +| stringstream.cpp:114:24:114:28 | call to basic_string | stringstream.cpp:114:24:114:29 | call to basic_stringstream | TAINT | | stringstream.cpp:114:24:114:29 | call to basic_stringstream | stringstream.cpp:118:11:118:13 | ss3 | | | stringstream.cpp:114:24:114:29 | call to basic_stringstream | stringstream.cpp:122:7:122:9 | ss3 | | | stringstream.cpp:115:24:115:29 | call to source | stringstream.cpp:115:24:115:31 | call to basic_string | TAINT | +| stringstream.cpp:115:24:115:31 | call to basic_string | stringstream.cpp:115:24:115:32 | call to basic_stringstream | TAINT | | stringstream.cpp:115:24:115:32 | call to basic_stringstream | stringstream.cpp:118:2:118:4 | ss4 | | | stringstream.cpp:115:24:115:32 | call to basic_stringstream | stringstream.cpp:123:7:123:9 | ss4 | | | stringstream.cpp:117:2:117:4 | ref arg ss1 | stringstream.cpp:120:7:120:9 | ss1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp index 9cae03894898..fad4b3baf934 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp @@ -97,14 +97,14 @@ void test_stringstream_constructors() std::stringstream ss6; sink(ss5 = std::stringstream("abc")); - sink(ss6 = std::stringstream(source())); // tainted [NOT DETECTED] + sink(ss6 = std::stringstream(source())); // tainted sink(ss1); - sink(ss2); // tainted [NOT DETECTED] + sink(ss2); // tainted sink(ss3); - sink(ss4); // tainted [NOT DETECTED] + sink(ss4); // tainted sink(ss5); - sink(ss6); // tainted [NOT DETECTED] + sink(ss6); // tainted } void test_stringstream_swap() @@ -118,9 +118,9 @@ void test_stringstream_swap() ss4.swap(ss3); sink(ss1); // tainted [NOT DETECTED] - sink(ss2); + sink(ss2); // [FALSE POSITIVE] sink(ss3); // tainted [NOT DETECTED] - sink(ss4); + sink(ss4); // [FALSE POSITIVE] } void test_stringstream_in() diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index e5d0ca7ab732..810274b6ab25 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -173,6 +173,12 @@ | stringstream.cpp:76:11:76:11 | call to operator<< | stringstream.cpp:70:32:70:37 | source | | stringstream.cpp:81:7:81:9 | ss2 | stringstream.cpp:70:32:70:37 | source | | stringstream.cpp:83:11:83:13 | call to str | stringstream.cpp:70:32:70:37 | source | +| stringstream.cpp:100:11:100:11 | call to operator= | stringstream.cpp:100:31:100:36 | call to source | +| stringstream.cpp:103:7:103:9 | ss2 | stringstream.cpp:91:19:91:24 | call to source | +| stringstream.cpp:105:7:105:9 | ss4 | stringstream.cpp:95:44:95:49 | call to source | +| stringstream.cpp:107:7:107:9 | ss6 | stringstream.cpp:100:31:100:36 | call to source | +| stringstream.cpp:121:7:121:9 | ss2 | stringstream.cpp:113:24:113:29 | call to source | +| stringstream.cpp:123:7:123:9 | ss4 | stringstream.cpp:115:24:115:29 | call to source | | stringstream.cpp:143:11:143:11 | call to operator<< | stringstream.cpp:143:14:143:19 | call to source | | structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source | | structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index a4cb807355aa..0bd42575a8b0 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -189,6 +189,12 @@ | stringstream.cpp:76:11:76:11 | stringstream.cpp:70:32:70:37 | AST only | | stringstream.cpp:81:7:81:9 | stringstream.cpp:70:32:70:37 | AST only | | stringstream.cpp:83:11:83:13 | stringstream.cpp:70:32:70:37 | AST only | +| stringstream.cpp:100:11:100:11 | stringstream.cpp:100:31:100:36 | AST only | +| stringstream.cpp:103:7:103:9 | stringstream.cpp:91:19:91:24 | AST only | +| stringstream.cpp:105:7:105:9 | stringstream.cpp:95:44:95:49 | AST only | +| stringstream.cpp:107:7:107:9 | stringstream.cpp:100:31:100:36 | AST only | +| stringstream.cpp:121:7:121:9 | stringstream.cpp:113:24:113:29 | AST only | +| stringstream.cpp:123:7:123:9 | stringstream.cpp:115:24:115:29 | AST only | | stringstream.cpp:143:11:143:11 | stringstream.cpp:143:14:143:21 | IR only | | stringstream.cpp:143:11:143:22 | stringstream.cpp:143:14:143:19 | IR only | | stringstream.cpp:143:11:143:22 | stringstream.cpp:143:14:143:21 | IR only | From 597757d76ffe4f1a737700d9ed32fbeaaf67c65e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 10 Sep 2020 11:04:11 +0100 Subject: [PATCH 3/8] C++: Model std::stringstream put and write. --- .../cpp/models/implementations/StdString.qll | 13 ++++++---- .../dataflow/taint-tests/localTaint.expected | 26 +++++++++++++++++++ .../dataflow/taint-tests/stringstream.cpp | 12 ++++----- .../dataflow/taint-tests/taint.expected | 6 +++++ .../dataflow/taint-tests/test_diff.expected | 6 +++++ 5 files changed, 52 insertions(+), 11 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index f48b0555de68..30655560a407 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -296,10 +296,11 @@ class StdBasicOStream extends TemplateClass { } /** - * The `std::ostream` function `operator<<` (defined as a member function). + * The `std::ostream` functions `operator<<` (defined as a member function), + * `put` and `write`. */ class StdOStreamOut extends DataFlowFunction, TaintFunction { - StdOStreamOut() { this.hasQualifiedName("std", "basic_ostream", "operator<<") } + StdOStreamOut() { this.hasQualifiedName("std", "basic_ostream", ["operator<<", "put", "write"]) } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to return value @@ -308,11 +309,11 @@ class StdOStreamOut extends DataFlowFunction, TaintFunction { } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // flow from parameter to qualifier + // flow from first parameter to qualifier input.isParameter(0) and output.isQualifierObject() or - // flow from parameter to return value + // flow from first parameter to return value input.isParameter(0) and output.isReturnValueDeref() or @@ -358,7 +359,9 @@ class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction { * input parameter. */ class StdStringStreamConstructor extends Constructor, TaintFunction { - StdStringStreamConstructor() { this.getDeclaringType().hasQualifiedName("std", "basic_stringstream") } + StdStringStreamConstructor() { + this.getDeclaringType().hasQualifiedName("std", "basic_stringstream") + } /** * Gets the index of a parameter to this function that is a string. diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 75a105da0a6c..99250c8c8180 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1449,11 +1449,35 @@ | stringstream.cpp:51:10:51:14 | abc | stringstream.cpp:51:10:51:14 | call to basic_string | TAINT | | stringstream.cpp:51:10:51:14 | call to basic_string | stringstream.cpp:51:2:51:4 | ref arg ss7 | TAINT | | stringstream.cpp:55:7:55:9 | ref arg ss8 | stringstream.cpp:58:7:58:9 | ss8 | | +| stringstream.cpp:55:15:55:17 | 97 | stringstream.cpp:55:7:55:9 | ref arg ss8 | TAINT | +| stringstream.cpp:55:15:55:17 | 97 | stringstream.cpp:55:11:55:13 | call to put | TAINT | | stringstream.cpp:56:7:56:9 | ref arg ss9 | stringstream.cpp:59:7:59:9 | ss9 | | +| stringstream.cpp:56:15:56:29 | call to source | stringstream.cpp:56:7:56:9 | ref arg ss9 | TAINT | +| stringstream.cpp:56:15:56:29 | call to source | stringstream.cpp:56:11:56:13 | call to put | TAINT | | stringstream.cpp:57:7:57:10 | ref arg ss10 | stringstream.cpp:60:7:60:10 | ss10 | | +| stringstream.cpp:57:12:57:14 | ref arg call to put | stringstream.cpp:57:7:57:10 | ref arg ss10 | TAINT | +| stringstream.cpp:57:16:57:18 | 97 | stringstream.cpp:57:7:57:10 | ref arg ss10 | TAINT | +| stringstream.cpp:57:16:57:18 | 97 | stringstream.cpp:57:12:57:14 | call to put | TAINT | +| stringstream.cpp:57:21:57:23 | ref arg call to put | stringstream.cpp:57:12:57:14 | ref arg call to put | TAINT | +| stringstream.cpp:57:25:57:39 | call to source | stringstream.cpp:57:12:57:14 | ref arg call to put | TAINT | +| stringstream.cpp:57:25:57:39 | call to source | stringstream.cpp:57:21:57:23 | call to put | TAINT | +| stringstream.cpp:57:48:57:50 | 122 | stringstream.cpp:57:21:57:23 | ref arg call to put | TAINT | +| stringstream.cpp:57:48:57:50 | 122 | stringstream.cpp:57:44:57:46 | call to put | TAINT | | stringstream.cpp:62:7:62:10 | ref arg ss11 | stringstream.cpp:65:7:65:10 | ss11 | | +| stringstream.cpp:62:18:62:24 | begin | stringstream.cpp:62:7:62:10 | ref arg ss11 | TAINT | +| stringstream.cpp:62:18:62:24 | begin | stringstream.cpp:62:12:62:16 | call to write | TAINT | | stringstream.cpp:63:7:63:10 | ref arg ss12 | stringstream.cpp:66:7:66:10 | ss12 | | +| stringstream.cpp:63:18:63:23 | call to source | stringstream.cpp:63:7:63:10 | ref arg ss12 | TAINT | +| stringstream.cpp:63:18:63:23 | call to source | stringstream.cpp:63:12:63:16 | call to write | TAINT | | stringstream.cpp:64:7:64:10 | ref arg ss13 | stringstream.cpp:67:7:67:10 | ss13 | | +| stringstream.cpp:64:12:64:16 | ref arg call to write | stringstream.cpp:64:7:64:10 | ref arg ss13 | TAINT | +| stringstream.cpp:64:18:64:24 | begin | stringstream.cpp:64:7:64:10 | ref arg ss13 | TAINT | +| stringstream.cpp:64:18:64:24 | begin | stringstream.cpp:64:12:64:16 | call to write | TAINT | +| stringstream.cpp:64:30:64:34 | ref arg call to write | stringstream.cpp:64:12:64:16 | ref arg call to write | TAINT | +| stringstream.cpp:64:36:64:41 | call to source | stringstream.cpp:64:12:64:16 | ref arg call to write | TAINT | +| stringstream.cpp:64:36:64:41 | call to source | stringstream.cpp:64:30:64:34 | call to write | TAINT | +| stringstream.cpp:64:60:64:64 | end | stringstream.cpp:64:30:64:34 | ref arg call to write | TAINT | +| stringstream.cpp:64:60:64:64 | end | stringstream.cpp:64:54:64:58 | call to write | TAINT | | stringstream.cpp:70:32:70:37 | source | stringstream.cpp:76:14:76:19 | source | | | stringstream.cpp:72:20:72:22 | call to basic_stringstream | stringstream.cpp:75:7:75:9 | ss1 | | | stringstream.cpp:72:20:72:22 | call to basic_stringstream | stringstream.cpp:77:7:77:9 | ss1 | | @@ -1737,6 +1761,8 @@ | stringstream.cpp:192:7:192:8 | ref arg ss | stringstream.cpp:195:7:195:8 | ss | | | stringstream.cpp:192:7:192:8 | ref arg ss | stringstream.cpp:196:7:196:8 | ss | | | stringstream.cpp:192:7:192:8 | ref arg ss | stringstream.cpp:197:7:197:8 | ss | | +| stringstream.cpp:192:14:192:16 | 97 | stringstream.cpp:192:7:192:8 | ref arg ss | TAINT | +| stringstream.cpp:192:14:192:16 | 97 | stringstream.cpp:192:10:192:12 | call to put | TAINT | | stringstream.cpp:193:7:193:8 | ref arg ss | stringstream.cpp:194:7:194:8 | ss | | | stringstream.cpp:193:7:193:8 | ref arg ss | stringstream.cpp:195:7:195:8 | ss | | | stringstream.cpp:193:7:193:8 | ref arg ss | stringstream.cpp:196:7:196:8 | ss | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp index fad4b3baf934..970b6a7b7c99 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp @@ -53,18 +53,18 @@ void test_stringstream_string(int amount) sink(ss7); // [FALSE POSITIVE] sink(ss8.put('a')); - sink(ss9.put(ns_char::source())); // tainted [NOT DETECTED] + sink(ss9.put(ns_char::source())); // tainted sink(ss10.put('a').put(ns_char::source()).put('z')); // tainted [NOT DETECTED] sink(ss8); - sink(ss9); // tainted [NOT DETECTED] - sink(ss10); // tainted [NOT DETECTED] + sink(ss9); // tainted + sink(ss10); // tainted sink(ss11.write("begin", 5)); - sink(ss12.write(source(), 5)); // tainted [NOT DETECTED] + sink(ss12.write(source(), 5)); // tainted sink(ss13.write("begin", 5).write(source(), amount).write("end", 3)); // tainted [NOT DETECTED] sink(ss11); - sink(ss12); // tainted [NOT DETECTED] - sink(ss13); // tainted [NOT DETECTED] + sink(ss12); // tainted + sink(ss13); // tainted } void test_stringstream_int(int source) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 810274b6ab25..408d185e3b47 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -170,6 +170,12 @@ | stringstream.cpp:46:11:46:13 | call to str | stringstream.cpp:29:16:29:21 | call to source | | stringstream.cpp:52:7:52:9 | ss6 | stringstream.cpp:49:10:49:15 | call to source | | stringstream.cpp:53:7:53:9 | ss7 | stringstream.cpp:50:10:50:15 | call to source | +| stringstream.cpp:56:11:56:13 | call to put | stringstream.cpp:56:15:56:29 | call to source | +| stringstream.cpp:59:7:59:9 | ss9 | stringstream.cpp:56:15:56:29 | call to source | +| stringstream.cpp:60:7:60:10 | ss10 | stringstream.cpp:57:25:57:39 | call to source | +| stringstream.cpp:63:12:63:16 | call to write | stringstream.cpp:63:18:63:23 | call to source | +| stringstream.cpp:66:7:66:10 | ss12 | stringstream.cpp:63:18:63:23 | call to source | +| stringstream.cpp:67:7:67:10 | ss13 | stringstream.cpp:64:36:64:41 | call to source | | stringstream.cpp:76:11:76:11 | call to operator<< | stringstream.cpp:70:32:70:37 | source | | stringstream.cpp:81:7:81:9 | ss2 | stringstream.cpp:70:32:70:37 | source | | stringstream.cpp:83:11:83:13 | call to str | stringstream.cpp:70:32:70:37 | source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index 0bd42575a8b0..0f4df62036d0 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -186,6 +186,12 @@ | stringstream.cpp:46:11:46:13 | stringstream.cpp:29:16:29:21 | AST only | | stringstream.cpp:52:7:52:9 | stringstream.cpp:49:10:49:15 | AST only | | stringstream.cpp:53:7:53:9 | stringstream.cpp:50:10:50:15 | AST only | +| stringstream.cpp:56:11:56:13 | stringstream.cpp:56:15:56:29 | AST only | +| stringstream.cpp:59:7:59:9 | stringstream.cpp:56:15:56:29 | AST only | +| stringstream.cpp:60:7:60:10 | stringstream.cpp:57:25:57:39 | AST only | +| stringstream.cpp:63:12:63:16 | stringstream.cpp:63:18:63:23 | AST only | +| stringstream.cpp:66:7:66:10 | stringstream.cpp:63:18:63:23 | AST only | +| stringstream.cpp:67:7:67:10 | stringstream.cpp:64:36:64:41 | AST only | | stringstream.cpp:76:11:76:11 | stringstream.cpp:70:32:70:37 | AST only | | stringstream.cpp:81:7:81:9 | stringstream.cpp:70:32:70:37 | AST only | | stringstream.cpp:83:11:83:13 | stringstream.cpp:70:32:70:37 | AST only | From dd53e3fe65d9281d930ee93fd26c8dcdd54b0c98 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 10 Sep 2020 11:32:52 +0100 Subject: [PATCH 4/8] C++: Fix data flow to return value. --- .../code/cpp/dataflow/internal/DataFlowUtil.qll | 17 ++++++++++++----- .../cpp/models/implementations/StdString.qll | 2 +- .../dataflow/taint-tests/localTaint.expected | 13 +++++++++++++ .../dataflow/taint-tests/stringstream.cpp | 4 ++-- .../dataflow/taint-tests/taint.expected | 2 ++ .../dataflow/taint-tests/test_diff.expected | 2 ++ 6 files changed, 32 insertions(+), 8 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll index 6647dda4072a..3ddeaef729c2 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -629,14 +629,21 @@ private predicate exprToExprStep_nocfg(Expr fromExpr, Expr toExpr) { // `ClassAggregateLiteral` (`{ capture1, ..., captureN }`). toExpr.(LambdaExpression).getInitializer() = fromExpr or + // Data flow through a function model. toExpr = any(Call call | - exists(DataFlowFunction f, FunctionInput inModel, FunctionOutput outModel, int iIn | - call.getTarget() = f and + exists(DataFlowFunction f, FunctionInput inModel, FunctionOutput outModel | f.hasDataFlow(inModel, outModel) and - outModel.isReturnValue() and - inModel.isParameter(iIn) and - fromExpr = call.getArgument(iIn) + ( + exists(int iIn | + inModel.isParameter(iIn) and + fromExpr = call.getArgument(iIn) + ) or + inModel.isQualifierObject() and + fromExpr = call.getQualifier() + ) and + call.getTarget() = f and + outModel.isReturnValue() ) ) } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 30655560a407..193117844076 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -304,7 +304,7 @@ class StdOStreamOut extends DataFlowFunction, TaintFunction { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to return value - input.isQualifierAddress() and + input.isQualifierObject() and output.isReturnValue() } diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 99250c8c8180..665fc70f5ab5 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1449,30 +1449,40 @@ | stringstream.cpp:51:10:51:14 | abc | stringstream.cpp:51:10:51:14 | call to basic_string | TAINT | | stringstream.cpp:51:10:51:14 | call to basic_string | stringstream.cpp:51:2:51:4 | ref arg ss7 | TAINT | | stringstream.cpp:55:7:55:9 | ref arg ss8 | stringstream.cpp:58:7:58:9 | ss8 | | +| stringstream.cpp:55:7:55:9 | ss8 | stringstream.cpp:55:11:55:13 | call to put | | | stringstream.cpp:55:15:55:17 | 97 | stringstream.cpp:55:7:55:9 | ref arg ss8 | TAINT | | stringstream.cpp:55:15:55:17 | 97 | stringstream.cpp:55:11:55:13 | call to put | TAINT | | stringstream.cpp:56:7:56:9 | ref arg ss9 | stringstream.cpp:59:7:59:9 | ss9 | | +| stringstream.cpp:56:7:56:9 | ss9 | stringstream.cpp:56:11:56:13 | call to put | | | stringstream.cpp:56:15:56:29 | call to source | stringstream.cpp:56:7:56:9 | ref arg ss9 | TAINT | | stringstream.cpp:56:15:56:29 | call to source | stringstream.cpp:56:11:56:13 | call to put | TAINT | | stringstream.cpp:57:7:57:10 | ref arg ss10 | stringstream.cpp:60:7:60:10 | ss10 | | +| stringstream.cpp:57:7:57:10 | ss10 | stringstream.cpp:57:12:57:14 | call to put | | +| stringstream.cpp:57:12:57:14 | call to put | stringstream.cpp:57:21:57:23 | call to put | | | stringstream.cpp:57:12:57:14 | ref arg call to put | stringstream.cpp:57:7:57:10 | ref arg ss10 | TAINT | | stringstream.cpp:57:16:57:18 | 97 | stringstream.cpp:57:7:57:10 | ref arg ss10 | TAINT | | stringstream.cpp:57:16:57:18 | 97 | stringstream.cpp:57:12:57:14 | call to put | TAINT | +| stringstream.cpp:57:21:57:23 | call to put | stringstream.cpp:57:44:57:46 | call to put | | | stringstream.cpp:57:21:57:23 | ref arg call to put | stringstream.cpp:57:12:57:14 | ref arg call to put | TAINT | | stringstream.cpp:57:25:57:39 | call to source | stringstream.cpp:57:12:57:14 | ref arg call to put | TAINT | | stringstream.cpp:57:25:57:39 | call to source | stringstream.cpp:57:21:57:23 | call to put | TAINT | | stringstream.cpp:57:48:57:50 | 122 | stringstream.cpp:57:21:57:23 | ref arg call to put | TAINT | | stringstream.cpp:57:48:57:50 | 122 | stringstream.cpp:57:44:57:46 | call to put | TAINT | | stringstream.cpp:62:7:62:10 | ref arg ss11 | stringstream.cpp:65:7:65:10 | ss11 | | +| stringstream.cpp:62:7:62:10 | ss11 | stringstream.cpp:62:12:62:16 | call to write | | | stringstream.cpp:62:18:62:24 | begin | stringstream.cpp:62:7:62:10 | ref arg ss11 | TAINT | | stringstream.cpp:62:18:62:24 | begin | stringstream.cpp:62:12:62:16 | call to write | TAINT | | stringstream.cpp:63:7:63:10 | ref arg ss12 | stringstream.cpp:66:7:66:10 | ss12 | | +| stringstream.cpp:63:7:63:10 | ss12 | stringstream.cpp:63:12:63:16 | call to write | | | stringstream.cpp:63:18:63:23 | call to source | stringstream.cpp:63:7:63:10 | ref arg ss12 | TAINT | | stringstream.cpp:63:18:63:23 | call to source | stringstream.cpp:63:12:63:16 | call to write | TAINT | | stringstream.cpp:64:7:64:10 | ref arg ss13 | stringstream.cpp:67:7:67:10 | ss13 | | +| stringstream.cpp:64:7:64:10 | ss13 | stringstream.cpp:64:12:64:16 | call to write | | +| stringstream.cpp:64:12:64:16 | call to write | stringstream.cpp:64:30:64:34 | call to write | | | stringstream.cpp:64:12:64:16 | ref arg call to write | stringstream.cpp:64:7:64:10 | ref arg ss13 | TAINT | | stringstream.cpp:64:18:64:24 | begin | stringstream.cpp:64:7:64:10 | ref arg ss13 | TAINT | | stringstream.cpp:64:18:64:24 | begin | stringstream.cpp:64:12:64:16 | call to write | TAINT | +| stringstream.cpp:64:30:64:34 | call to write | stringstream.cpp:64:54:64:58 | call to write | | | stringstream.cpp:64:30:64:34 | ref arg call to write | stringstream.cpp:64:12:64:16 | ref arg call to write | TAINT | | stringstream.cpp:64:36:64:41 | call to source | stringstream.cpp:64:12:64:16 | ref arg call to write | TAINT | | stringstream.cpp:64:36:64:41 | call to source | stringstream.cpp:64:30:64:34 | call to write | TAINT | @@ -1494,11 +1504,13 @@ | stringstream.cpp:75:7:75:9 | ref arg ss1 | stringstream.cpp:77:7:77:9 | ss1 | | | stringstream.cpp:75:7:75:9 | ref arg ss1 | stringstream.cpp:80:7:80:9 | ss1 | | | stringstream.cpp:75:7:75:9 | ref arg ss1 | stringstream.cpp:82:7:82:9 | ss1 | | +| stringstream.cpp:75:7:75:9 | ss1 | stringstream.cpp:75:11:75:11 | call to operator<< | | | stringstream.cpp:75:14:75:17 | 1234 | stringstream.cpp:75:7:75:9 | ref arg ss1 | TAINT | | stringstream.cpp:75:14:75:17 | 1234 | stringstream.cpp:75:11:75:11 | call to operator<< | TAINT | | stringstream.cpp:76:7:76:9 | ref arg ss2 | stringstream.cpp:78:7:78:9 | ss2 | | | stringstream.cpp:76:7:76:9 | ref arg ss2 | stringstream.cpp:81:7:81:9 | ss2 | | | stringstream.cpp:76:7:76:9 | ref arg ss2 | stringstream.cpp:83:7:83:9 | ss2 | | +| stringstream.cpp:76:7:76:9 | ss2 | stringstream.cpp:76:11:76:11 | call to operator<< | | | stringstream.cpp:76:14:76:19 | source | stringstream.cpp:76:7:76:9 | ref arg ss2 | TAINT | | stringstream.cpp:76:14:76:19 | source | stringstream.cpp:76:11:76:11 | call to operator<< | TAINT | | stringstream.cpp:77:7:77:9 | ref arg ss1 | stringstream.cpp:80:7:80:9 | ss1 | | @@ -1761,6 +1773,7 @@ | stringstream.cpp:192:7:192:8 | ref arg ss | stringstream.cpp:195:7:195:8 | ss | | | stringstream.cpp:192:7:192:8 | ref arg ss | stringstream.cpp:196:7:196:8 | ss | | | stringstream.cpp:192:7:192:8 | ref arg ss | stringstream.cpp:197:7:197:8 | ss | | +| stringstream.cpp:192:7:192:8 | ss | stringstream.cpp:192:10:192:12 | call to put | | | stringstream.cpp:192:14:192:16 | 97 | stringstream.cpp:192:7:192:8 | ref arg ss | TAINT | | stringstream.cpp:192:14:192:16 | 97 | stringstream.cpp:192:10:192:12 | call to put | TAINT | | stringstream.cpp:193:7:193:8 | ref arg ss | stringstream.cpp:194:7:194:8 | ss | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp index 970b6a7b7c99..d9b35b4a9e4a 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp @@ -54,14 +54,14 @@ void test_stringstream_string(int amount) sink(ss8.put('a')); sink(ss9.put(ns_char::source())); // tainted - sink(ss10.put('a').put(ns_char::source()).put('z')); // tainted [NOT DETECTED] + sink(ss10.put('a').put(ns_char::source()).put('z')); // tainted sink(ss8); sink(ss9); // tainted sink(ss10); // tainted sink(ss11.write("begin", 5)); sink(ss12.write(source(), 5)); // tainted - sink(ss13.write("begin", 5).write(source(), amount).write("end", 3)); // tainted [NOT DETECTED] + sink(ss13.write("begin", 5).write(source(), amount).write("end", 3)); // tainted sink(ss11); sink(ss12); // tainted sink(ss13); // tainted diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 408d185e3b47..4e8a7255feb4 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -171,9 +171,11 @@ | stringstream.cpp:52:7:52:9 | ss6 | stringstream.cpp:49:10:49:15 | call to source | | stringstream.cpp:53:7:53:9 | ss7 | stringstream.cpp:50:10:50:15 | call to source | | stringstream.cpp:56:11:56:13 | call to put | stringstream.cpp:56:15:56:29 | call to source | +| stringstream.cpp:57:44:57:46 | call to put | stringstream.cpp:57:25:57:39 | call to source | | stringstream.cpp:59:7:59:9 | ss9 | stringstream.cpp:56:15:56:29 | call to source | | stringstream.cpp:60:7:60:10 | ss10 | stringstream.cpp:57:25:57:39 | call to source | | stringstream.cpp:63:12:63:16 | call to write | stringstream.cpp:63:18:63:23 | call to source | +| stringstream.cpp:64:54:64:58 | call to write | stringstream.cpp:64:36:64:41 | call to source | | stringstream.cpp:66:7:66:10 | ss12 | stringstream.cpp:63:18:63:23 | call to source | | stringstream.cpp:67:7:67:10 | ss13 | stringstream.cpp:64:36:64:41 | call to source | | stringstream.cpp:76:11:76:11 | call to operator<< | stringstream.cpp:70:32:70:37 | source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index 0f4df62036d0..bc4213cb3dfb 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -187,9 +187,11 @@ | stringstream.cpp:52:7:52:9 | stringstream.cpp:49:10:49:15 | AST only | | stringstream.cpp:53:7:53:9 | stringstream.cpp:50:10:50:15 | AST only | | stringstream.cpp:56:11:56:13 | stringstream.cpp:56:15:56:29 | AST only | +| stringstream.cpp:57:44:57:46 | stringstream.cpp:57:25:57:39 | AST only | | stringstream.cpp:59:7:59:9 | stringstream.cpp:56:15:56:29 | AST only | | stringstream.cpp:60:7:60:10 | stringstream.cpp:57:25:57:39 | AST only | | stringstream.cpp:63:12:63:16 | stringstream.cpp:63:18:63:23 | AST only | +| stringstream.cpp:64:54:64:58 | stringstream.cpp:64:36:64:41 | AST only | | stringstream.cpp:66:7:66:10 | stringstream.cpp:63:18:63:23 | AST only | | stringstream.cpp:67:7:67:10 | stringstream.cpp:64:36:64:41 | AST only | | stringstream.cpp:76:11:76:11 | stringstream.cpp:70:32:70:37 | AST only | From d648150322cc8a746895bc52f76ed0dde2e028df Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 11 Sep 2020 11:07:55 +0100 Subject: [PATCH 5/8] C++: Autoformat. --- cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll index 3ddeaef729c2..d3e4ee9cc05e 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -638,7 +638,8 @@ private predicate exprToExprStep_nocfg(Expr fromExpr, Expr toExpr) { exists(int iIn | inModel.isParameter(iIn) and fromExpr = call.getArgument(iIn) - ) or + ) + or inModel.isQualifierObject() and fromExpr = call.getQualifier() ) and From d3ca140eeb7a0aa2901047a07fe079320d0d619d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 11 Sep 2020 15:04:52 +0100 Subject: [PATCH 6/8] C++: Account for pointer / reference parameters to operator<<. --- .../code/cpp/models/implementations/StdString.qll | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 193117844076..178f5d399f24 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -309,14 +309,20 @@ class StdOStreamOut extends DataFlowFunction, TaintFunction { } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // flow from first parameter to qualifier + // flow from first parameter (value or pointer) to qualifier input.isParameter(0) and output.isQualifierObject() or - // flow from first parameter to return value + input.isParameterDeref(0) and + output.isQualifierObject() + or + // flow from first parameter (value or pointer) to return value input.isParameter(0) and output.isReturnValueDeref() or + input.isParameterDeref(0) and + output.isReturnValueDeref() + or // reverse flow from returned reference to the qualifier input.isReturnValueDeref() and output.isQualifierObject() From b404a339a4d0982533d76cb0187b1908fc19b9a4 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 11 Sep 2020 16:15:47 +0100 Subject: [PATCH 7/8] C++: Correct isQualifierObject -> isQualifierAddress. --- .../code/cpp/models/implementations/StdString.qll | 2 +- .../dataflow/taint-tests/localTaint.expected | 13 ------------- .../dataflow/taint-tests/taint.expected | 2 -- .../dataflow/taint-tests/test_diff.expected | 2 -- 4 files changed, 1 insertion(+), 18 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 178f5d399f24..f5fc470a42cb 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -304,7 +304,7 @@ class StdOStreamOut extends DataFlowFunction, TaintFunction { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to return value - input.isQualifierObject() and + input.isQualifierAddress() and output.isReturnValue() } diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 665fc70f5ab5..99250c8c8180 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1449,40 +1449,30 @@ | stringstream.cpp:51:10:51:14 | abc | stringstream.cpp:51:10:51:14 | call to basic_string | TAINT | | stringstream.cpp:51:10:51:14 | call to basic_string | stringstream.cpp:51:2:51:4 | ref arg ss7 | TAINT | | stringstream.cpp:55:7:55:9 | ref arg ss8 | stringstream.cpp:58:7:58:9 | ss8 | | -| stringstream.cpp:55:7:55:9 | ss8 | stringstream.cpp:55:11:55:13 | call to put | | | stringstream.cpp:55:15:55:17 | 97 | stringstream.cpp:55:7:55:9 | ref arg ss8 | TAINT | | stringstream.cpp:55:15:55:17 | 97 | stringstream.cpp:55:11:55:13 | call to put | TAINT | | stringstream.cpp:56:7:56:9 | ref arg ss9 | stringstream.cpp:59:7:59:9 | ss9 | | -| stringstream.cpp:56:7:56:9 | ss9 | stringstream.cpp:56:11:56:13 | call to put | | | stringstream.cpp:56:15:56:29 | call to source | stringstream.cpp:56:7:56:9 | ref arg ss9 | TAINT | | stringstream.cpp:56:15:56:29 | call to source | stringstream.cpp:56:11:56:13 | call to put | TAINT | | stringstream.cpp:57:7:57:10 | ref arg ss10 | stringstream.cpp:60:7:60:10 | ss10 | | -| stringstream.cpp:57:7:57:10 | ss10 | stringstream.cpp:57:12:57:14 | call to put | | -| stringstream.cpp:57:12:57:14 | call to put | stringstream.cpp:57:21:57:23 | call to put | | | stringstream.cpp:57:12:57:14 | ref arg call to put | stringstream.cpp:57:7:57:10 | ref arg ss10 | TAINT | | stringstream.cpp:57:16:57:18 | 97 | stringstream.cpp:57:7:57:10 | ref arg ss10 | TAINT | | stringstream.cpp:57:16:57:18 | 97 | stringstream.cpp:57:12:57:14 | call to put | TAINT | -| stringstream.cpp:57:21:57:23 | call to put | stringstream.cpp:57:44:57:46 | call to put | | | stringstream.cpp:57:21:57:23 | ref arg call to put | stringstream.cpp:57:12:57:14 | ref arg call to put | TAINT | | stringstream.cpp:57:25:57:39 | call to source | stringstream.cpp:57:12:57:14 | ref arg call to put | TAINT | | stringstream.cpp:57:25:57:39 | call to source | stringstream.cpp:57:21:57:23 | call to put | TAINT | | stringstream.cpp:57:48:57:50 | 122 | stringstream.cpp:57:21:57:23 | ref arg call to put | TAINT | | stringstream.cpp:57:48:57:50 | 122 | stringstream.cpp:57:44:57:46 | call to put | TAINT | | stringstream.cpp:62:7:62:10 | ref arg ss11 | stringstream.cpp:65:7:65:10 | ss11 | | -| stringstream.cpp:62:7:62:10 | ss11 | stringstream.cpp:62:12:62:16 | call to write | | | stringstream.cpp:62:18:62:24 | begin | stringstream.cpp:62:7:62:10 | ref arg ss11 | TAINT | | stringstream.cpp:62:18:62:24 | begin | stringstream.cpp:62:12:62:16 | call to write | TAINT | | stringstream.cpp:63:7:63:10 | ref arg ss12 | stringstream.cpp:66:7:66:10 | ss12 | | -| stringstream.cpp:63:7:63:10 | ss12 | stringstream.cpp:63:12:63:16 | call to write | | | stringstream.cpp:63:18:63:23 | call to source | stringstream.cpp:63:7:63:10 | ref arg ss12 | TAINT | | stringstream.cpp:63:18:63:23 | call to source | stringstream.cpp:63:12:63:16 | call to write | TAINT | | stringstream.cpp:64:7:64:10 | ref arg ss13 | stringstream.cpp:67:7:67:10 | ss13 | | -| stringstream.cpp:64:7:64:10 | ss13 | stringstream.cpp:64:12:64:16 | call to write | | -| stringstream.cpp:64:12:64:16 | call to write | stringstream.cpp:64:30:64:34 | call to write | | | stringstream.cpp:64:12:64:16 | ref arg call to write | stringstream.cpp:64:7:64:10 | ref arg ss13 | TAINT | | stringstream.cpp:64:18:64:24 | begin | stringstream.cpp:64:7:64:10 | ref arg ss13 | TAINT | | stringstream.cpp:64:18:64:24 | begin | stringstream.cpp:64:12:64:16 | call to write | TAINT | -| stringstream.cpp:64:30:64:34 | call to write | stringstream.cpp:64:54:64:58 | call to write | | | stringstream.cpp:64:30:64:34 | ref arg call to write | stringstream.cpp:64:12:64:16 | ref arg call to write | TAINT | | stringstream.cpp:64:36:64:41 | call to source | stringstream.cpp:64:12:64:16 | ref arg call to write | TAINT | | stringstream.cpp:64:36:64:41 | call to source | stringstream.cpp:64:30:64:34 | call to write | TAINT | @@ -1504,13 +1494,11 @@ | stringstream.cpp:75:7:75:9 | ref arg ss1 | stringstream.cpp:77:7:77:9 | ss1 | | | stringstream.cpp:75:7:75:9 | ref arg ss1 | stringstream.cpp:80:7:80:9 | ss1 | | | stringstream.cpp:75:7:75:9 | ref arg ss1 | stringstream.cpp:82:7:82:9 | ss1 | | -| stringstream.cpp:75:7:75:9 | ss1 | stringstream.cpp:75:11:75:11 | call to operator<< | | | stringstream.cpp:75:14:75:17 | 1234 | stringstream.cpp:75:7:75:9 | ref arg ss1 | TAINT | | stringstream.cpp:75:14:75:17 | 1234 | stringstream.cpp:75:11:75:11 | call to operator<< | TAINT | | stringstream.cpp:76:7:76:9 | ref arg ss2 | stringstream.cpp:78:7:78:9 | ss2 | | | stringstream.cpp:76:7:76:9 | ref arg ss2 | stringstream.cpp:81:7:81:9 | ss2 | | | stringstream.cpp:76:7:76:9 | ref arg ss2 | stringstream.cpp:83:7:83:9 | ss2 | | -| stringstream.cpp:76:7:76:9 | ss2 | stringstream.cpp:76:11:76:11 | call to operator<< | | | stringstream.cpp:76:14:76:19 | source | stringstream.cpp:76:7:76:9 | ref arg ss2 | TAINT | | stringstream.cpp:76:14:76:19 | source | stringstream.cpp:76:11:76:11 | call to operator<< | TAINT | | stringstream.cpp:77:7:77:9 | ref arg ss1 | stringstream.cpp:80:7:80:9 | ss1 | | @@ -1773,7 +1761,6 @@ | stringstream.cpp:192:7:192:8 | ref arg ss | stringstream.cpp:195:7:195:8 | ss | | | stringstream.cpp:192:7:192:8 | ref arg ss | stringstream.cpp:196:7:196:8 | ss | | | stringstream.cpp:192:7:192:8 | ref arg ss | stringstream.cpp:197:7:197:8 | ss | | -| stringstream.cpp:192:7:192:8 | ss | stringstream.cpp:192:10:192:12 | call to put | | | stringstream.cpp:192:14:192:16 | 97 | stringstream.cpp:192:7:192:8 | ref arg ss | TAINT | | stringstream.cpp:192:14:192:16 | 97 | stringstream.cpp:192:10:192:12 | call to put | TAINT | | stringstream.cpp:193:7:193:8 | ref arg ss | stringstream.cpp:194:7:194:8 | ss | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 4e8a7255feb4..408d185e3b47 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -171,11 +171,9 @@ | stringstream.cpp:52:7:52:9 | ss6 | stringstream.cpp:49:10:49:15 | call to source | | stringstream.cpp:53:7:53:9 | ss7 | stringstream.cpp:50:10:50:15 | call to source | | stringstream.cpp:56:11:56:13 | call to put | stringstream.cpp:56:15:56:29 | call to source | -| stringstream.cpp:57:44:57:46 | call to put | stringstream.cpp:57:25:57:39 | call to source | | stringstream.cpp:59:7:59:9 | ss9 | stringstream.cpp:56:15:56:29 | call to source | | stringstream.cpp:60:7:60:10 | ss10 | stringstream.cpp:57:25:57:39 | call to source | | stringstream.cpp:63:12:63:16 | call to write | stringstream.cpp:63:18:63:23 | call to source | -| stringstream.cpp:64:54:64:58 | call to write | stringstream.cpp:64:36:64:41 | call to source | | stringstream.cpp:66:7:66:10 | ss12 | stringstream.cpp:63:18:63:23 | call to source | | stringstream.cpp:67:7:67:10 | ss13 | stringstream.cpp:64:36:64:41 | call to source | | stringstream.cpp:76:11:76:11 | call to operator<< | stringstream.cpp:70:32:70:37 | source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index bc4213cb3dfb..0f4df62036d0 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -187,11 +187,9 @@ | stringstream.cpp:52:7:52:9 | stringstream.cpp:49:10:49:15 | AST only | | stringstream.cpp:53:7:53:9 | stringstream.cpp:50:10:50:15 | AST only | | stringstream.cpp:56:11:56:13 | stringstream.cpp:56:15:56:29 | AST only | -| stringstream.cpp:57:44:57:46 | stringstream.cpp:57:25:57:39 | AST only | | stringstream.cpp:59:7:59:9 | stringstream.cpp:56:15:56:29 | AST only | | stringstream.cpp:60:7:60:10 | stringstream.cpp:57:25:57:39 | AST only | | stringstream.cpp:63:12:63:16 | stringstream.cpp:63:18:63:23 | AST only | -| stringstream.cpp:64:54:64:58 | stringstream.cpp:64:36:64:41 | AST only | | stringstream.cpp:66:7:66:10 | stringstream.cpp:63:18:63:23 | AST only | | stringstream.cpp:67:7:67:10 | stringstream.cpp:64:36:64:41 | AST only | | stringstream.cpp:76:11:76:11 | stringstream.cpp:70:32:70:37 | AST only | From 6b035df660c4a9df533a4c202d0b1b0baa9ea4d4 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 11 Sep 2020 17:16:55 +0100 Subject: [PATCH 8/8] C++: Repair taint flow from previous. --- .../cpp/dataflow/internal/DataFlowUtil.qll | 3 + .../dataflow/taint-tests/localTaint.expected | 55 ++++++++++++------- .../dataflow/taint-tests/taint.expected | 2 + .../dataflow/taint-tests/test_diff.expected | 2 + 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll index d3e4ee9cc05e..d84dd49e1666 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -642,6 +642,9 @@ private predicate exprToExprStep_nocfg(Expr fromExpr, Expr toExpr) { or inModel.isQualifierObject() and fromExpr = call.getQualifier() + or + inModel.isQualifierAddress() and + fromExpr = call.getQualifier() ) and call.getTarget() = f and outModel.isReturnValue() diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 99250c8c8180..ea4d5438614e 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -444,19 +444,19 @@ | standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:42:14:42:20 | source1 | | | standalone_iterators.cpp:40:11:40:17 | source1 | standalone_iterators.cpp:40:10:40:10 | call to operator* | TAINT | | standalone_iterators.cpp:41:12:41:18 | ref arg source1 | standalone_iterators.cpp:42:14:42:20 | source1 | | -| standalone_iterators.cpp:41:12:41:18 | source1 | standalone_iterators.cpp:41:19:41:19 | call to operator++ | TAINT | +| standalone_iterators.cpp:41:12:41:18 | source1 | standalone_iterators.cpp:41:19:41:19 | call to operator++ | | | standalone_iterators.cpp:41:19:41:19 | call to operator++ | standalone_iterators.cpp:41:10:41:10 | call to operator* | TAINT | | standalone_iterators.cpp:42:12:42:12 | call to operator++ | standalone_iterators.cpp:42:10:42:10 | call to operator* | TAINT | -| standalone_iterators.cpp:42:14:42:20 | source1 | standalone_iterators.cpp:42:12:42:12 | call to operator++ | TAINT | +| standalone_iterators.cpp:42:14:42:20 | source1 | standalone_iterators.cpp:42:12:42:12 | call to operator++ | | | standalone_iterators.cpp:45:39:45:45 | source1 | standalone_iterators.cpp:46:11:46:17 | source1 | | | standalone_iterators.cpp:45:39:45:45 | source1 | standalone_iterators.cpp:47:12:47:18 | source1 | | | standalone_iterators.cpp:45:39:45:45 | source1 | standalone_iterators.cpp:48:14:48:20 | source1 | | | standalone_iterators.cpp:46:11:46:17 | source1 | standalone_iterators.cpp:46:10:46:10 | call to operator* | TAINT | | standalone_iterators.cpp:47:12:47:18 | ref arg source1 | standalone_iterators.cpp:48:14:48:20 | source1 | | -| standalone_iterators.cpp:47:12:47:18 | source1 | standalone_iterators.cpp:47:19:47:19 | call to operator++ | TAINT | +| standalone_iterators.cpp:47:12:47:18 | source1 | standalone_iterators.cpp:47:19:47:19 | call to operator++ | | | standalone_iterators.cpp:47:19:47:19 | call to operator++ | standalone_iterators.cpp:47:10:47:10 | call to operator* | TAINT | | standalone_iterators.cpp:48:12:48:12 | call to operator++ | standalone_iterators.cpp:48:10:48:10 | call to operator* | TAINT | -| standalone_iterators.cpp:48:14:48:20 | source1 | standalone_iterators.cpp:48:12:48:12 | call to operator++ | TAINT | +| standalone_iterators.cpp:48:14:48:20 | source1 | standalone_iterators.cpp:48:12:48:12 | call to operator++ | | | standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:52:11:52:17 | source1 | | | standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:53:12:53:18 | source1 | | | standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:54:14:54:20 | source1 | | @@ -528,7 +528,7 @@ | string.cpp:119:16:119:24 | call to basic_string | string.cpp:124:50:124:50 | s | | | string.cpp:119:16:119:24 | call to basic_string | string.cpp:128:16:128:16 | s | | | string.cpp:120:15:120:15 | (__begin) | string.cpp:120:15:120:15 | call to operator* | TAINT | -| string.cpp:120:15:120:15 | (__begin) | string.cpp:120:15:120:15 | call to operator++ | TAINT | +| string.cpp:120:15:120:15 | (__begin) | string.cpp:120:15:120:15 | call to operator++ | | | string.cpp:120:15:120:15 | (__end) | string.cpp:120:15:120:15 | call to iterator | | | string.cpp:120:15:120:15 | (__range) | string.cpp:120:15:120:15 | call to begin | TAINT | | string.cpp:120:15:120:15 | (__range) | string.cpp:120:15:120:15 | call to end | TAINT | @@ -553,13 +553,13 @@ | string.cpp:124:50:124:50 | ref arg s | string.cpp:124:50:124:50 | s | | | string.cpp:124:50:124:50 | ref arg s | string.cpp:128:16:128:16 | s | | | string.cpp:124:50:124:50 | s | string.cpp:124:52:124:54 | call to end | TAINT | -| string.cpp:124:61:124:62 | it | string.cpp:124:59:124:59 | call to operator++ | TAINT | +| string.cpp:124:61:124:62 | it | string.cpp:124:59:124:59 | call to operator++ | | | string.cpp:124:61:124:62 | ref arg it | string.cpp:124:44:124:45 | it | | | string.cpp:124:61:124:62 | ref arg it | string.cpp:124:61:124:62 | it | | | string.cpp:124:61:124:62 | ref arg it | string.cpp:125:9:125:10 | it | | | string.cpp:125:9:125:10 | it | string.cpp:125:8:125:8 | call to operator* | TAINT | | string.cpp:128:16:128:16 | (__begin) | string.cpp:128:16:128:16 | call to operator* | TAINT | -| string.cpp:128:16:128:16 | (__begin) | string.cpp:128:16:128:16 | call to operator++ | TAINT | +| string.cpp:128:16:128:16 | (__begin) | string.cpp:128:16:128:16 | call to operator++ | | | string.cpp:128:16:128:16 | (__end) | string.cpp:128:16:128:16 | call to iterator | | | string.cpp:128:16:128:16 | (__range) | string.cpp:128:16:128:16 | call to begin | TAINT | | string.cpp:128:16:128:16 | (__range) | string.cpp:128:16:128:16 | call to end | TAINT | @@ -578,7 +578,7 @@ | string.cpp:132:28:132:33 | call to source | string.cpp:132:28:132:36 | call to basic_string | TAINT | | string.cpp:132:28:132:36 | call to basic_string | string.cpp:133:22:133:28 | const_s | | | string.cpp:133:22:133:22 | (__begin) | string.cpp:133:22:133:22 | call to operator* | TAINT | -| string.cpp:133:22:133:22 | (__begin) | string.cpp:133:22:133:22 | call to operator++ | TAINT | +| string.cpp:133:22:133:22 | (__begin) | string.cpp:133:22:133:22 | call to operator++ | | | string.cpp:133:22:133:22 | (__range) | string.cpp:133:22:133:22 | call to begin | TAINT | | string.cpp:133:22:133:22 | (__range) | string.cpp:133:22:133:22 | call to end | TAINT | | string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | | @@ -981,38 +981,38 @@ | string.cpp:396:8:396:9 | i2 | string.cpp:396:3:396:9 | ... = ... | | | string.cpp:396:8:396:9 | i2 | string.cpp:397:12:397:13 | i3 | | | string.cpp:397:10:397:10 | call to operator++ | string.cpp:397:8:397:8 | call to operator* | TAINT | -| string.cpp:397:12:397:13 | i3 | string.cpp:397:10:397:10 | call to operator++ | TAINT | +| string.cpp:397:12:397:13 | i3 | string.cpp:397:10:397:10 | call to operator++ | | | string.cpp:398:8:398:9 | i2 | string.cpp:398:3:398:9 | ... = ... | | | string.cpp:398:8:398:9 | i2 | string.cpp:399:12:399:13 | i4 | | | string.cpp:399:10:399:10 | call to operator-- | string.cpp:399:8:399:8 | call to operator* | TAINT | -| string.cpp:399:12:399:13 | i4 | string.cpp:399:10:399:10 | call to operator-- | TAINT | +| string.cpp:399:12:399:13 | i4 | string.cpp:399:10:399:10 | call to operator-- | | | string.cpp:400:8:400:9 | i2 | string.cpp:400:3:400:9 | ... = ... | | | string.cpp:400:8:400:9 | i2 | string.cpp:401:3:401:4 | i5 | | | string.cpp:400:8:400:9 | i2 | string.cpp:402:9:402:10 | i5 | | -| string.cpp:401:3:401:4 | i5 | string.cpp:401:5:401:5 | call to operator++ | TAINT | +| string.cpp:401:3:401:4 | i5 | string.cpp:401:5:401:5 | call to operator++ | | | string.cpp:401:3:401:4 | ref arg i5 | string.cpp:402:9:402:10 | i5 | | | string.cpp:402:9:402:10 | i5 | string.cpp:402:8:402:8 | call to operator* | TAINT | | string.cpp:403:8:403:9 | i2 | string.cpp:403:3:403:9 | ... = ... | | | string.cpp:403:8:403:9 | i2 | string.cpp:404:3:404:4 | i6 | | | string.cpp:403:8:403:9 | i2 | string.cpp:405:9:405:10 | i6 | | -| string.cpp:404:3:404:4 | i6 | string.cpp:404:5:404:5 | call to operator-- | TAINT | +| string.cpp:404:3:404:4 | i6 | string.cpp:404:5:404:5 | call to operator-- | | | string.cpp:404:3:404:4 | ref arg i6 | string.cpp:405:9:405:10 | i6 | | | string.cpp:405:9:405:10 | i6 | string.cpp:405:8:405:8 | call to operator* | TAINT | | string.cpp:406:8:406:9 | i2 | string.cpp:406:3:406:9 | ... = ... | | | string.cpp:406:8:406:9 | i2 | string.cpp:407:10:407:11 | i7 | | -| string.cpp:407:10:407:11 | i7 | string.cpp:407:12:407:12 | call to operator+= | TAINT | +| string.cpp:407:10:407:11 | i7 | string.cpp:407:12:407:12 | call to operator+= | | | string.cpp:407:12:407:12 | call to operator+= | string.cpp:407:8:407:8 | call to operator* | TAINT | | string.cpp:407:14:407:14 | 1 | string.cpp:407:12:407:12 | call to operator+= | | | string.cpp:408:8:408:9 | i2 | string.cpp:408:3:408:9 | ... = ... | | | string.cpp:408:8:408:9 | i2 | string.cpp:409:10:409:11 | i8 | | -| string.cpp:409:10:409:11 | i8 | string.cpp:409:12:409:12 | call to operator-= | TAINT | +| string.cpp:409:10:409:11 | i8 | string.cpp:409:12:409:12 | call to operator-= | | | string.cpp:409:12:409:12 | call to operator-= | string.cpp:409:8:409:8 | call to operator* | TAINT | | string.cpp:409:14:409:14 | 1 | string.cpp:409:12:409:12 | call to operator-= | | | string.cpp:411:8:411:9 | s2 | string.cpp:411:11:411:13 | call to end | TAINT | | string.cpp:411:11:411:13 | call to end | string.cpp:411:3:411:15 | ... = ... | | | string.cpp:411:11:411:13 | call to end | string.cpp:412:5:412:6 | i9 | | | string.cpp:411:11:411:13 | call to end | string.cpp:413:9:413:10 | i9 | | -| string.cpp:412:5:412:6 | i9 | string.cpp:412:3:412:3 | call to operator-- | TAINT | +| string.cpp:412:5:412:6 | i9 | string.cpp:412:3:412:3 | call to operator-- | | | string.cpp:412:5:412:6 | ref arg i9 | string.cpp:413:9:413:10 | i9 | | | string.cpp:413:9:413:10 | i9 | string.cpp:413:8:413:8 | call to operator* | TAINT | | string.cpp:419:17:419:20 | aa | string.cpp:419:17:419:21 | call to basic_string | TAINT | @@ -1449,30 +1449,40 @@ | stringstream.cpp:51:10:51:14 | abc | stringstream.cpp:51:10:51:14 | call to basic_string | TAINT | | stringstream.cpp:51:10:51:14 | call to basic_string | stringstream.cpp:51:2:51:4 | ref arg ss7 | TAINT | | stringstream.cpp:55:7:55:9 | ref arg ss8 | stringstream.cpp:58:7:58:9 | ss8 | | +| stringstream.cpp:55:7:55:9 | ss8 | stringstream.cpp:55:11:55:13 | call to put | | | stringstream.cpp:55:15:55:17 | 97 | stringstream.cpp:55:7:55:9 | ref arg ss8 | TAINT | | stringstream.cpp:55:15:55:17 | 97 | stringstream.cpp:55:11:55:13 | call to put | TAINT | | stringstream.cpp:56:7:56:9 | ref arg ss9 | stringstream.cpp:59:7:59:9 | ss9 | | +| stringstream.cpp:56:7:56:9 | ss9 | stringstream.cpp:56:11:56:13 | call to put | | | stringstream.cpp:56:15:56:29 | call to source | stringstream.cpp:56:7:56:9 | ref arg ss9 | TAINT | | stringstream.cpp:56:15:56:29 | call to source | stringstream.cpp:56:11:56:13 | call to put | TAINT | | stringstream.cpp:57:7:57:10 | ref arg ss10 | stringstream.cpp:60:7:60:10 | ss10 | | +| stringstream.cpp:57:7:57:10 | ss10 | stringstream.cpp:57:12:57:14 | call to put | | +| stringstream.cpp:57:12:57:14 | call to put | stringstream.cpp:57:21:57:23 | call to put | | | stringstream.cpp:57:12:57:14 | ref arg call to put | stringstream.cpp:57:7:57:10 | ref arg ss10 | TAINT | | stringstream.cpp:57:16:57:18 | 97 | stringstream.cpp:57:7:57:10 | ref arg ss10 | TAINT | | stringstream.cpp:57:16:57:18 | 97 | stringstream.cpp:57:12:57:14 | call to put | TAINT | +| stringstream.cpp:57:21:57:23 | call to put | stringstream.cpp:57:44:57:46 | call to put | | | stringstream.cpp:57:21:57:23 | ref arg call to put | stringstream.cpp:57:12:57:14 | ref arg call to put | TAINT | | stringstream.cpp:57:25:57:39 | call to source | stringstream.cpp:57:12:57:14 | ref arg call to put | TAINT | | stringstream.cpp:57:25:57:39 | call to source | stringstream.cpp:57:21:57:23 | call to put | TAINT | | stringstream.cpp:57:48:57:50 | 122 | stringstream.cpp:57:21:57:23 | ref arg call to put | TAINT | | stringstream.cpp:57:48:57:50 | 122 | stringstream.cpp:57:44:57:46 | call to put | TAINT | | stringstream.cpp:62:7:62:10 | ref arg ss11 | stringstream.cpp:65:7:65:10 | ss11 | | +| stringstream.cpp:62:7:62:10 | ss11 | stringstream.cpp:62:12:62:16 | call to write | | | stringstream.cpp:62:18:62:24 | begin | stringstream.cpp:62:7:62:10 | ref arg ss11 | TAINT | | stringstream.cpp:62:18:62:24 | begin | stringstream.cpp:62:12:62:16 | call to write | TAINT | | stringstream.cpp:63:7:63:10 | ref arg ss12 | stringstream.cpp:66:7:66:10 | ss12 | | +| stringstream.cpp:63:7:63:10 | ss12 | stringstream.cpp:63:12:63:16 | call to write | | | stringstream.cpp:63:18:63:23 | call to source | stringstream.cpp:63:7:63:10 | ref arg ss12 | TAINT | | stringstream.cpp:63:18:63:23 | call to source | stringstream.cpp:63:12:63:16 | call to write | TAINT | | stringstream.cpp:64:7:64:10 | ref arg ss13 | stringstream.cpp:67:7:67:10 | ss13 | | +| stringstream.cpp:64:7:64:10 | ss13 | stringstream.cpp:64:12:64:16 | call to write | | +| stringstream.cpp:64:12:64:16 | call to write | stringstream.cpp:64:30:64:34 | call to write | | | stringstream.cpp:64:12:64:16 | ref arg call to write | stringstream.cpp:64:7:64:10 | ref arg ss13 | TAINT | | stringstream.cpp:64:18:64:24 | begin | stringstream.cpp:64:7:64:10 | ref arg ss13 | TAINT | | stringstream.cpp:64:18:64:24 | begin | stringstream.cpp:64:12:64:16 | call to write | TAINT | +| stringstream.cpp:64:30:64:34 | call to write | stringstream.cpp:64:54:64:58 | call to write | | | stringstream.cpp:64:30:64:34 | ref arg call to write | stringstream.cpp:64:12:64:16 | ref arg call to write | TAINT | | stringstream.cpp:64:36:64:41 | call to source | stringstream.cpp:64:12:64:16 | ref arg call to write | TAINT | | stringstream.cpp:64:36:64:41 | call to source | stringstream.cpp:64:30:64:34 | call to write | TAINT | @@ -1494,11 +1504,13 @@ | stringstream.cpp:75:7:75:9 | ref arg ss1 | stringstream.cpp:77:7:77:9 | ss1 | | | stringstream.cpp:75:7:75:9 | ref arg ss1 | stringstream.cpp:80:7:80:9 | ss1 | | | stringstream.cpp:75:7:75:9 | ref arg ss1 | stringstream.cpp:82:7:82:9 | ss1 | | +| stringstream.cpp:75:7:75:9 | ss1 | stringstream.cpp:75:11:75:11 | call to operator<< | | | stringstream.cpp:75:14:75:17 | 1234 | stringstream.cpp:75:7:75:9 | ref arg ss1 | TAINT | | stringstream.cpp:75:14:75:17 | 1234 | stringstream.cpp:75:11:75:11 | call to operator<< | TAINT | | stringstream.cpp:76:7:76:9 | ref arg ss2 | stringstream.cpp:78:7:78:9 | ss2 | | | stringstream.cpp:76:7:76:9 | ref arg ss2 | stringstream.cpp:81:7:81:9 | ss2 | | | stringstream.cpp:76:7:76:9 | ref arg ss2 | stringstream.cpp:83:7:83:9 | ss2 | | +| stringstream.cpp:76:7:76:9 | ss2 | stringstream.cpp:76:11:76:11 | call to operator<< | | | stringstream.cpp:76:14:76:19 | source | stringstream.cpp:76:7:76:9 | ref arg ss2 | TAINT | | stringstream.cpp:76:14:76:19 | source | stringstream.cpp:76:11:76:11 | call to operator<< | TAINT | | stringstream.cpp:77:7:77:9 | ref arg ss1 | stringstream.cpp:80:7:80:9 | ss1 | | @@ -1761,6 +1773,7 @@ | stringstream.cpp:192:7:192:8 | ref arg ss | stringstream.cpp:195:7:195:8 | ss | | | stringstream.cpp:192:7:192:8 | ref arg ss | stringstream.cpp:196:7:196:8 | ss | | | stringstream.cpp:192:7:192:8 | ref arg ss | stringstream.cpp:197:7:197:8 | ss | | +| stringstream.cpp:192:7:192:8 | ss | stringstream.cpp:192:10:192:12 | call to put | | | stringstream.cpp:192:14:192:16 | 97 | stringstream.cpp:192:7:192:8 | ref arg ss | TAINT | | stringstream.cpp:192:14:192:16 | 97 | stringstream.cpp:192:10:192:12 | call to put | TAINT | | stringstream.cpp:193:7:193:8 | ref arg ss | stringstream.cpp:194:7:194:8 | ss | | @@ -2597,7 +2610,7 @@ | vector.cpp:17:21:17:33 | call to vector | vector.cpp:35:1:35:1 | v | | | vector.cpp:17:26:17:32 | source1 | vector.cpp:17:21:17:33 | call to vector | TAINT | | vector.cpp:19:14:19:14 | (__begin) | vector.cpp:19:14:19:14 | call to operator* | TAINT | -| vector.cpp:19:14:19:14 | (__begin) | vector.cpp:19:14:19:14 | call to operator++ | TAINT | +| vector.cpp:19:14:19:14 | (__begin) | vector.cpp:19:14:19:14 | call to operator++ | | | vector.cpp:19:14:19:14 | (__end) | vector.cpp:19:14:19:14 | call to iterator | | | vector.cpp:19:14:19:14 | (__range) | vector.cpp:19:14:19:14 | call to begin | TAINT | | vector.cpp:19:14:19:14 | (__range) | vector.cpp:19:14:19:14 | call to end | TAINT | @@ -2624,13 +2637,13 @@ | vector.cpp:23:55:23:55 | ref arg v | vector.cpp:27:15:27:15 | v | | | vector.cpp:23:55:23:55 | ref arg v | vector.cpp:35:1:35:1 | v | | | vector.cpp:23:55:23:55 | v | vector.cpp:23:57:23:59 | call to end | TAINT | -| vector.cpp:23:66:23:67 | it | vector.cpp:23:64:23:64 | call to operator++ | TAINT | +| vector.cpp:23:66:23:67 | it | vector.cpp:23:64:23:64 | call to operator++ | | | vector.cpp:23:66:23:67 | ref arg it | vector.cpp:23:49:23:50 | it | | | vector.cpp:23:66:23:67 | ref arg it | vector.cpp:23:66:23:67 | it | | | vector.cpp:23:66:23:67 | ref arg it | vector.cpp:24:9:24:10 | it | | | vector.cpp:24:9:24:10 | it | vector.cpp:24:8:24:8 | call to operator* | TAINT | | vector.cpp:27:15:27:15 | (__begin) | vector.cpp:27:15:27:15 | call to operator* | TAINT | -| vector.cpp:27:15:27:15 | (__begin) | vector.cpp:27:15:27:15 | call to operator++ | TAINT | +| vector.cpp:27:15:27:15 | (__begin) | vector.cpp:27:15:27:15 | call to operator++ | | | vector.cpp:27:15:27:15 | (__end) | vector.cpp:27:15:27:15 | call to iterator | | | vector.cpp:27:15:27:15 | (__range) | vector.cpp:27:15:27:15 | call to begin | TAINT | | vector.cpp:27:15:27:15 | (__range) | vector.cpp:27:15:27:15 | call to end | TAINT | @@ -2650,7 +2663,7 @@ | vector.cpp:31:33:31:45 | call to vector | vector.cpp:35:1:35:1 | const_v | | | vector.cpp:31:38:31:44 | source1 | vector.cpp:31:33:31:45 | call to vector | TAINT | | vector.cpp:32:21:32:21 | (__begin) | vector.cpp:32:21:32:21 | call to operator* | TAINT | -| vector.cpp:32:21:32:21 | (__begin) | vector.cpp:32:21:32:21 | call to operator++ | TAINT | +| vector.cpp:32:21:32:21 | (__begin) | vector.cpp:32:21:32:21 | call to operator++ | | | vector.cpp:32:21:32:21 | (__range) | vector.cpp:32:21:32:21 | call to begin | TAINT | | vector.cpp:32:21:32:21 | (__range) | vector.cpp:32:21:32:21 | call to end | TAINT | | vector.cpp:32:21:32:21 | call to begin | vector.cpp:32:21:32:21 | (__begin) | | @@ -3331,7 +3344,7 @@ | vector.cpp:251:11:251:15 | call to begin | vector.cpp:253:8:253:9 | i1 | | | vector.cpp:251:11:251:15 | call to begin | vector.cpp:255:13:255:14 | i1 | | | vector.cpp:251:11:251:15 | call to begin | vector.cpp:259:8:259:9 | i1 | | -| vector.cpp:252:3:252:4 | i1 | vector.cpp:252:5:252:5 | call to operator++ | TAINT | +| vector.cpp:252:3:252:4 | i1 | vector.cpp:252:5:252:5 | call to operator++ | | | vector.cpp:252:3:252:4 | ref arg i1 | vector.cpp:253:8:253:9 | i1 | | | vector.cpp:252:3:252:4 | ref arg i1 | vector.cpp:255:13:255:14 | i1 | | | vector.cpp:252:3:252:4 | ref arg i1 | vector.cpp:259:8:259:9 | i1 | | @@ -3339,7 +3352,7 @@ | vector.cpp:253:8:253:9 | i1 | vector.cpp:254:3:254:4 | i2 | | | vector.cpp:253:8:253:9 | i1 | vector.cpp:255:17:255:18 | i2 | | | vector.cpp:253:8:253:9 | i1 | vector.cpp:260:8:260:9 | i2 | | -| vector.cpp:254:3:254:4 | i2 | vector.cpp:254:5:254:5 | call to operator++ | TAINT | +| vector.cpp:254:3:254:4 | i2 | vector.cpp:254:5:254:5 | call to operator++ | | | vector.cpp:254:3:254:4 | ref arg i2 | vector.cpp:255:17:255:18 | i2 | | | vector.cpp:254:3:254:4 | ref arg i2 | vector.cpp:260:8:260:9 | i2 | | | vector.cpp:255:3:255:4 | ref arg v6 | vector.cpp:261:8:261:9 | v6 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 408d185e3b47..4e8a7255feb4 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -171,9 +171,11 @@ | stringstream.cpp:52:7:52:9 | ss6 | stringstream.cpp:49:10:49:15 | call to source | | stringstream.cpp:53:7:53:9 | ss7 | stringstream.cpp:50:10:50:15 | call to source | | stringstream.cpp:56:11:56:13 | call to put | stringstream.cpp:56:15:56:29 | call to source | +| stringstream.cpp:57:44:57:46 | call to put | stringstream.cpp:57:25:57:39 | call to source | | stringstream.cpp:59:7:59:9 | ss9 | stringstream.cpp:56:15:56:29 | call to source | | stringstream.cpp:60:7:60:10 | ss10 | stringstream.cpp:57:25:57:39 | call to source | | stringstream.cpp:63:12:63:16 | call to write | stringstream.cpp:63:18:63:23 | call to source | +| stringstream.cpp:64:54:64:58 | call to write | stringstream.cpp:64:36:64:41 | call to source | | stringstream.cpp:66:7:66:10 | ss12 | stringstream.cpp:63:18:63:23 | call to source | | stringstream.cpp:67:7:67:10 | ss13 | stringstream.cpp:64:36:64:41 | call to source | | stringstream.cpp:76:11:76:11 | call to operator<< | stringstream.cpp:70:32:70:37 | source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index 0f4df62036d0..bc4213cb3dfb 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -187,9 +187,11 @@ | stringstream.cpp:52:7:52:9 | stringstream.cpp:49:10:49:15 | AST only | | stringstream.cpp:53:7:53:9 | stringstream.cpp:50:10:50:15 | AST only | | stringstream.cpp:56:11:56:13 | stringstream.cpp:56:15:56:29 | AST only | +| stringstream.cpp:57:44:57:46 | stringstream.cpp:57:25:57:39 | AST only | | stringstream.cpp:59:7:59:9 | stringstream.cpp:56:15:56:29 | AST only | | stringstream.cpp:60:7:60:10 | stringstream.cpp:57:25:57:39 | AST only | | stringstream.cpp:63:12:63:16 | stringstream.cpp:63:18:63:23 | AST only | +| stringstream.cpp:64:54:64:58 | stringstream.cpp:64:36:64:41 | AST only | | stringstream.cpp:66:7:66:10 | stringstream.cpp:63:18:63:23 | AST only | | stringstream.cpp:67:7:67:10 | stringstream.cpp:64:36:64:41 | AST only | | stringstream.cpp:76:11:76:11 | stringstream.cpp:70:32:70:37 | AST only |