Skip to content

Commit b1c0e6f

Browse files
committed
Merge remote-tracking branch 'upstream/main' into SimpleRangeAnalysis-mul-constant
2 parents 01a226b + a457d54 commit b1c0e6f

File tree

23 files changed

+598
-53
lines changed

23 files changed

+598
-53
lines changed

change-notes/1.26/analysis-cpp.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ The following changes in version 1.26 affect C/C++ analysis in all applications.
1919

2020
## Changes to libraries
2121

22-
* The models library now models more taint flows through `std::string`.
22+
* The models library now models many more taint flows through `std::string`.
2323
* The `SimpleRangeAnalysis` library now supports multiplications of the form
2424
`e1 * e2` and `x *= e2` when `e1` and `e2` are unsigned or constant.

cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ class StdBasicString extends TemplateClass {
88
}
99

1010
/**
11-
* The standard function `std::string.c_str`.
11+
* The `std::string` functions `c_str` and `data`.
1212
*/
1313
class StdStringCStr extends TaintFunction {
14-
StdStringCStr() { this.hasQualifiedName("std", "basic_string", "c_str") }
14+
StdStringCStr() {
15+
this.hasQualifiedName("std", "basic_string", "c_str") or
16+
this.hasQualifiedName("std", "basic_string", "data")
17+
}
1518

1619
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
1720
// flow from string itself (qualifier) to return value
@@ -40,12 +43,16 @@ class StdStringPlus extends TaintFunction {
4043
}
4144

4245
/**
43-
* The `std::string` functions `operator+=` and `append`.
46+
* The `std::string` functions `operator+=`, `append`, `insert` and
47+
* `replace`. All of these functions combine the existing string
48+
* with a new string (or character) from one of the arguments.
4449
*/
4550
class StdStringAppend extends TaintFunction {
4651
StdStringAppend() {
4752
this.hasQualifiedName("std", "basic_string", "operator+=") or
48-
this.hasQualifiedName("std", "basic_string", "append")
53+
this.hasQualifiedName("std", "basic_string", "append") or
54+
this.hasQualifiedName("std", "basic_string", "insert") or
55+
this.hasQualifiedName("std", "basic_string", "replace")
4956
}
5057

5158
/**
@@ -58,6 +65,35 @@ class StdStringAppend extends TaintFunction {
5865
getParameter(result).getType() = getDeclaringType().getTemplateArgument(0) // i.e. `std::basic_string::CharT`
5966
}
6067

68+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
69+
// flow from string and parameter to string (qualifier) and return value
70+
(
71+
input.isQualifierObject() or
72+
input.isParameterDeref(getAStringParameter())
73+
) and
74+
(
75+
output.isQualifierObject() or
76+
output.isReturnValueDeref()
77+
)
78+
}
79+
}
80+
81+
/**
82+
* The standard function `std::string.assign`.
83+
*/
84+
class StdStringAssign extends TaintFunction {
85+
StdStringAssign() { this.hasQualifiedName("std", "basic_string", "assign") }
86+
87+
/**
88+
* Gets the index of a parameter to this function that is a string (or
89+
* character).
90+
*/
91+
int getAStringParameter() {
92+
getParameter(result).getType() instanceof PointerType or
93+
getParameter(result).getType() instanceof ReferenceType or
94+
getParameter(result).getType() = getDeclaringType().getTemplateArgument(0) // i.e. `std::basic_string::CharT`
95+
}
96+
6197
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
6298
// flow from parameter to string itself (qualifier) and return value
6399
input.isParameterDeref(getAStringParameter()) and
@@ -67,3 +103,45 @@ class StdStringAppend extends TaintFunction {
67103
)
68104
}
69105
}
106+
107+
/**
108+
* The standard function `std::string.copy`.
109+
*/
110+
class StdStringCopy extends TaintFunction {
111+
StdStringCopy() { this.hasQualifiedName("std", "basic_string", "copy") }
112+
113+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
114+
// copy(dest, num, pos)
115+
input.isQualifierObject() and
116+
output.isParameterDeref(0)
117+
}
118+
}
119+
120+
/**
121+
* The standard function `std::string.substr`.
122+
*/
123+
class StdStringSubstr extends TaintFunction {
124+
StdStringSubstr() { this.hasQualifiedName("std", "basic_string", "substr") }
125+
126+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
127+
// substr(pos, num)
128+
input.isQualifierObject() and
129+
output.isReturnValue()
130+
}
131+
}
132+
133+
/**
134+
* The standard function `std::string.swap`.
135+
*/
136+
class StdStringSwap extends TaintFunction {
137+
StdStringSwap() { this.hasQualifiedName("std", "basic_string", "swap") }
138+
139+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
140+
// str1.swap(str2)
141+
input.isQualifierObject() and
142+
output.isParameterDeref(0)
143+
or
144+
input.isParameterDeref(0) and
145+
output.isQualifierObject()
146+
}
147+
}

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

