Skip to content

Commit 56390c1

Browse files
committed
C++: Flow through operator>>.
1 parent 5079deb commit 56390c1

File tree

6 files changed

+123
-12
lines changed

6 files changed

+123
-12
lines changed

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

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,63 @@ class StdStringAt extends TaintFunction {
288288
}
289289
}
290290

291+
/**
292+
* The `std::basic_istream` template class.
293+
*/
294+
class StdBasicIStream extends TemplateClass {
295+
StdBasicIStream() { this.hasQualifiedName("std", "basic_istream") }
296+
}
297+
298+
/**
299+
* The `std::istream` function `operator>>` (defined as a member function).
300+
*/
301+
class StdIStreamIn extends DataFlowFunction, TaintFunction {
302+
StdIStreamIn() { this.hasQualifiedName("std", "basic_istream", "operator>>") }
303+
304+
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
305+
// flow from qualifier to return value
306+
input.isQualifierObject() and
307+
output.isReturnValue()
308+
}
309+
310+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
311+
// flow from qualifier to first parameter
312+
input.isQualifierObject() and
313+
output.isParameterDeref(0)
314+
or
315+
// reverse flow from returned reference to the qualifier
316+
input.isReturnValueDeref() and
317+
output.isQualifierObject()
318+
}
319+
}
320+
321+
/**
322+
* The `std::istream` function `operator>>` (defined as a non-member function).
323+
*/
324+
class StdIStreamInNonMember extends DataFlowFunction, TaintFunction {
325+
StdIStreamInNonMember() {
326+
this.hasQualifiedName("std", "operator>>") and
327+
this.getUnspecifiedType().(ReferenceType).getBaseType() =
328+
any(StdBasicIStream s).getAnInstantiation()
329+
}
330+
331+
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
332+
// flow from first parameter to return value
333+
input.isParameter(0) and
334+
output.isReturnValue()
335+
}
336+
337+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
338+
// flow from first parameter to second parameter
339+
input.isParameterDeref(0) and
340+
output.isParameterDeref(1)
341+
or
342+
// reverse flow from returned reference to the first parameter
343+
input.isReturnValueDeref() and
344+
output.isParameterDeref(0)
345+
}
346+
}
347+
291348
/**
292349
* The `std::basic_ostream` template class.
293350
*/

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,9 +1568,13 @@
15681568
| stringstream.cpp:76:14:76:19 | source | stringstream.cpp:76:11:76:11 | call to operator<< | TAINT |
15691569
| stringstream.cpp:77:7:77:9 | ref arg ss1 | stringstream.cpp:80:7:80:9 | ss1 | |
15701570
| stringstream.cpp:77:7:77:9 | ref arg ss1 | stringstream.cpp:82:7:82:9 | ss1 | |
1571+
| stringstream.cpp:77:7:77:9 | ss1 | stringstream.cpp:77:11:77:11 | call to operator>> | |
1572+
| stringstream.cpp:77:7:77:9 | ss1 | stringstream.cpp:77:14:77:15 | ref arg v1 | TAINT |
15711573
| stringstream.cpp:77:14:77:15 | ref arg v1 | stringstream.cpp:84:7:84:8 | v1 | |
15721574
| stringstream.cpp:78:7:78:9 | ref arg ss2 | stringstream.cpp:81:7:81:9 | ss2 | |
15731575
| stringstream.cpp:78:7:78:9 | ref arg ss2 | stringstream.cpp:83:7:83:9 | ss2 | |
1576+
| stringstream.cpp:78:7:78:9 | ss2 | stringstream.cpp:78:11:78:11 | call to operator>> | |
1577+
| stringstream.cpp:78:7:78:9 | ss2 | stringstream.cpp:78:14:78:15 | ref arg v2 | TAINT |
15741578
| stringstream.cpp:78:14:78:15 | ref arg v2 | stringstream.cpp:85:7:85:8 | v2 | |
15751579
| stringstream.cpp:82:7:82:9 | ss1 | stringstream.cpp:82:11:82:13 | call to str | TAINT |
15761580
| stringstream.cpp:83:7:83:9 | ss2 | stringstream.cpp:83:11:83:13 | call to str | TAINT |
@@ -1715,6 +1719,8 @@
17151719
| stringstream.cpp:145:7:145:9 | ref arg ss1 | stringstream.cpp:174:12:174:14 | ss1 | |
17161720
| stringstream.cpp:145:7:145:9 | ref arg ss1 | stringstream.cpp:176:12:176:14 | ss1 | |
17171721
| stringstream.cpp:145:7:145:9 | ref arg ss1 | stringstream.cpp:178:7:178:9 | ss1 | |
1722+
| stringstream.cpp:145:7:145:9 | ss1 | stringstream.cpp:145:11:145:11 | call to operator>> | |
1723+
| stringstream.cpp:145:7:145:9 | ss1 | stringstream.cpp:145:14:145:15 | ref arg s1 | TAINT |
17181724
| stringstream.cpp:145:14:145:15 | ref arg s1 | stringstream.cpp:148:7:148:8 | s1 | |
17191725
| stringstream.cpp:146:7:146:9 | ref arg ss2 | stringstream.cpp:147:7:147:9 | ss2 | |
17201726
| stringstream.cpp:146:7:146:9 | ref arg ss2 | stringstream.cpp:154:7:154:9 | ss2 | |
@@ -1725,6 +1731,8 @@
17251731
| stringstream.cpp:146:7:146:9 | ref arg ss2 | stringstream.cpp:175:12:175:14 | ss2 | |
17261732
| stringstream.cpp:146:7:146:9 | ref arg ss2 | stringstream.cpp:177:12:177:14 | ss2 | |
17271733
| stringstream.cpp:146:7:146:9 | ref arg ss2 | stringstream.cpp:179:7:179:9 | ss2 | |
1734+
| stringstream.cpp:146:7:146:9 | ss2 | stringstream.cpp:146:11:146:11 | call to operator>> | |
1735+
| stringstream.cpp:146:7:146:9 | ss2 | stringstream.cpp:146:14:146:15 | ref arg s2 | TAINT |
17281736
| stringstream.cpp:146:14:146:15 | ref arg s2 | stringstream.cpp:149:7:149:8 | s2 | |
17291737
| stringstream.cpp:147:7:147:9 | ref arg ss2 | stringstream.cpp:154:7:154:9 | ss2 | |
17301738
| stringstream.cpp:147:7:147:9 | ref arg ss2 | stringstream.cpp:155:7:155:9 | ss2 | |
@@ -1734,6 +1742,11 @@
17341742
| stringstream.cpp:147:7:147:9 | ref arg ss2 | stringstream.cpp:175:12:175:14 | ss2 | |
17351743
| stringstream.cpp:147:7:147:9 | ref arg ss2 | stringstream.cpp:177:12:177:14 | ss2 | |
17361744
| stringstream.cpp:147:7:147:9 | ref arg ss2 | stringstream.cpp:179:7:179:9 | ss2 | |
1745+
| stringstream.cpp:147:7:147:9 | ss2 | stringstream.cpp:147:11:147:11 | call to operator>> | |
1746+
| stringstream.cpp:147:7:147:9 | ss2 | stringstream.cpp:147:14:147:15 | ref arg s3 | TAINT |
1747+
| stringstream.cpp:147:11:147:11 | call to operator>> | stringstream.cpp:147:17:147:17 | call to operator>> | |
1748+
| stringstream.cpp:147:11:147:11 | call to operator>> | stringstream.cpp:147:20:147:21 | ref arg s4 | TAINT |
1749+
| stringstream.cpp:147:11:147:11 | ref arg call to operator>> | stringstream.cpp:147:7:147:9 | ref arg ss2 | TAINT |
17371750
| stringstream.cpp:147:14:147:15 | ref arg s3 | stringstream.cpp:150:7:150:8 | s3 | |
17381751
| stringstream.cpp:147:20:147:21 | ref arg s4 | stringstream.cpp:151:7:151:8 | s4 | |
17391752
| stringstream.cpp:153:7:153:9 | ref arg ss1 | stringstream.cpp:161:7:161:9 | ss1 | |
@@ -1742,6 +1755,8 @@
17421755
| stringstream.cpp:153:7:153:9 | ref arg ss1 | stringstream.cpp:174:12:174:14 | ss1 | |
17431756
| stringstream.cpp:153:7:153:9 | ref arg ss1 | stringstream.cpp:176:12:176:14 | ss1 | |
17441757
| stringstream.cpp:153:7:153:9 | ref arg ss1 | stringstream.cpp:178:7:178:9 | ss1 | |
1758+
| stringstream.cpp:153:7:153:9 | ss1 | stringstream.cpp:153:11:153:11 | call to operator>> | |
1759+
| stringstream.cpp:153:7:153:9 | ss1 | stringstream.cpp:153:14:153:15 | ref arg b1 | TAINT |
17451760
| stringstream.cpp:153:14:153:15 | ref arg b1 | stringstream.cpp:156:7:156:8 | b1 | |
17461761
| stringstream.cpp:154:7:154:9 | ref arg ss2 | stringstream.cpp:155:7:155:9 | ss2 | |
17471762
| stringstream.cpp:154:7:154:9 | ref arg ss2 | stringstream.cpp:162:7:162:9 | ss2 | |
@@ -1750,13 +1765,20 @@
17501765
| stringstream.cpp:154:7:154:9 | ref arg ss2 | stringstream.cpp:175:12:175:14 | ss2 | |
17511766
| stringstream.cpp:154:7:154:9 | ref arg ss2 | stringstream.cpp:177:12:177:14 | ss2 | |
17521767
| stringstream.cpp:154:7:154:9 | ref arg ss2 | stringstream.cpp:179:7:179:9 | ss2 | |
1768+
| stringstream.cpp:154:7:154:9 | ss2 | stringstream.cpp:154:11:154:11 | call to operator>> | |
1769+
| stringstream.cpp:154:7:154:9 | ss2 | stringstream.cpp:154:14:154:15 | ref arg b2 | TAINT |
17531770
| stringstream.cpp:154:14:154:15 | ref arg b2 | stringstream.cpp:157:7:157:8 | b2 | |
17541771
| stringstream.cpp:155:7:155:9 | ref arg ss2 | stringstream.cpp:162:7:162:9 | ss2 | |
17551772
| stringstream.cpp:155:7:155:9 | ref arg ss2 | stringstream.cpp:164:7:164:9 | ss2 | |
17561773
| stringstream.cpp:155:7:155:9 | ref arg ss2 | stringstream.cpp:166:7:166:9 | ss2 | |
17571774
| stringstream.cpp:155:7:155:9 | ref arg ss2 | stringstream.cpp:175:12:175:14 | ss2 | |
17581775
| stringstream.cpp:155:7:155:9 | ref arg ss2 | stringstream.cpp:177:12:177:14 | ss2 | |
17591776
| stringstream.cpp:155:7:155:9 | ref arg ss2 | stringstream.cpp:179:7:179:9 | ss2 | |
1777+
| stringstream.cpp:155:7:155:9 | ss2 | stringstream.cpp:155:11:155:11 | call to operator>> | |
1778+
| stringstream.cpp:155:7:155:9 | ss2 | stringstream.cpp:155:14:155:15 | ref arg b3 | TAINT |
1779+
| stringstream.cpp:155:11:155:11 | call to operator>> | stringstream.cpp:155:17:155:17 | call to operator>> | |
1780+
| stringstream.cpp:155:11:155:11 | call to operator>> | stringstream.cpp:155:20:155:21 | ref arg b4 | TAINT |
1781+
| stringstream.cpp:155:11:155:11 | ref arg call to operator>> | stringstream.cpp:155:7:155:9 | ref arg ss2 | TAINT |
17601782
| stringstream.cpp:155:14:155:15 | ref arg b3 | stringstream.cpp:158:7:158:8 | b3 | |
17611783
| stringstream.cpp:155:20:155:21 | ref arg b4 | stringstream.cpp:159:7:159:8 | b4 | |
17621784
| stringstream.cpp:156:7:156:8 | b1 | stringstream.cpp:156:7:156:8 | call to basic_string | TAINT |

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,14 @@ void test_stringstream_int(int source)
7575
sink(ss1 << 1234);
7676
sink(ss2 << source); // tainted
7777
sink(ss1 >> v1);
78-
sink(ss2 >> v2); // tainted [NOT DETECTED]
78+
sink(ss2 >> v2); // tainted
7979

