From 2f192f6a0c1fffb7097916caec26f3280aeae782 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 11 Jun 2020 16:49:06 +0100 Subject: [PATCH 1/2] C++: Add a test of char* -> std::string -> char* taint. --- .../dataflow/taint-tests/localTaint.expected | 11 ++++++++ .../dataflow/taint-tests/stl.cpp | 25 +++++++++++++++++++ .../dataflow/taint-tests/taint.expected | 4 +++ .../dataflow/taint-tests/test_diff.expected | 4 +++ .../dataflow/taint-tests/test_ir.expected | 2 ++ 5 files changed, 46 insertions(+) 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 48d96a5c2c22..0a19ab081c1f 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -188,6 +188,17 @@ | stl.cpp:131:15:131:24 | call to user_input | stl.cpp:131:15:131:27 | call to basic_string | TAINT | | stl.cpp:131:15:131:27 | call to basic_string | stl.cpp:132:7:132:11 | path3 | | | stl.cpp:132:7:132:11 | path3 | stl.cpp:132:13:132:17 | call to c_str | TAINT | +| stl.cpp:137:19:137:24 | call to source | stl.cpp:140:17:140:18 | cs | | +| stl.cpp:137:19:137:24 | call to source | stl.cpp:142:7:142:8 | cs | | +| stl.cpp:140:17:140:18 | cs | stl.cpp:140:17:140:19 | call to basic_string | TAINT | +| stl.cpp:140:17:140:19 | call to basic_string | stl.cpp:143:7:143:8 | ss | | +| stl.cpp:148:19:148:24 | call to source | stl.cpp:151:17:151:18 | cs | | +| stl.cpp:151:17:151:18 | cs | stl.cpp:151:17:151:19 | call to basic_string | TAINT | +| stl.cpp:151:17:151:19 | call to basic_string | stl.cpp:154:7:154:8 | ss | | +| stl.cpp:151:17:151:19 | call to basic_string | stl.cpp:157:7:157:8 | ss | | +| stl.cpp:154:7:154:8 | ss | stl.cpp:154:10:154:14 | call to c_str | TAINT | +| stl.cpp:154:10:154:14 | call to c_str | stl.cpp:154:2:154:16 | ... = ... | | +| stl.cpp:154:10:154:14 | call to c_str | stl.cpp:156:7:156:8 | cs | | | taint.cpp:4:27:4:33 | source1 | taint.cpp:6:13:6:19 | source1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:5:8:5:13 | clean1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:6:3:6:8 | clean1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index d92bb39d1584..95eeeaf43987 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -131,3 +131,28 @@ void test_strings2() string path3(user_input()); sink(path3.c_str(), "r"); // tainted } + +void test_string3() +{ + const char *cs = source(); + + // convert char * -> std::string + std::string ss(cs); + + sink(cs); // tainted + sink(ss); // tainted +} + +void test_string4() +{ + const char *cs = source(); + + // convert char * -> std::string + std::string ss(cs); + + // convert back std::string -> char * + cs = ss.c_str(); + + sink(cs); // tainted + sink(ss); // 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 312a46e979e9..07d5b5bbdcf4 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -16,6 +16,10 @@ | stl.cpp:125:13:125:17 | call to c_str | stl.cpp:117:10:117:15 | call to source | | stl.cpp:129:13:129:17 | call to c_str | stl.cpp:117:10:117:15 | call to source | | stl.cpp:132:13:132:17 | call to c_str | stl.cpp:117:10:117:15 | call to source | +| stl.cpp:142:7:142:8 | cs | stl.cpp:137:19:137:24 | call to source | +| stl.cpp:143:7:143:8 | ss | stl.cpp:137:19:137:24 | call to source | +| stl.cpp:156:7:156:8 | cs | stl.cpp:148:19:148:24 | call to source | +| stl.cpp:157:7:157:8 | ss | stl.cpp:148:19:148:24 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | 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 0426082e01bf..d3c7a1307e61 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 @@ -13,6 +13,10 @@ | stl.cpp:125:13:125:17 | stl.cpp:117:10:117:15 | AST only | | stl.cpp:129:13:129:17 | stl.cpp:117:10:117:15 | AST only | | stl.cpp:132:13:132:17 | stl.cpp:117:10:117:15 | AST only | +| stl.cpp:142:7:142:8 | stl.cpp:137:19:137:26 | IR only | +| stl.cpp:143:7:143:8 | stl.cpp:137:19:137:24 | AST only | +| stl.cpp:156:7:156:8 | stl.cpp:148:19:148:24 | AST only | +| stl.cpp:157:7:157:8 | stl.cpp:148:19:148:24 | AST only | | taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected index bb52de0d7c51..644ce743dd1c 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected @@ -3,6 +3,8 @@ | format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source | | stl.cpp:71:7:71:7 | (const char *)... | stl.cpp:67:12:67:17 | call to source | | stl.cpp:71:7:71:7 | a | stl.cpp:67:12:67:17 | call to source | +| stl.cpp:142:7:142:8 | cs | stl.cpp:137:19:137:24 | call to source | +| stl.cpp:142:7:142:8 | cs | stl.cpp:137:19:137:26 | (const char *)... | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source | From 40c20f27311a0ddafd9c1d0597cd6859006e8ba9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 11 Jun 2020 17:32:44 +0100 Subject: [PATCH 2/2] C++: Add the test for DefaultTaintTracking as well. --- .../dataflow/DefaultTaintTracking/stl.cpp | 159 ++++++++++++++++++ .../DefaultTaintTracking/tainted.expected | 44 +++++ .../DefaultTaintTracking/test_diff.expected | 14 ++ 3 files changed, 217 insertions(+) create mode 100644 cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/stl.cpp diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/stl.cpp b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/stl.cpp new file mode 100644 index 000000000000..3786e31a9ee6 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/stl.cpp @@ -0,0 +1,159 @@ + +#include "shared.h" + +typedef unsigned long size_t; + +namespace std +{ + template struct char_traits; + + typedef size_t streamsize; + + template class allocator { + public: + allocator() throw(); + }; + + template, class Allocator = allocator > + class basic_string { + public: + explicit basic_string(const Allocator& a = Allocator()); + basic_string(const charT* s, const Allocator& a = Allocator()); + + const charT* c_str() const; + }; + + typedef basic_string string; + + template > + class basic_istream /*: virtual public basic_ios - not needed for this test */ { + public: + basic_istream& operator>>(int& n); + }; + + template > + class basic_ostream /*: virtual public basic_ios - not needed for this test */ { + public: + typedef charT char_type; + basic_ostream& write(const char_type* s, streamsize n); + + basic_ostream& operator<<(int n); + }; + + template basic_ostream& operator<<(basic_ostream&, const charT*); + template basic_ostream& operator<<(basic_ostream& os, const basic_string& str); + + template> + class basic_iostream : public basic_istream, public basic_ostream { + public: + }; + + template, class Allocator = allocator> + class basic_stringstream : public basic_iostream { + public: + explicit basic_stringstream(/*ios_base::openmode which = ios_base::out|ios_base::in - not needed for this test*/); + + basic_string str() const; + }; + + using stringstream = basic_stringstream; +} + +char *source() { return getenv("USERDATA"); } +void sink(const std::string &s) {}; +void sink(const std::stringstream &s) {}; + +void test_string() +{ + char *a = source(); + std::string b("123"); + std::string c(source()); + + sink(a); // tainted + sink(b); + sink(c); // tainted [NOT DETECTED] + sink(b.c_str()); + sink(c.c_str()); // tainted [NOT DETECTED] +} + +void test_stringstream() +{ + std::stringstream ss1, ss2, ss3, ss4, ss5; + std::string t(source()); + + ss1 << "1234"; + ss2 << source(); + ss3 << "123" << source(); + ss4 << source() << "456"; + ss5 << t; + + sink(ss1); + sink(ss2); // tainted [NOT DETECTED] + sink(ss3); // tainted [NOT DETECTED] + sink(ss4); // tainted [NOT DETECTED] + sink(ss5); // tainted [NOT DETECTED] + 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] +} + +void test_stringstream_int(int source) +{ + std::stringstream ss1, ss2; + + ss1 << 1234; + ss2 << source; + + sink(ss1); + sink(ss2); // tainted [NOT DETECTED] + sink(ss1.str()); + sink(ss2.str()); // tainted [NOT DETECTED] +} + +using namespace std; + +char *user_input() { + return source(); +} + +void sink(const char *filename, const char *mode); + +void test_strings2() +{ + string path1 = user_input(); + sink(path1.c_str(), "r"); // tainted [NOT DETECTED] + + string path2; + path2 = user_input(); + sink(path2.c_str(), "r"); // tainted + + string path3(user_input()); + sink(path3.c_str(), "r"); // tainted [NOT DETECTED] +} + +void test_string3() +{ + const char *cs = source(); + + // convert char * -> std::string + std::string ss(cs); + + sink(cs); // tainted + sink(ss); // tainted [NOT DETECTED] +} + +void test_string4() +{ + const char *cs = source(); + + // convert char * -> std::string + std::string ss(cs); + + // convert back std::string -> char * + cs = ss.c_str(); + + sink(cs); // tainted [NOT DETECTED] + sink(ss); // tainted [NOT DETECTED] +} diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected index 4a87761da6fa..e0c97fb5270e 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected @@ -153,6 +153,50 @@ | globals.cpp:13:15:13:20 | call to getenv | globals.cpp:13:15:13:20 | call to getenv | | globals.cpp:23:15:23:20 | call to getenv | globals.cpp:16:15:16:21 | global2 | | globals.cpp:23:15:23:20 | call to getenv | globals.cpp:23:15:23:20 | call to getenv | +| stl.cpp:62:25:62:30 | call to getenv | shared.h:5:23:5:31 | sinkparam | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:21:29:21:29 | s | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:43:114:43:118 | p#1 | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:62:25:62:30 | call to getenv | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:68:8:68:8 | a | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:68:12:68:17 | call to source | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:70:16:70:21 | call to source | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:70:16:70:23 | (const char *)... | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:70:16:70:24 | call to basic_string | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:72:7:72:7 | (const char *)... | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:72:7:72:7 | a | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:82:16:82:21 | call to source | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:82:16:82:23 | (const char *)... | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:82:16:82:24 | call to basic_string | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:85:9:85:14 | call to source | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:85:9:85:16 | (const char *)... | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:86:18:86:23 | call to source | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:86:18:86:25 | (const char *)... | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:9:87:14 | call to source | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:9:87:16 | (const char *)... | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:118:10:118:15 | call to source | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:125:16:125:28 | call to basic_string | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:125:17:125:26 | call to user_input | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:125:17:125:28 | (const char *)... | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:128:9:128:13 | path2 | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:129:10:129:19 | call to user_input | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:129:10:129:21 | (const char *)... | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:129:10:129:21 | call to basic_string | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:130:7:130:11 | (const basic_string, allocator>)... | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:130:7:130:11 | path2 | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:132:15:132:24 | call to user_input | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:132:15:132:26 | (const char *)... | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:132:15:132:27 | call to basic_string | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:138:14:138:15 | cs | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:138:19:138:24 | call to source | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:138:19:138:26 | (const char *)... | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:141:17:141:18 | cs | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:141:17:141:19 | call to basic_string | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:143:7:143:8 | cs | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:149:14:149:15 | cs | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:149:19:149:24 | call to source | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:149:19:149:26 | (const char *)... | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:152:17:152:18 | cs | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:152:17:152:19 | call to basic_string | | test_diff.cpp:92:10:92:13 | argv | shared.h:5:23:5:31 | sinkparam | | test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:92:10:92:13 | argv | | test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:92:10:92:16 | (const char *)... | diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/test_diff.expected b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/test_diff.expected index 79b02cd9d608..2864260e017e 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/test_diff.expected @@ -31,6 +31,20 @@ | defaulttainttracking.cpp:140:11:140:16 | call to getenv | defaulttainttracking.cpp:150:13:150:14 | & ... | IR only | | globals.cpp:13:15:13:20 | call to getenv | globals.cpp:13:5:13:11 | global1 | AST only | | globals.cpp:23:15:23:20 | call to getenv | globals.cpp:23:5:23:11 | global2 | AST only | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:62:7:62:12 | source | AST only | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:70:16:70:24 | call to basic_string | IR only | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:82:16:82:24 | call to basic_string | IR only | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:9:87:16 | (const char *)... | IR only | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:117:7:117:16 | user_input | AST only | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:125:16:125:28 | call to basic_string | IR only | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:128:9:128:13 | path2 | IR only | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:129:10:129:21 | call to basic_string | IR only | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:130:7:130:11 | (const basic_string, allocator>)... | IR only | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:130:7:130:11 | path2 | IR only | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:132:15:132:27 | call to basic_string | IR only | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:141:17:141:19 | call to basic_string | IR only | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:152:17:152:19 | call to basic_string | IR only | +| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:157:7:157:8 | cs | AST only | | test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:11:104:20 | (...) | IR only | | test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:36:24:36:24 | p | AST only | | test_diff.cpp:111:10:111:13 | argv | shared.h:5:23:5:31 | sinkparam | AST only |