Lines changed: 183 additions & 0 deletions
Large diffs are not rendered by default.

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,14 @@ namespace std
3939
class basic_string {
4040
public:
4141
typedef typename Allocator::size_type size_type;
42+
static const size_type npos = -1;
4243

4344
explicit basic_string(const Allocator& a = Allocator());
4445
basic_string(const charT* s, const Allocator& a = Allocator());
4546

4647
const charT* c_str() const;
48+
charT* data() noexcept;
49+
size_t length() const;
4750

4851
typedef std::iterator<random_access_iterator_tag, charT> iterator;
4952
typedef std::iterator<random_access_iterator_tag, const charT> const_iterator;
@@ -60,6 +63,16 @@ namespace std
6063
basic_string& append(const basic_string& str);
6164
basic_string& append(const charT* s);
6265
basic_string& append(size_type n, charT c);
66+
basic_string& assign(const basic_string& str);
67+
basic_string& assign(size_type n, charT c);
68+
basic_string& insert(size_type pos, const basic_string& str);
69+
basic_string& insert(size_type pos, size_type n, charT c);
70+
basic_string& replace(size_type pos1, size_type n1, const basic_string& str);
71+
basic_string& replace(size_type pos1, size_type n1, size_type n2, charT c);
72+
size_type copy(charT* s, size_type n, size_type pos = 0) const;
73+
void clear() noexcept;
74+
basic_string substr(size_type pos = 0, size_type n = npos) const;
75+
void swap(basic_string& s) noexcept/*(allocator_traits<Allocator>::propagate_on_container_swap::value || allocator_traits<Allocator>::is_always_equal::value)*/;
6376
};
6477