8080
sink(ss1);
8181
sink(ss2); // tainted
8282
sink(ss1.str());
8383
sink(ss2.str()); // tainted
8484
sink(v1);
85-
sink(v2); // tainted [NOT DETECTED]
85+
sink(v2); // tainted
8686
}
8787

8888
void test_stringstream_constructors()
@@ -143,20 +143,20 @@ void test_stringstream_in()
143143
sink(ss2 << source()); // tainted
144144

145145
sink(ss1 >> s1);
146-
sink(ss2 >> s2); // tainted [NOT DETECTED]
147-
sink(ss2 >> s3 >> s4); // tainted [NOT DETECTED]
146+
sink(ss2 >> s2); // tainted
147+
sink(ss2 >> s3 >> s4); // tainted
148148
sink(s1);
149-
sink(s2); // tainted [NOT DETECTED]
150-
sink(s3); // tainted [NOT DETECTED]
151-
sink(s4); // tainted [NOT DETECTED]
149+
sink(s2); // tainted
150+
sink(s3); // tainted
151+
sink(s4); // tainted
152152

153153
sink(ss1 >> b1);
154-
sink(ss2 >> b2);
155-
sink(ss2 >> b3 >> b4);
154+
sink(ss2 >> b2); // tainted
155+
sink(ss2 >> b3 >> b4); // tainted
156156
sink(b1);
157-
sink(b2); // tainted [NOT DETECTED]
158-
sink(b3); // tainted [NOT DETECTED]
159-
sink(b4); // tainted [NOT DETECTED]
157+
sink(b2); // tainted
158+
sink(b3); // tainted
159+
sink(b4); // tainted
160160

