Skip to content

Commit 81d8dc1

Browse files
authored
Merge pull request github#3693 from geoffw0/stringtest
C++: Add tests of char* -> std::string -> char* conversions.
2 parents 573d55a + 35487ff commit 81d8dc1

File tree

8 files changed

+263
-0
lines changed

8 files changed

+263
-0
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
2+
#include "shared.h"
3+
4+
typedef unsigned long size_t;
5+
6+
namespace std
7+
{
8+
template<class charT> struct char_traits;
9+
10+
typedef size_t streamsize;
11+
12+
template <class T> class allocator {
13+
public:
14+
allocator() throw();
15+
};
16+
17+
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
18+
class basic_string {
19+
public:
20+
explicit basic_string(const Allocator& a = Allocator());
21+
basic_string(const charT* s, const Allocator& a = Allocator());
22+
23+
const charT* c_str() const;
24+
};
25+
26+
typedef basic_string<char> string;
27+
28+
template <class charT, class traits = char_traits<charT> >
29+
class basic_istream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
30+
public:
31+
basic_istream<charT,traits>& operator>>(int& n);
32+
};
33+
34+
template <class charT, class traits = char_traits<charT> >
35+
class basic_ostream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
36+
public:
37+
typedef charT char_type;
38+
basic_ostream<charT,traits>& write(const char_type* s, streamsize n);
39+
40+
basic_ostream<charT, traits>& operator<<(int n);
41+
};
42+
43+
template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
44+
template<class charT, class traits, class Allocator> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const basic_string<charT, traits, Allocator>& str);
45+
46+
template<class charT, class traits = char_traits<charT>>
47+
class basic_iostream : public basic_istream<charT, traits>, public basic_ostream<charT, traits> {
48+
public:
49+
};
50+
51+
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
52+
class basic_stringstream : public basic_iostream<charT, traits> {
53+
public:
54+
explicit basic_stringstream(/*ios_base::openmode which = ios_base::out|ios_base::in - not needed for this test*/);
55+
56+
basic_string<charT, traits, Allocator> str() const;
57+
};
58+
59+
using stringstream = basic_stringstream<char>;
60+
}
61+
62+
char *source() { return getenv("USERDATA"); }
63+
void sink(const std::string &s) {};
64+
void sink(const std::stringstream &s) {};
65+
66+
void test_string()
67+
{
68+
char *a = source();
69+
std::string b("123");
70+
std::string c(source());
71+
72+
sink(a); // tainted
73+
sink(b);
74+
sink(c); // tainted [NOT DETECTED]
75+
sink(b.c_str());
76+
sink(c.c_str()); // tainted [NOT DETECTED]
77+
}
78+
79+
void test_stringstream()
80+
{
81+
std::stringstream ss1, ss2, ss3, ss4, ss5;
82+
std::string t(source());
83+
84+
ss1 << "1234";
85+
ss2 << source();
86+
ss3 << "123" << source();
87+
ss4 << source() << "456";
88+
ss5 << t;
89+
90+
sink(ss1);
91+
sink(ss2); // tainted [NOT DETECTED]
92+
sink(ss3); // tainted [NOT DETECTED]
93+
sink(ss4); // tainted [NOT DETECTED]
94+
sink(ss5); // tainted [NOT DETECTED]
95+
sink(ss1.str());
96+
sink(ss2.str()); // tainted [NOT DETECTED]
97+
sink(ss3.str()); // tainted [NOT DETECTED]
98+
sink(ss4.str()); // tainted [NOT DETECTED]
99+
sink(ss5.str()); // tainted [NOT DETECTED]
100+
}
101+
102+
void test_stringstream_int(int source)
103+
{
104+
std::stringstream ss1, ss2;
105+
106+
ss1 << 1234;
107+
ss2 << source;
108+
109+
sink(ss1);
110+
sink(ss2); // tainted [NOT DETECTED]
111+
sink(ss1.str());
112+
sink(ss2.str()); // tainted [NOT DETECTED]
113+
}
114+
115+
using namespace std;
116+
117+
char *user_input() {
118+
return source();
119+
}
120+
121+
void sink(const char *filename, const char *mode);
122+
123+
void test_strings2()
124+
{
125+
string path1 = user_input();
126+
sink(path1.c_str(), "r"); // tainted [NOT DETECTED]
127+
128+
string path2;
129+
path2 = user_input();
130+
sink(path2.c_str(), "r"); // tainted
131+
132+
string path3(user_input());
133+
sink(path3.c_str(), "r"); // tainted [NOT DETECTED]
134+
}
135+
136+
void test_string3()
137+
{
138+
const char *cs = source();
139+
140+
// convert char * -> std::string
141+
std::string ss(cs);
142+
143+
sink(cs); // tainted
144+
sink(ss); // tainted [NOT DETECTED]
145+
}
146+
147+
void test_string4()
148+
{
149+
const char *cs = source();
150+
151+
// convert char * -> std::string
152+
std::string ss(cs);
153+
154+
// convert back std::string -> char *
155+
cs = ss.c_str();
156+
157+
sink(cs); // tainted [NOT DETECTED]
158+
sink(ss); // tainted [NOT DETECTED]
159+
}

cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,50 @@
153153
| globals.cpp:13:15:13:20 | call to getenv | globals.cpp:13:15:13:20 | call to getenv |
154154
| globals.cpp:23:15:23:20 | call to getenv | globals.cpp:16:15:16:21 | global2 |
155155
| globals.cpp:23:15:23:20 | call to getenv | globals.cpp:23:15:23:20 | call to getenv |
156+
| stl.cpp:62:25:62:30 | call to getenv | shared.h:5:23:5:31 | sinkparam |
157+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:21:29:21:29 | s |
158+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:43:114:43:118 | p#1 |
159+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:62:25:62:30 | call to getenv |
160+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:68:8:68:8 | a |
161+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:68:12:68:17 | call to source |
162+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:70:16:70:21 | call to source |
163+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:70:16:70:23 | (const char *)... |
164+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:70:16:70:24 | call to basic_string |
165+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:72:7:72:7 | (const char *)... |
166+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:72:7:72:7 | a |
167+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:82:16:82:21 | call to source |
168+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:82:16:82:23 | (const char *)... |
169+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:82:16:82:24 | call to basic_string |
170+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:85:9:85:14 | call to source |
171+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:85:9:85:16 | (const char *)... |
172+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:86:18:86:23 | call to source |
173+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:86:18:86:25 | (const char *)... |
174+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:9:87:14 | call to source |
175+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:9:87:16 | (const char *)... |
176+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:118:10:118:15 | call to source |
177+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:125:16:125:28 | call to basic_string |
178+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:125:17:125:26 | call to user_input |
179+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:125:17:125:28 | (const char *)... |
180+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:128:9:128:13 | path2 |
181+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:129:10:129:19 | call to user_input |
182+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:129:10:129:21 | (const char *)... |
183+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:129:10:129:21 | call to basic_string |
184+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:130:7:130:11 | (const basic_string<char, char_traits<char>, allocator<char>>)... |
185+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:130:7:130:11 | path2 |
186+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:132:15:132:24 | call to user_input |
187+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:132:15:132:26 | (const char *)... |
188+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:132:15:132:27 | call to basic_string |
189+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:138:14:138:15 | cs |
190+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:138:19:138:24 | call to source |
191+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:138:19:138:26 | (const char *)... |
192+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:141:17:141:18 | cs |
193+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:141:17:141:19 | call to basic_string |
194+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:143:7:143:8 | cs |
195+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:149:14:149:15 | cs |
196+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:149:19:149:24 | call to source |
197+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:149:19:149:26 | (const char *)... |
198+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:152:17:152:18 | cs |
199+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:152:17:152:19 | call to basic_string |
156200
| test_diff.cpp:92:10:92:13 | argv | shared.h:5:23:5:31 | sinkparam |
157201
| test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:92:10:92:13 | argv |
158202
| test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:92:10:92:16 | (const char *)... |

cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/test_diff.expected

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,20 @@
3131
| defaulttainttracking.cpp:140:11:140:16 | call to getenv | defaulttainttracking.cpp:150:13:150:14 | & ... | IR only |
3232
| globals.cpp:13:15:13:20 | call to getenv | globals.cpp:13:5:13:11 | global1 | AST only |
3333
| globals.cpp:23:15:23:20 | call to getenv | globals.cpp:23:5:23:11 | global2 | AST only |
34+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:62:7:62:12 | source | AST only |
35+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:70:16:70:24 | call to basic_string | IR only |
36+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:82:16:82:24 | call to basic_string | IR only |
37+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:9:87:16 | (const char *)... | IR only |
38+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:117:7:117:16 | user_input | AST only |
39+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:125:16:125:28 | call to basic_string | IR only |
40+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:128:9:128:13 | path2 | IR only |
41+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:129:10:129:21 | call to basic_string | IR only |
42+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:130:7:130:11 | (const basic_string<char, char_traits<char>, allocator<char>>)... | IR only |
43+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:130:7:130:11 | path2 | IR only |
44+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:132:15:132:27 | call to basic_string | IR only |
45+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:141:17:141:19 | call to basic_string | IR only |
46+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:152:17:152:19 | call to basic_string | IR only |
47+
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:157:7:157:8 | cs | AST only |
3448
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:11:104:20 | (...) | IR only |
3549
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:36:24:36:24 | p | AST only |
3650
| test_diff.cpp:111:10:111:13 | argv | shared.h:5:23:5:31 | sinkparam | AST only |

cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,17 @@
188188
| stl.cpp:131:15:131:24 | call to user_input | stl.cpp:131:15:131:27 | call to basic_string | TAINT |
189189
| stl.cpp:131:15:131:27 | call to basic_string | stl.cpp:132:7:132:11 | path3 | |
190190
| stl.cpp:132:7:132:11 | path3 | stl.cpp:132:13:132:17 | call to c_str | TAINT |
191+
| stl.cpp:137:19:137:24 | call to source | stl.cpp:140:17:140:18 | cs | |
192+
| stl.cpp:137:19:137:24 | call to source | stl.cpp:142:7:142:8 | cs | |
193+
| stl.cpp:140:17:140:18 | cs | stl.cpp:140:17:140:19 | call to basic_string | TAINT |
194+
| stl.cpp:140:17:140:19 | call to basic_string | stl.cpp:143:7:143:8 | ss | |
195+
| stl.cpp:148:19:148:24 | call to source | stl.cpp:151:17:151:18 | cs | |
196+
| stl.cpp:151:17:151:18 | cs | stl.cpp:151:17:151:19 | call to basic_string | TAINT |
197+
| stl.cpp:151:17:151:19 | call to basic_string | stl.cpp:154:7:154:8 | ss | |
198+
| stl.cpp:151:17:151:19 | call to basic_string | stl.cpp:157:7:157:8 | ss | |
199+
| stl.cpp:154:7:154:8 | ss | stl.cpp:154:10:154:14 | call to c_str | TAINT |
200+
| stl.cpp:154:10:154:14 | call to c_str | stl.cpp:154:2:154:16 | ... = ... | |
201+
| stl.cpp:154:10:154:14 | call to c_str | stl.cpp:156:7:156:8 | cs | |
191202
| swap1.cpp:14:17:14:17 | t | swap1.cpp:14:17:14:17 | t | |
192203
| swap1.cpp:14:17:14:17 | t | swap1.cpp:14:17:14:17 | t | |
193204
| swap1.cpp:14:17:14:17 | t | swap1.cpp:14:56:14:56 | t | |

cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,28 @@ void test_strings2()
131131
string path3(user_input());
132132
sink(path3.c_str(), "r"); // tainted
133133
}
134+
135+
void test_string3()
136+
{
137+
const char *cs = source();
138+
139+
// convert char * -> std::string
140+
std::string ss(cs);
141+
142+
sink(cs); // tainted
143+
sink(ss); // tainted
144+
}
145+
146+
void test_string4()
147+
{
148+
const char *cs = source();
149+
150+
// convert char * -> std::string
151+
std::string ss(cs);
152+
153+
// convert back std::string -> char *
154+
cs = ss.c_str();
155+
156+
sink(cs); // tainted
157+
sink(ss); // tainted
158+
}

cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
| stl.cpp:125:13:125:17 | call to c_str | stl.cpp:117:10:117:15 | call to source |
1717
| stl.cpp:129:13:129:17 | call to c_str | stl.cpp:117:10:117:15 | call to source |
1818
| stl.cpp:132:13:132:17 | call to c_str | stl.cpp:117:10:117:15 | call to source |
19+
| stl.cpp:142:7:142:8 | cs | stl.cpp:137:19:137:24 | call to source |
20+
| stl.cpp:143:7:143:8 | ss | stl.cpp:137:19:137:24 | call to source |
21+
| stl.cpp:156:7:156:8 | cs | stl.cpp:148:19:148:24 | call to source |
22+
| stl.cpp:157:7:157:8 | ss | stl.cpp:148:19:148:24 | call to source |
1923
| swap1.cpp:60:12:60:16 | data1 | swap1.cpp:58:15:58:20 | call to source |
2024
| swap1.cpp:65:12:65:16 | data1 | swap1.cpp:58:15:58:20 | call to source |
2125
| swap1.cpp:66:12:66:16 | data1 | swap1.cpp:58:15:58:20 | call to source |

cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
| stl.cpp:125:13:125:17 | stl.cpp:117:10:117:15 | AST only |
1414
| stl.cpp:129:13:129:17 | stl.cpp:117:10:117:15 | AST only |
1515
| stl.cpp:132:13:132:17 | stl.cpp:117:10:117:15 | AST only |
16+
| stl.cpp:142:7:142:8 | stl.cpp:137:19:137:26 | IR only |
17+
| stl.cpp:143:7:143:8 | stl.cpp:137:19:137:24 | AST only |
18+
| stl.cpp:156:7:156:8 | stl.cpp:148:19:148:24 | AST only |
19+
| stl.cpp:157:7:157:8 | stl.cpp:148:19:148:24 | AST only |
1620
| swap1.cpp:74:13:74:17 | swap1.cpp:69:16:69:21 | AST only |
1721
| swap1.cpp:75:13:75:17 | swap1.cpp:68:27:68:28 | AST only |
1822
| swap1.cpp:89:12:89:16 | swap1.cpp:80:23:80:23 | AST only |

cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
| format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source |
44
| stl.cpp:71:7:71:7 | (const char *)... | stl.cpp:67:12:67:17 | call to source |
55
| stl.cpp:71:7:71:7 | a | stl.cpp:67:12:67:17 | call to source |
6+
| stl.cpp:142:7:142:8 | cs | stl.cpp:137:19:137:24 | call to source |
7+
| stl.cpp:142:7:142:8 | cs | stl.cpp:137:19:137:26 | (const char *)... |
68
| swap1.cpp:60:12:60:16 | data1 | swap1.cpp:58:15:58:20 | call to source |
79
| swap1.cpp:65:12:65:16 | data1 | swap1.cpp:58:15:58:20 | call to source |
810
| swap1.cpp:66:12:66:16 | data1 | swap1.cpp:58:15:58:20 | call to source |

0 commit comments

Comments
 (0)