6578
template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs);

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

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,140 @@ void test_string_append() {
184184
sink(s10); // tainted
185185
}
186186
}
187+
188+
void test_string_assign() {
189+
std::string s1("hello");
190+
std::string s2(source());
191+
char c = ns_char::source();
192+
std::string s3, s4, s5;
193+
std::string s6(source());
194+
195+
sink(s3.assign(s1));
196+
sink(s3);
197+
198+
sink(s4.assign(s2)); // tainted
199+
sink(s4); // tainted
200+
201+
sink(s5.assign(10, c)); // tainted
202+
sink(s5); // tainted
203+
204+
sink(s6.assign(s1));
205+
sink(s6); // [FALSE POSITIVE]
206+
}
207+
208+
void test_string_insert() {
209+
std::string s1("hello");
210+
std::string s2(source());
211+
char c = ns_char::source();
212+
std::string s3, s4, s5, s6;
213+
214+
s3 = s1;
215+
sink(s3.insert(0, s1));
216+
sink(s3);
217+
218+
s4 = s2;
219+
sink(s4.insert(0, s1)); // tainted
220+
sink(s4); // tainted
221+
222+
s5 = s1;
223+
sink(s5.insert(0, s2)); // tainted
224+
sink(s5); // tainted
225+
226+
s6 = s1;
227+
sink(s6.insert(0, 10, c)); // tainted
228+
sink(s6); // tainted
229+
}
230+
231+
void test_string_replace() {
232+
std::string s1("hello");
233+
std::string s2(source());
234+
char c = ns_char::source();
235+
std::string s3, s4, s5, s6;
236+
237+
s3 = s1;
238+
sink(s3.replace(1, 2, s1));
239+
sink(s3);
240+
241+
s4 = s2;
242+
sink(s4.replace(1, 2, s1)); // tainted
243+
sink(s4); // tainted
244+
245+
s5 = s1;
246+
sink(s5.replace(1, 2, s2)); // tainted
247+
sink(s5); // tainted
248+
249+
s6 = s1;
250+
sink(s6.replace(1, 2, 10, c)); // tainted
251+
sink(s6); // tainted
252+
}
253+
254+
void test_string_copy() {
255+
char b1[1024] = {0};
256+
char b2[1024] = {0};
257+
std::string s1("hello");
258+
std::string s2(source());
259+
260+
s1.copy(b1, s1.length(), 0);
261+
sink(b1);
262+
263+
s2.copy(b2, s1.length(), 0);
264+
sink(b2); // tainted
265+
}
266+
267+
void test_string_swap() {
268+
std::string s1("hello");
269+
std::string s2(source());
270+
std::string s3("world");
271+
std::string s4(source());
272+
273+
sink(s1);
274+
sink(s2); // tainted
275+
sink(s3);
276+
sink(s4); // tainted
277+
278+
s1.swap(s2);
279+
s4.swap(s3);
280+
281+
sink(s1); // tainted
282+
sink(s2); // [FALSE POSITIVE]
283+
sink(s3); // tainted
284+
sink(s4); // [FALSE POSITIVE]
285+
}
286+
287+
void test_string_clear() {
288+
std::string s1(source());
289+
std::string s2(source());
290+
std::string s3(source());
291+
292+
sink(s1); // tainted
293+
sink(s2); // tainted
294+
sink(s3); // tainted
295+
296+
s1.clear();
297+
s2 = "";
298+
s3 = s3;
299+
300+
sink(s1); // [FALSE POSITIVE]
301+
sink(s2);
302+
sink(s3); // tainted
303+
}
304+
305+
void test_string_data()
306+
{
307+
std::string a("123");
308+
std::string b(source());
309+
310+
sink(a.data());
311+
sink(b.data()); // tainted
312+
sink(a.length());
313+
sink(b.length());
314+
}
315+
316+
void test_string_substr()
317+
{
318+
std::string a("123");
319+
std::string b(source());
320+
321+
sink(a.substr(0, a.length()));
322+
sink(b.substr(0, b.length())); // tainted
323+
}

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,37 @@
6060
| string.cpp:171:8:171:9 | s8 | string.cpp:154:18:154:23 | call to source |
6161
| string.cpp:176:8:176:9 | s9 | string.cpp:174:13:174:18 | call to source |
6262
| string.cpp:184:8:184:10 | s10 | string.cpp:181:12:181:26 | call to source |
63+
| string.cpp:198:10:198:15 | call to assign | string.cpp:190:17:190:22 | call to source |
64+
| string.cpp:199:7:199:8 | s4 | string.cpp:190:17:190:22 | call to source |
65+
| string.cpp:201:10:201:15 | call to assign | string.cpp:191:11:191:25 | call to source |
66+
| string.cpp:202:7:202:8 | s5 | string.cpp:191:11:191:25 | call to source |
67+
| string.cpp:205:7:205:8 | s6 | string.cpp:193:17:193:22 | call to source |
68+
| string.cpp:219:10:219:15 | call to insert | string.cpp:210:17:210:22 | call to source |
69+
| string.cpp:220:7:220:8 | s4 | string.cpp:210:17:210:22 | call to source |
70+
| string.cpp:223:10:223:15 | call to insert | string.cpp:210:17:210:22 | call to source |
71+
| string.cpp:224:7:224:8 | s5 | string.cpp:210:17:210:22 | call to source |
72+
| string.cpp:227:10:227:15 | call to insert | string.cpp:211:11:211:25 | call to source |
73+
| string.cpp:228:7:228:8 | s6 | string.cpp:211:11:211:25 | call to source |
74+
| string.cpp:242:10:242:16 | call to replace | string.cpp:233:17:233:22 | call to source |
75+
| string.cpp:243:7:243:8 | s4 | string.cpp:233:17:233:22 | call to source |
76+
| string.cpp:246:10:246:16 | call to replace | string.cpp:233:17:233:22 | call to source |
77+
| string.cpp:247:7:247:8 | s5 | string.cpp:233:17:233:22 | call to source |
78+
| string.cpp:250:10:250:16 | call to replace | string.cpp:234:11:234:25 | call to source |
79+
| string.cpp:251:7:251:8 | s6 | string.cpp:234:11:234:25 | call to source |
80+
| string.cpp:264:7:264:8 | b2 | string.cpp:258:17:258:22 | call to source |
81+
| string.cpp:274:7:274:8 | s2 | string.cpp:269:17:269:22 | call to source |
82+
| string.cpp:276:7:276:8 | s4 | string.cpp:271:17:271:22 | call to source |
83+
| string.cpp:281:7:281:8 | s1 | string.cpp:269:17:269:22 | call to source |
84+
| string.cpp:282:7:282:8 | s2 | string.cpp:269:17:269:22 | call to source |
85+
| string.cpp:283:7:283:8 | s3 | string.cpp:271:17:271:22 | call to source |
86+
| string.cpp:284:7:284:8 | s4 | string.cpp:271:17:271:22 | call to source |
87+
| string.cpp:292:7:292:8 | s1 | string.cpp:288:17:288:22 | call to source |
88+
| string.cpp:293:7:293:8 | s2 | string.cpp:289:17:289:22 | call to source |
89+
| string.cpp:294:7:294:8 | s3 | string.cpp:290:17:290:22 | call to source |
90+
| string.cpp:300:7:300:8 | s1 | string.cpp:288:17:288:22 | call to source |
91+
| string.cpp:302:7:302:8 | s3 | string.cpp:290:17:290:22 | call to source |
92+
| string.cpp:311:9:311:12 | call to data | string.cpp:308:16:308:21 | call to source |
93+
| string.cpp:322:9:322:14 | call to substr | string.cpp:319:16:319:21 | call to source |
6394
| structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source |
6495
| structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source |
6596
| structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source |

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,37 @@
5757
| string.cpp:171:8:171:9 | string.cpp:154:18:154:23 | AST only |
5858
| string.cpp:176:8:176:9 | string.cpp:174:13:174:18 | AST only |
5959
| string.cpp:184:8:184:10 | string.cpp:181:12:181:26 | AST only |
60+
| string.cpp:198:10:198:15 | string.cpp:190:17:190:22 | AST only |
61+
| string.cpp:199:7:199:8 | string.cpp:190:17:190:22 | AST only |
62+
| string.cpp:201:10:201:15 | string.cpp:191:11:191:25 | AST only |
63+
| string.cpp:202:7:202:8 | string.cpp:191:11:191:25 | AST only |
64+
| string.cpp:205:7:205:8 | string.cpp:193:17:193:22 | AST only |
65+
| string.cpp:219:10:219:15 | string.cpp:210:17:210:22 | AST only |
66+
| string.cpp:220:7:220:8 | string.cpp:210:17:210:22 | AST only |
67+
| string.cpp:223:10:223:15 | string.cpp:210:17:210:22 | AST only |
68+
| string.cpp:224:7:224:8 | string.cpp:210:17:210:22 | AST only |
69+
| string.cpp:227:10:227:15 | string.cpp:211:11:211:25 | AST only |
70+
| string.cpp:228:7:228:8 | string.cpp:211:11:211:25 | AST only |
71+
| string.cpp:242:10:242:16 | string.cpp:233:17:233:22 | AST only |
72+
| string.cpp:243:7:243:8 | string.cpp:233:17:233:22 | AST only |
73+
| string.cpp:246:10:246:16 | string.cpp:233:17:233:22 | AST only |
74+
| string.cpp:247:7:247:8 | string.cpp:233:17:233:22 | AST only |
75+
| string.cpp:250:10:250:16 | string.cpp:234:11:234:25 | AST only |
76+
| string.cpp:251:7:251:8 | string.cpp:234:11:234:25 | AST only |
77+
| string.cpp:264:7:264:8 | string.cpp:258:17:258:22 | AST only |
78+
| string.cpp:274:7:274:8 | string.cpp:269:17:269:22 | AST only |
79+
| string.cpp:276:7:276:8 | string.cpp:271:17:271:22 | AST only |
80+
| string.cpp:281:7:281:8 | string.cpp:269:17:269:22 | AST only |
81+
| string.cpp:282:7:282:8 | string.cpp:269:17:269:22 | AST only |
82+
| string.cpp:283:7:283:8 | string.cpp:271:17:271:22 | AST only |
83+
| string.cpp:284:7:284:8 | string.cpp:271:17:271:22 | AST only |
84+
| string.cpp:292:7:292:8 | string.cpp:288:17:288:22 | AST only |
85+
| string.cpp:293:7:293:8 | string.cpp:289:17:289:22 | AST only |
86+
| string.cpp:294:7:294:8 | string.cpp:290:17:290:22 | AST only |
87+
| string.cpp:300:7:300:8 | string.cpp:288:17:288:22 | AST only |
88+
| string.cpp:302:7:302:8 | string.cpp:290:17:290:22 | AST only |
89+
| string.cpp:311:9:311:12 | string.cpp:308:16:308:21 | AST only |
90+
| string.cpp:322:9:322:14 | string.cpp:319:16:319:21 | AST only |
6091
| structlikeclass.cpp:35:8:35:9 | structlikeclass.cpp:29:22:29:27 | AST only |
6192
| structlikeclass.cpp:36:8:36:9 | structlikeclass.cpp:30:24:30:29 | AST only |
6293
| structlikeclass.cpp:37:8:37:9 | structlikeclass.cpp:29:22:29:27 | AST only |

cpp/ql/test/library-tests/ir/ssa/ssa.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ struct A {
291291
Point *NewAliasing(int x) {
292292
Point* p = new Point;
293293
Point* q = new Point;
294-
int j = new A(new A(x))->i;
294+
int j = (new A(new A(x)))->i;
295295
A* a = new A;
296296
return p;
297297
}
@@ -310,4 +310,4 @@ class ThisAliasTest {
310310
void setX(int arg) {
311311
this->x = arg;
312312
}
313-
};
313+
};

0 commit comments

Comments
 (0)