161161
sink(ss1.read(b5, 100));
162162
sink(ss2.read(b6, 100)); // tainted [NOT DETECTED]

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,15 +188,27 @@
188188
| stringstream.cpp:66:7:66:10 | ss12 | stringstream.cpp:63:18:63:23 | call to source |
189189
| stringstream.cpp:67:7:67:10 | ss13 | stringstream.cpp:64:36:64:41 | call to source |
190190
| stringstream.cpp:76:11:76:11 | call to operator<< | stringstream.cpp:70:32:70:37 | source |
191+
| stringstream.cpp:78:11:78:11 | call to operator>> | stringstream.cpp:70:32:70:37 | source |
191192
| stringstream.cpp:81:7:81:9 | ss2 | stringstream.cpp:70:32:70:37 | source |
192193
| stringstream.cpp:83:11:83:13 | call to str | stringstream.cpp:70:32:70:37 | source |
194+
| stringstream.cpp:85:7:85:8 | v2 | stringstream.cpp:70:32:70:37 | source |
193195
| stringstream.cpp:100:11:100:11 | call to operator= | stringstream.cpp:100:31:100:36 | call to source |
194196
| stringstream.cpp:103:7:103:9 | ss2 | stringstream.cpp:91:19:91:24 | call to source |
195197
| stringstream.cpp:105:7:105:9 | ss4 | stringstream.cpp:95:44:95:49 | call to source |
196198
| stringstream.cpp:107:7:107:9 | ss6 | stringstream.cpp:100:31:100:36 | call to source |
197199
| stringstream.cpp:121:7:121:9 | ss2 | stringstream.cpp:113:24:113:29 | call to source |
198200
| stringstream.cpp:123:7:123:9 | ss4 | stringstream.cpp:115:24:115:29 | call to source |
199201
| stringstream.cpp:143:11:143:11 | call to operator<< | stringstream.cpp:143:14:143:19 | call to source |
202+
| stringstream.cpp:146:11:146:11 | call to operator>> | stringstream.cpp:143:14:143:19 | call to source |
203+
| stringstream.cpp:147:17:147:17 | call to operator>> | stringstream.cpp:143:14:143:19 | call to source |
204+
| stringstream.cpp:149:7:149:8 | s2 | stringstream.cpp:143:14:143:19 | call to source |
205+
| stringstream.cpp:150:7:150:8 | s3 | stringstream.cpp:143:14:143:19 | call to source |
206+
| stringstream.cpp:151:7:151:8 | s4 | stringstream.cpp:143:14:143:19 | call to source |
207+
| stringstream.cpp:154:11:154:11 | call to operator>> | stringstream.cpp:143:14:143:19 | call to source |
208+
| stringstream.cpp:155:17:155:17 | call to operator>> | stringstream.cpp:143:14:143:19 | call to source |
209+
| stringstream.cpp:157:7:157:8 | call to basic_string | stringstream.cpp:143:14:143:19 | call to source |
210+
| stringstream.cpp:158:7:158:8 | call to basic_string | stringstream.cpp:143:14:143:19 | call to source |
211+
| stringstream.cpp:159:7:159:8 | call to basic_string | stringstream.cpp:143:14:143:19 | call to source |
200212
| structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source |
201213
| structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source |
202214
| 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: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,10 @@
188188
| stringstream.cpp:66:7:66:10 | stringstream.cpp:63:18:63:23 | AST only |
189189
| stringstream.cpp:67:7:67:10 | stringstream.cpp:64:36:64:41 | AST only |
190190
| stringstream.cpp:76:11:76:11 | stringstream.cpp:70:32:70:37 | AST only |
191+
| stringstream.cpp:78:11:78:11 | stringstream.cpp:70:32:70:37 | AST only |
191192
| stringstream.cpp:81:7:81:9 | stringstream.cpp:70:32:70:37 | AST only |
192193
| stringstream.cpp:83:11:83:13 | stringstream.cpp:70:32:70:37 | AST only |
194+
| stringstream.cpp:85:7:85:8 | stringstream.cpp:70:32:70:37 | AST only |
193195
| stringstream.cpp:100:11:100:11 | stringstream.cpp:100:31:100:36 | AST only |
194196
| stringstream.cpp:103:7:103:9 | stringstream.cpp:91:19:91:24 | AST only |
195197
| stringstream.cpp:105:7:105:9 | stringstream.cpp:95:44:95:49 | AST only |
@@ -199,6 +201,16 @@
199201
| stringstream.cpp:143:11:143:11 | stringstream.cpp:143:14:143:21 | IR only |
200202
| stringstream.cpp:143:11:143:22 | stringstream.cpp:143:14:143:19 | IR only |
201203
| stringstream.cpp:143:11:143:22 | stringstream.cpp:143:14:143:21 | IR only |
204+
| stringstream.cpp:146:11:146:11 | stringstream.cpp:143:14:143:19 | AST only |
205+
| stringstream.cpp:147:17:147:17 | stringstream.cpp:143:14:143:19 | AST only |
206+
| stringstream.cpp:149:7:149:8 | stringstream.cpp:143:14:143:19 | AST only |
207+
| stringstream.cpp:150:7:150:8 | stringstream.cpp:143:14:143:19 | AST only |
208+
| stringstream.cpp:151:7:151:8 | stringstream.cpp:143:14:143:19 | AST only |
209+
| stringstream.cpp:154:11:154:11 | stringstream.cpp:143:14:143:19 | AST only |
210+
| stringstream.cpp:155:17:155:17 | stringstream.cpp:143:14:143:19 | AST only |
211+
| stringstream.cpp:157:7:157:8 | stringstream.cpp:143:14:143:21 | IR only |
212+
| stringstream.cpp:158:7:158:8 | stringstream.cpp:143:14:143:21 | IR only |
213+
| stringstream.cpp:159:7:159:8 | stringstream.cpp:143:14:143:19 | AST only |
202214
| swap1.cpp:78:12:78:16 | swap1.cpp:69:23:69:23 | AST only |
203215
| swap1.cpp:87:13:87:17 | swap1.cpp:82:16:82:21 | AST only |
204216
| swap1.cpp:88:13:88:17 | swap1.cpp:81:27:81:28 | AST only |

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@
7070
| stringstream.cpp:143:11:143:22 | (reference dereference) | stringstream.cpp:143:14:143:21 | (const char *)... |
7171
| stringstream.cpp:143:11:143:22 | (reference to) | stringstream.cpp:143:14:143:19 | call to source |
7272
| stringstream.cpp:143:11:143:22 | (reference to) | stringstream.cpp:143:14:143:21 | (const char *)... |
73+
| stringstream.cpp:157:7:157:8 | (reference to) | stringstream.cpp:143:14:143:19 | call to source |
74+
| stringstream.cpp:157:7:157:8 | (reference to) | stringstream.cpp:143:14:143:21 | (const char *)... |
75+
| stringstream.cpp:157:7:157:8 | call to basic_string | stringstream.cpp:143:14:143:19 | call to source |
76+
| stringstream.cpp:157:7:157:8 | call to basic_string | stringstream.cpp:143:14:143:21 | (const char *)... |
77+
| stringstream.cpp:158:7:158:8 | (reference to) | stringstream.cpp:143:14:143:19 | call to source |
78+
| stringstream.cpp:158:7:158:8 | (reference to) | stringstream.cpp:143:14:143:21 | (const char *)... |
79+
| stringstream.cpp:158:7:158:8 | call to basic_string | stringstream.cpp:143:14:143:19 | call to source |
80+
| stringstream.cpp:158:7:158:8 | call to basic_string | stringstream.cpp:143:14:143:21 | (const char *)... |
7381
| structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source |
7482
| structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source |
7583
| structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source |

0 commit comments

Comments
 (0)